summaryrefslogtreecommitdiffhomepage
path: root/minicc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'minicc.cpp')
-rw-r--r--minicc.cpp71
1 files changed, 21 insertions, 50 deletions
diff --git a/minicc.cpp b/minicc.cpp
index b392195..37fc974 100644
--- a/minicc.cpp
+++ b/minicc.cpp
@@ -62,6 +62,13 @@ private:
index_t last{};
public:
+ void clear() {
+ nodes.clear();
+ root = 0;
+ last = 0;
+ node_num = 0;
+ }
+
bool Valid(const std::string& Top) const {
// A token is non empty
if (node_num == 0)
@@ -298,38 +305,14 @@ private:
std::map<std::string, std::set<std::string>> ReverseBNF;
// to be called on token end
- void FinalizeCandidates(std::deque<Tree>& candidates, std::string& token, std::vector<std::string>& result)
+ void FinalizeTree(Tree& tree, std::string& token, std::vector<std::string>& result)
{
- if (candidates.empty()) { // skip
- if (!token.empty())
- throw std::runtime_error("Expected empty token, got "s + token);
- } else { // check candidates
- bool valid{false};
- for (auto& ct : candidates) {
- ct.Resolve(bnf, ReverseBNF);
- if (ct.Valid(Top)) {
- if (valid)
- throw std::runtime_error("Found ambiguous token "s + token);
- result.push_back(token);
- token.clear();
- valid = true;
- }
- }
- if (!valid)
- throw std::runtime_error("Invalid token: "s + token);
-
- candidates.clear();
- }
- }
-
- void AddCandidate(char c, std::deque<Tree>& candidates) {
- // new candidate: starting with c
- auto element {ReverseBNF.find(std::string(1, c))};
- if (element != ReverseBNF.end()) {
- Tree newTree;
- if (newTree.Add(c, bnf, ReverseBNF))
- candidates.push_back(newTree);
+ tree.Resolve(bnf, ReverseBNF);
+ if (tree.Valid(Top)) {
+ result.push_back(token);
+ token.clear();
}
+ tree.clear();
}
public:
@@ -343,39 +326,27 @@ public:
std::string token;
std::string Whitespace{"\t \n\r"};
- std::deque<Tree> candidates;
+ Tree tree;
for (size_t pos{0}; pos < s.size(); pos++) {
char c{s[pos]};
std::cout << "Char: |" << c << "|" << std::endl;
if (Whitespace.find(c) != std::string::npos) { // found whitespace character
// evaluate token up to now and skip whitespace
- FinalizeCandidates(candidates, token, result);
+ FinalizeTree(tree, token, result);
} else { // no whitespace: try to add to tree
- std::deque<index_t> EraseList;
- int i = 0;
- for (auto ct = candidates.begin(); ct != candidates.end(); ct++, i++) {
- if (!ct->Add(c, bnf, ReverseBNF)) { // either add char or delete candidate
- // push to front to get reversed order
- EraseList.push_front(i); // no candidate anymore
- }
- }
-
- if (token.empty()) {
- AddCandidate(c, candidates);
- } else if (candidates.size() - EraseList.size() > 0) { // added to some candidates: Erase invalidated ones
- for (const auto& i : EraseList)
- candidates.erase(candidates.begin() + i);
- } else { // no candidates left: new tree
- FinalizeCandidates(candidates, token, result);
- AddCandidate(c, candidates);
+ if (!tree.Add(c, bnf, ReverseBNF)) {
+ FinalizeTree(tree, token, result);
+ if (!tree.Add(c, bnf, ReverseBNF))
+ throw std::runtime_error("Parse error");
}
+
token.push_back(c);
}
}
// Final evaluation of last token
- FinalizeCandidates(candidates, token, result);
+ FinalizeTree(tree, token, result);
return result;
}