#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 #include 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 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 : 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; } }