78 lines
2.6 KiB
C++
78 lines
2.6 KiB
C++
#include "ParsodusLexer.h"
|
|
#include "Parsodus/inputparser.h"
|
|
#include "Parsodus/parser.h"
|
|
#include "Parsodus/util/parserType.h"
|
|
#include "Lexesis/inputparser.h"
|
|
#include "g3log/g3log.hpp"
|
|
#include <set>
|
|
#include <fstream>
|
|
|
|
|
|
namespace pds {
|
|
|
|
InputParserException::InputParserException(std::string what): m_what(what) {}
|
|
const char* InputParserException::what() const throw() {
|
|
return m_what.c_str();
|
|
}
|
|
Config InputParser::parseInput(std::istream& is, std::string current_dir) {
|
|
ParsodusLexer lex(is);
|
|
Parser parser(lex);
|
|
|
|
Config cnf = *parser.parse();
|
|
if (!cnf.lexesisFile.empty()) {
|
|
std::fstream file(current_dir + cnf.lexesisFile);
|
|
auto terminals = lxs::input::InputParser::getTokens(file);
|
|
for(auto& terminal : terminals)
|
|
cnf.grammar.terminals.insert(terminal);
|
|
}
|
|
|
|
for(auto& rule : cnf.grammar.rules) {
|
|
for(auto& tail_piece : rule->tail) {
|
|
if (cnf.grammar.terminals.find(tail_piece) == cnf.grammar.terminals.end() &&
|
|
cnf.grammar.variables.find(tail_piece) == cnf.grammar.variables.end() && tail_piece != "error")
|
|
throw InputParserException("Found '" + tail_piece + "' in rule body, which is neither a variable nor a terminal.");
|
|
}
|
|
}
|
|
|
|
for(auto& rule : cnf.grammar.rules)
|
|
if (rule->head == "error")
|
|
throw InputParserException("Found <error> terminal in a head of a rule.");
|
|
|
|
|
|
bool found_token;
|
|
for(auto& term : cnf.grammar.terminals) {
|
|
found_token = false;
|
|
for(auto& rule : cnf.grammar.rules) {
|
|
for(auto& tail_value : rule->tail) {
|
|
if (tail_value == term) {
|
|
found_token = true;
|
|
break;
|
|
}
|
|
}
|
|
if (found_token) break;
|
|
}
|
|
if (!found_token)
|
|
LOG(WARNING) << "Terminal '" << term << "' is specified, but never used." << std::endl;
|
|
}
|
|
|
|
// Set precedence of each rule
|
|
for(std::shared_ptr<Rule>& rule : cnf.grammar.rules) {
|
|
if (rule->precedence.first) continue;
|
|
if (rule->tail.size() == 0)
|
|
rule->precedence = {false,{0,PrecedenceType::RIGHT}};
|
|
std::string rightmostTerm;
|
|
for (const std::string& term : rule->tail) {
|
|
if (cnf.grammar.terminals.count(term)) {
|
|
rightmostTerm = term;
|
|
}
|
|
}
|
|
auto prec = cnf.grammar.precedence.find(rightmostTerm);
|
|
if (prec != cnf.grammar.precedence.end())
|
|
rule->precedence = {true,prec->second};
|
|
else rule->precedence = {false,{0, PrecedenceType::RIGHT}};
|
|
}
|
|
|
|
return cnf;
|
|
}
|
|
}
|