Precedence resolution

This commit is contained in:
Robin Jadoul 2017-01-15 14:50:51 +01:00
parent 4dd9fc7aeb
commit 3d6ff5d44d
4 changed files with 50 additions and 9 deletions

11
TODO
View File

@ -1,6 +1,10 @@
-----------------------------------------------------------------------
- TODO -
-----------------------------------------------------------------------
T> Parser selection without enum (Thomas) (flexible matching (case insensitive, ...))
R> Precedence resolution in generator
R> Generated code error handler
T> Parsodus regex parser in Lexesis
-> Vrijgeven in libraryformaat: mogelijkheid verschillende tokens opvragen
K> Parsodus Parsodus parser
@ -36,3 +40,8 @@ R> man pages
-> write configuration sets, table
-> Generator: logging
-> driver/main: debug flag
-----------------------------------------------------------------------
- DONE -
-----------------------------------------------------------------------
R> Precedence resolution in generator

View File

@ -7,17 +7,10 @@
namespace pds {
enum class PrecedenceType {
LEFT,
RIGHT,
NONASSOC
};
struct Config {
util::ParserType parserType;
std::string lexesisFile;
Grammar grammar;
std::map<std::string, std::pair<int, PrecedenceType> > precedence; ///< lower value -> higher precedence
};
}

View File

@ -31,6 +31,12 @@ namespace pds {
Rule(const std::string& h, const std::vector<std::string>& t) : head(h), tail(t) {}
};
enum class PrecedenceType {
LEFT,
RIGHT,
NONASSOC
};
/**
* A context free grammar
* Keeps track of variables, terminals and replacement rules
@ -40,6 +46,7 @@ namespace pds {
std::set<std::string> variables; ///< the variables
std::set<std::string> terminals; ///< the terminals
std::vector<std::shared_ptr<Rule>> rules; ///< the replacement rules
std::map<std::string, std::pair<int, PrecedenceType> > precedence; ///< lower value -> higher precedence
std::unique_ptr<util::FirstSet> first;
std::unique_ptr<util::FollowSet> follow;

View File

@ -132,6 +132,38 @@ LRTable Generator<Itemset>::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) {
// Keep the shift
handled = true;
} else if (leftTokenIt->second.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) {
// replace with a reduce
table.act[curIdx][term] = {Action::REDUCE, rule_applied};
handled = true;
} else if (leftTokenIt->second.second == PrecedenceType::RIGHT) {
// Keep the shift
handled = true;
} //Nonassoc falls through
}
if (!handled)
throw std::runtime_error("shift-reduce");
} else if (table.act[curIdx][term].first == Action::REDUCE
&& table.act[curIdx][term].second != rule_applied) {