parsing loop closed
This commit is contained in:
parent
aaeb6438a1
commit
30d4f194ba
8 changed files with 92 additions and 45 deletions
|
|
@ -1,8 +0,0 @@
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "LanguageCommon.hpp"
|
|
||||||
|
|
||||||
namespace tp {
|
|
||||||
class AST {};
|
|
||||||
}
|
|
||||||
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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) {
|
||||||
|
|
|
||||||
|
|
@ -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); }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -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() {
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue