From 982d385ea371e331f7d2285b2316d4ea160e7c89 Mon Sep 17 00:00:00 2001 From: Robin Jadoul Date: Fri, 20 Jan 2017 20:05:41 +0100 Subject: [PATCH] LR support for explicit rule precedences --- TODO | 2 +- include/Parsodus/grammar.h | 13 +++++++------ include/Parsodus/lrtables/generator.h | 21 ++++++--------------- 3 files changed, 14 insertions(+), 22 deletions(-) diff --git a/TODO b/TODO index f36df7e..597cefa 100644 --- a/TODO +++ b/TODO @@ -5,7 +5,7 @@ T> Parsodus regex parser in Lexesis -> Vrijgeven in libraryformaat: mogelijkheid verschillende tokens opvragen K> Parsodus Parsodus parser - -> Precedence + -> Precedence + fill precedence in rules -> rule naming (problem: multiple rules same name -> change in backend) -> grammar struct change to contain optional name per rule -> Volgorde belangrijk? diff --git a/include/Parsodus/grammar.h b/include/Parsodus/grammar.h index 8b58a3a..73b1a9f 100644 --- a/include/Parsodus/grammar.h +++ b/include/Parsodus/grammar.h @@ -11,6 +11,12 @@ #include namespace pds { + enum class PrecedenceType { + LEFT, + RIGHT, + NONASSOC + }; + /** * Represents a grammar rule * head -> tail[0] tail[1] ... tail[tail.size() - 1] @@ -19,6 +25,7 @@ namespace pds { std::string head; ///< The replaced variable std::vector tail; ///< The replacement rule const std::string name; ///< An optional name for this rule, if it's empty, there's no name + std::pair> precedence; ///< precedence for this rule, the bool indicates whether it's valid (invalid if there is no rightmost terminal and no explicit precedence) bool operator<(const Rule& other) const { if(head != other.head){ @@ -33,12 +40,6 @@ namespace pds { Rule(const std::string& h, const std::vector& t, const std::string& name) : head(h), tail(t), name(name) {} }; - enum class PrecedenceType { - LEFT, - RIGHT, - NONASSOC - }; - /** * A context free grammar * Keeps track of variables, terminals and replacement rules diff --git a/include/Parsodus/lrtables/generator.h b/include/Parsodus/lrtables/generator.h index d78f738..5fb0cd4 100644 --- a/include/Parsodus/lrtables/generator.h +++ b/include/Parsodus/lrtables/generator.h @@ -132,32 +132,23 @@ LRTable Generator::generate() { } else if (table.act[curIdx].count(term)) { if (table.act[curIdx][term].first == Action::SHIFT) { //Shift-Reduce conflict, rapport and resolve it (TODO) - std::string leftToken = ""; - for (std::size_t i = m_gram.rules[rule_applied]->tail.size(); i > 0; i--) { - std::string leftSym = m_gram.rules[rule_applied]->tail[i - 1]; - if (m_gram.terminals.count(leftSym)) { - leftToken = leftSym; - break; - } - } - bool handled = false; - auto leftTokenIt = m_gram.precedence.find(leftToken); auto rightTokenIt = m_gram.precedence.find(term); - if (leftTokenIt != m_gram.precedence.end() && rightTokenIt != m_gram.precedence.end()) { - if (leftTokenIt->second.first > rightTokenIt->second.first) { + if (m_gram.rules[rule_applied]->precedence.first && rightTokenIt != m_gram.precedence.end()) { + auto& leftPrec = m_gram.rules[rule_applied]->precedence.second; + if (leftPrec.first > rightTokenIt->second.first) { // Keep the shift handled = true; - } else if (leftTokenIt->second.first > rightTokenIt->second.first) { + } else if (leftPrec.first > rightTokenIt->second.first) { // replace with a reduce table.act[curIdx][term] = {Action::REDUCE, rule_applied}; handled = true; - } else if (leftTokenIt->second.second == PrecedenceType::LEFT) { + } else if (leftPrec.second == PrecedenceType::LEFT) { // replace with a reduce table.act[curIdx][term] = {Action::REDUCE, rule_applied}; handled = true; - } else if (leftTokenIt->second.second == PrecedenceType::RIGHT) { + } else if (leftPrec.second == PrecedenceType::RIGHT) { // Keep the shift handled = true; } //Nonassoc falls through