#pragma once #include "RegularCompiler.hpp" #include "RegularAutomata.hpp" #include "ContextFreeCompiler.hpp" #include "ContextFreeAutomata.hpp" namespace tp { template class Parser { typedef RegularGrammar RegularGrammar; typedef RegularCompiler RegularCompiler; typedef FiniteStateAutomation RegularGraph; typedef RegularAutomata RegularAutomata; // ContextFreeGrammar; // ContextFreeCompiler; typedef FiniteStateAutomation ContextFreeGraph; typedef ContextFreeAutomata ContextFreeAutomata; public: struct ParseResult { bool accepted = false; const ContextFreeAutomata::StackItem* ast = nullptr; }; public: Parser() = default; public: bool compileTables( const ContextFreeGrammar& cfGrammar, const RegularGrammar& reGrammar, const Map& contextFreeToRegular ) { // Compile Regular Grammar { RegularGraph graph; RegularCompiler compiler; compiler.compile(graph, reGrammar); graph.makeDeterministic(); mRegularAutomata.construct(graph); } // compile context free grammar { ContextFreeGraph graph; ContextFreeCompiler compiler; compiler.compile(cfGrammar, graph); graph.makeDeterministic(); mContextFreeAutomata.construct(graph); // make glue for (auto symbol : *compiler.getSymbols()) { auto symbolId = compiler.getSymbolId(symbol->mId); if (symbol->mIsTerminal) { auto iter = contextFreeToRegular.presents(symbol->mId); if (!iter) return false; mGrammarGlue.put(contextFreeToRegular.getSlotVal(iter), symbolId); } else { mAstNames.put(symbolId, symbol->mId); } } } return true; } ParseResult parse(const tAlphabetType* sentence, ualni sentenceLength) { // get tokens stream Buffer tokens; const tAlphabetType* sentenceIter = sentence; ualni lengthIter = sentenceLength; while (lengthIter) { auto result = mRegularAutomata.accept(sentenceIter, lengthIter); if (!result.accepted) { return { false, nullptr }; } tokens.append(ContextFreeCompiler::SymbolVal( mGrammarGlue.get(result.state), ualni(sentenceIter - sentence), result.advancedIdx )); sentenceIter += result.advancedIdx; lengthIter -= result.advancedIdx; } ContextFreeAutomata::AcceptResult result = mContextFreeAutomata.accept(tokens.getBuff(), tokens.size()); return { result.accepted, result.ast }; } public: // save load compiled tables RegularAutomata mRegularAutomata; ContextFreeAutomata mContextFreeAutomata; Map mGrammarGlue; Map mAstNames; }; }