parsing loop closed

This commit is contained in:
IlyaShurupov 2024-02-08 21:52:00 +03:00 committed by Ilusha
parent 63b0560375
commit 3bed74df87
8 changed files with 92 additions and 45 deletions

View file

@ -1,8 +0,0 @@
#pragma once
#include "LanguageCommon.hpp"
namespace tp {
class AST {};
}

View file

@ -37,7 +37,7 @@ namespace tp {
ualni advancedIdx = 0; ualni advancedIdx = 0;
while (advancedIdx < size) { while (advancedIdx < size) {
tAlphabetType& symbol = *(stream + advancedIdx); const tAlphabetType& symbol = *(stream + advancedIdx);
if (!(symbol >= mRange.mBegin && symbol < mRange.mEnd)) { if (!(symbol >= mRange.mBegin && symbol < mRange.mEnd)) {
return { false, advancedIdx, nullptr }; return { false, advancedIdx, nullptr };
@ -56,7 +56,7 @@ namespace tp {
} }
if (mTable.get({ 0, mCurrentState }).type == Action::REDUCE) { if (mTable.get({ 0, mCurrentState }).type == Action::REDUCE) {
StackItem* newItem = &mItems.append({}); StackItem* newItem = &mItems.append(StackItem{});
for (auto iter : Range<ualni>(action.num)) { for (auto iter : Range<ualni>(action.num)) {
newItem->leafs.append(mStack.last()); newItem->leafs.append(mStack.last());
mCurrentState = mStack.last()->state; mCurrentState = mStack.last()->state;

View file

@ -8,7 +8,7 @@ namespace tp {
class ContextFreeCompiler { class ContextFreeCompiler {
public: public:
typedef ualni SymbolID; typedef ualni SymbolId;
struct Item { struct Item {
const ContextFreeGrammar::Rule* mRule = nullptr; const ContextFreeGrammar::Rule* mRule = nullptr;
@ -16,12 +16,12 @@ namespace tp {
ualni numArgs() const { return 0; } ualni numArgs() const { return 0; }
}; };
private:
struct Symbol { struct Symbol {
String mId; String mId;
bool mIsTerminal = false; bool mIsTerminal = false;
}; };
private:
struct NonTerminal { struct NonTerminal {
Buffer<ContextFreeGrammar::Rule*> rules; Buffer<ContextFreeGrammar::Rule*> rules;
Map<String, NonTerminal*> references; Map<String, NonTerminal*> references;
@ -48,11 +48,14 @@ namespace tp {
}; };
public: public:
bool compile(const ContextFreeGrammar& grammar, FiniteStateAutomation<SymbolID, Item>& automata) { bool compile(const ContextFreeGrammar& grammar, FiniteStateAutomation<SymbolId, Item>& automata) {
if (!init(grammar)) return false; if (!init(grammar)) return false;
return true; return true;
} }
[[nodiscard]] const Buffer<Symbol>* getSymbols() const { return &mSymbols; }
[[nodiscard]] SymbolId getSymbolId(const String& name) const { return mSymbolLookup.get(name); }
private: private:
bool init(const ContextFreeGrammar& grammar) { bool init(const ContextFreeGrammar& grammar) {
@ -135,7 +138,7 @@ namespace tp {
void initSymbols(const ContextFreeGrammar& grammar) { void initSymbols(const ContextFreeGrammar& grammar) {
for (auto nonTerminal : mNonTerminals) { for (auto nonTerminal : mNonTerminals) {
mSymbols.append({ nonTerminal->key, false }); mSymbols.append({ nonTerminal->key, false });
mSymbolLookup.put(nonTerminal->key, SymbolID(mSymbols.size() - 1)); mSymbolLookup.put(nonTerminal->key, SymbolId(mSymbols.size() - 1));
for (auto rule : nonTerminal->val.rules) { for (auto rule : nonTerminal->val.rules) {
for (auto arg : *rule->getArgs()) { for (auto arg : *rule->getArgs()) {
@ -144,7 +147,7 @@ namespace tp {
mTerminals.put(arg->getId(), {}); mTerminals.put(arg->getId(), {});
mSymbols.append({ nonTerminal->key, true }); mSymbols.append({ nonTerminal->key, true });
mSymbolLookup.put(nonTerminal->key, SymbolID(mSymbols.size() - 1)); mSymbolLookup.put(nonTerminal->key, SymbolId(mSymbols.size() - 1));
} }
} }
} }
@ -154,6 +157,6 @@ namespace tp {
Map<String, NonTerminal> mNonTerminals; Map<String, NonTerminal> mNonTerminals;
Map<String, bool> mTerminals; Map<String, bool> mTerminals;
Buffer<Symbol> mSymbols; Buffer<Symbol> mSymbols;
Map<String, SymbolID> mSymbolLookup; Map<String, SymbolId> mSymbolLookup;
}; };
} }

View file

@ -1,8 +1,6 @@
#pragma once #pragma once
#include "AST.hpp"
#include "RegularCompiler.hpp" #include "RegularCompiler.hpp"
#include "RegularAutomata.hpp" #include "RegularAutomata.hpp"
@ -11,24 +9,34 @@
namespace tp { namespace tp {
template <typename tAlphabetType, typename TokenType, ualni MinSymbol, ualni MaxSymbol> template <typename tAlphabetType, typename tTokenType, tTokenType tInTransition, ualni MinSymbol, ualni MaxSymbol>
class Parser { class Parser {
typedef RegularGrammar<tAlphabetType, TokenType> RegularGrammar; typedef RegularGrammar<tAlphabetType, tTokenType> RegularGrammar;
typedef RegularCompiler<tAlphabetType, TokenType, MinSymbol, MaxSymbol> RegularCompiler; typedef RegularCompiler<tAlphabetType, tTokenType, tInTransition, MinSymbol, MaxSymbol> RegularCompiler;
typedef FiniteStateAutomation<tAlphabetType, TokenType> RegularGraph; typedef FiniteStateAutomation<tAlphabetType, tTokenType> RegularGraph;
typedef RegularAutomata<tAlphabetType, TokenType> RegularAutomata; typedef RegularAutomata<tAlphabetType, tTokenType> RegularAutomata;
// ContextFreeGrammar; // ContextFreeGrammar;
// ContextFreeCompiler; // ContextFreeCompiler;
typedef FiniteStateAutomation<ContextFreeCompiler::SymbolID, ContextFreeCompiler::Item> ContextFreeGraph; typedef FiniteStateAutomation<ContextFreeCompiler::SymbolId, ContextFreeCompiler::Item> ContextFreeGraph;
typedef ContextFreeAutomata<ContextFreeCompiler::SymbolID, ContextFreeCompiler::Item> ContextFreeAutomata; typedef ContextFreeAutomata<ContextFreeCompiler::SymbolId, ContextFreeCompiler::Item> ContextFreeAutomata;
public:
struct ParseResult {
bool accepted = false;
const ContextFreeAutomata::StackItem* ast = nullptr;
};
public: public:
Parser() = default; Parser() = default;
public: public:
bool compileTables(const ContextFreeGrammar& cfGrammar, const RegularGrammar& reGrammar) { bool compileTables(
const ContextFreeGrammar& cfGrammar,
const RegularGrammar& reGrammar,
const Map<String, tTokenType>& contextFreeToRegular
) {
// Compile Regular Grammar // Compile Regular Grammar
{ {
RegularGraph graph; RegularGraph graph;
@ -45,16 +53,53 @@ namespace tp {
compiler.compile(cfGrammar, graph); compiler.compile(cfGrammar, graph);
graph.makeDeterministic(); graph.makeDeterministic();
mContextFreeAutomata.construct(graph); 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; return true;
} }
void parse(const tAlphabetType* sentence, ualni sentenceLength, AST& out) {} ParseResult parse(const tAlphabetType* sentence, ualni sentenceLength) {
// get tokens stream
Buffer<ContextFreeCompiler::SymbolId> tokens;
const tAlphabetType* sentenceIter = sentence;
ualni lengthIter = sentenceLength;
while (lengthIter) {
auto result = mRegularAutomata.accept(sentenceIter, lengthIter);
if (!result.accepted) {
return { false, nullptr };
}
sentenceIter += result.advancedIdx;
lengthIter -= result.advancedIdx;
tokens.append(mGrammarGlue.get(result.state));
}
ContextFreeAutomata::AcceptResult result = mContextFreeAutomata.accept(tokens.getBuff(), tokens.size());
return { result.accepted, result.ast };
}
public: public:
// save load compiled tables // save load compiled tables
RegularAutomata mRegularAutomata; RegularAutomata mRegularAutomata;
ContextFreeAutomata mContextFreeAutomata; ContextFreeAutomata mContextFreeAutomata;
Map<tTokenType, ContextFreeCompiler::SymbolId> mGrammarGlue;
Map<ContextFreeCompiler::SymbolId, String> mAstNames;
}; };
} }

View file

@ -25,7 +25,7 @@ namespace tp {
ualni advancedIdx = 0; ualni advancedIdx = 0;
while (advancedIdx < size) { while (advancedIdx < size) {
tAlphabetType& symbol = *(stream + advancedIdx); const tAlphabetType& symbol = *(stream + advancedIdx);
if (!(symbol >= mSymbolRange.mBegin && symbol < mSymbolRange.mEnd)) { if (!(symbol >= mSymbolRange.mBegin && symbol < mSymbolRange.mEnd)) {
return { false, advancedIdx, {} }; return { false, advancedIdx, {} };
@ -34,7 +34,7 @@ namespace tp {
mCurrentState = mTable.get({ (ualni) (symbol - mSymbolRange.mBegin), mCurrentState }); mCurrentState = mTable.get({ (ualni) (symbol - mSymbolRange.mBegin), mCurrentState });
if (mCurrentState == mStates.size()) { if (mCurrentState == mStates.size()) {
return false; return { false, advancedIdx, {} };
} }
if (mStates[mCurrentState].first) { if (mStates[mCurrentState].first) {

View file

@ -6,7 +6,7 @@
namespace tp { namespace tp {
template <typename tAlphabetType, typename tStateType, ualni tMinSymbol, ualni tMaxSymbol> template <typename tAlphabetType, typename tStateType, tStateType tInTransition, ualni tMinSymbol, ualni tMaxSymbol>
class RegularCompiler { class RegularCompiler {
typedef FiniteStateAutomation<tAlphabetType, tStateType> Graph; typedef FiniteStateAutomation<tAlphabetType, tStateType> Graph;
@ -203,6 +203,6 @@ namespace tp {
} }
} }
Vertex* addVertex() { return mGraph->addState(tStateType::InTransition, false); } Vertex* addVertex() { return mGraph->addState(tInTransition, false); }
}; };
} }

View file

@ -7,7 +7,10 @@ namespace tp {
// Gives ability to express grammar in the Unified Format as sentence // Gives ability to express grammar in the Unified Format as sentence
template <typename tAlphabetType> template <typename tAlphabetType>
class SimpleParser { class SimpleParser {
enum UGTokens : ualni { InTransition = 0, Failed, TestSeq }; enum UGTokens : alni { InTransition = -1, TestSeq };
typedef Parser<tAlphabetType, UGTokens, InTransition, 0, 127> UGParser;
typedef Parser<tAlphabetType, alni, -1, 0, 127> UserParser;
public: public:
SimpleParser() { SimpleParser() {
@ -22,23 +25,25 @@ namespace tp {
} }
// Define Regular grammar // Define Regular grammar
RegularGrammar<tAlphabetType, UGTokens> rg; RegularGrammar<tAlphabetType, UGTokens> regularGrammar;
{ {
// this is basically ast from existing tokenizer // this is basically ast from existing tokenizer
rg.addRule(rg.seq({ rg.val('a'), rg.val('b') }), TestSeq); regularGrammar.addRule(regularGrammar.seq({ regularGrammar.val('a'), regularGrammar.val('b') }), TestSeq);
} }
mUnifiedGrammarParser.compileTables(contextFreeGrammar, rg); Map<String, UGTokens> terminalsMap;
terminalsMap.put("TestSeq", TestSeq);
mUnifiedGrammarParser.compileTables(contextFreeGrammar, regularGrammar, terminalsMap);
} }
public: public:
void compileTables(const tAlphabetType* grammar, ualni grammarLength) { void compileTables(const tAlphabetType* grammar, ualni grammarLength) {
AST unifiedGrammarAst; mUnifiedGrammarParser.parse(grammar, grammarLength);
mUnifiedGrammarParser.parse(grammar, grammarLength, unifiedGrammarAst);
// compile each ast into RegularGrammar and ContextFree Grammar api instructions // compile each ast into RegularGrammar and ContextFree Grammar api instructions
ContextFreeGrammar userContextFreeGrammar; ContextFreeGrammar userContextFreeGrammar;
RegularGrammar<tAlphabetType, UGTokens> userRegularGrammar; RegularGrammar<tAlphabetType, alni> userRegularGrammar;
// ... // ...
// split ast into RE and CF part // split ast into RE and CF part
@ -47,15 +52,18 @@ namespace tp {
// ... // ...
// compile tables from user grammar // compile tables from user grammar
mUserParser.compileTables(userContextFreeGrammar, userRegularGrammar); Map<String, alni> terminalsMap;
terminalsMap.put("TestSeq", 0);
mUserParser.compileTables(userContextFreeGrammar, userRegularGrammar, terminalsMap);
} }
void parse(const tAlphabetType* grammar, ualni grammarLength, AST& out) { UserParser::ParseResult parse(const tAlphabetType* grammar, ualni grammarLength) {
mUserParser.parse(grammar, grammarLength, out); return mUserParser.parse(grammar, grammarLength);
} }
private: private:
Parser<tAlphabetType, UGTokens, 0, 127> mUnifiedGrammarParser; UGParser mUnifiedGrammarParser;
Parser<tAlphabetType, UGTokens, 0, 127> mUserParser; UserParser mUserParser;
}; };
} }

View file

@ -19,10 +19,9 @@ void testAutomation() {
void test() { void test() {
auto parser = SimpleParser<int1>(); auto parser = SimpleParser<int1>();
auto ast = AST();
parser.compileTables(gGrammar, String::Logic::calcLength(gGrammar)); parser.compileTables(gGrammar, String::Logic::calcLength(gGrammar));
parser.parse(gSentence, String::Logic::calcLength(gSentence), ast); auto result = parser.parse(gSentence, String::Logic::calcLength(gSentence));
} }
int main() { int main() {