diff options
-rw-r--r-- | minicc.cpp | 71 |
1 files changed, 21 insertions, 50 deletions
@@ -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; } |