LR(1) Parser Initial
This commit is contained in:
parent
616441e049
commit
01b6f9099c
8 changed files with 161 additions and 46 deletions
26
Parser/private/CLR.cpp
Normal file
26
Parser/private/CLR.cpp
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
#include "CLR.hpp"
|
||||||
|
#include "NewPlacement.hpp"
|
||||||
|
|
||||||
|
using namespace tp;
|
||||||
|
|
||||||
|
void CLR::setGrammar(const tp::CfGrammar& grammar) {
|
||||||
|
if (grammar.isLooped()) {
|
||||||
|
mState = ParserState::FAILED;
|
||||||
|
mBuildError.description = "Cant build lalr parser from looped context free grammar";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mState = ParserState::FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLR::setTerminal(const String& name, TerminalStream::TerminalID id) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLR::build() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void CLR::parse(TerminalStream* source, List<ASTNode>& out, ASTNode** root) {
|
||||||
|
*root = nullptr;
|
||||||
|
}
|
||||||
|
|
@ -203,3 +203,7 @@ void CfGrammar::deinitializeCfGrammarParser(CfGrammarParserState* state) {
|
||||||
bool CfGrammar::parse(CfGrammarParserState* context, const String& source) {
|
bool CfGrammar::parse(CfGrammarParserState* context, const String& source) {
|
||||||
return ::parse(source.read(), &context->automata, &context->tokenizer, this);
|
return ::parse(source.read(), &context->automata, &context->tokenizer, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CfGrammar::isLooped() const {
|
||||||
|
return mIsLooped;
|
||||||
|
}
|
||||||
|
|
|
||||||
65
Parser/public/CLR.hpp
Normal file
65
Parser/public/CLR.hpp
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "CfGrammar.hpp"
|
||||||
|
|
||||||
|
namespace tp {
|
||||||
|
class CLR {
|
||||||
|
public:
|
||||||
|
struct ASTNode {
|
||||||
|
const CfGrammar::Rule* production = nullptr;
|
||||||
|
Map<String, String> terminals;
|
||||||
|
};
|
||||||
|
|
||||||
|
class Automation {
|
||||||
|
public:
|
||||||
|
class State {
|
||||||
|
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
class TerminalStream {
|
||||||
|
public:
|
||||||
|
typedef ualni TerminalID;
|
||||||
|
public:
|
||||||
|
TerminalStream() = default;
|
||||||
|
virtual TerminalID getNextTerminal() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
struct BuildError {
|
||||||
|
String description;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ParseError {
|
||||||
|
const Automation::State* state = nullptr;
|
||||||
|
String::Index location = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
class SententialStack {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
CLR() = default;
|
||||||
|
|
||||||
|
void setGrammar(const CfGrammar& grammar);
|
||||||
|
void setTerminal(const String& name, TerminalStream::TerminalID id);
|
||||||
|
void build();
|
||||||
|
|
||||||
|
void parse(TerminalStream* stream, List<ASTNode>& out, ASTNode** root);
|
||||||
|
|
||||||
|
[[nodiscard]] bool isBuild() { return mState == ParserState::BUILD; }
|
||||||
|
[[nodiscard]] const BuildError& getBuildError() { return mBuildError; }
|
||||||
|
[[nodiscard]] const ParseError& getParseError() { return mParseError; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum class ParserState { NONE, BUILD, FAILED } mState = ParserState::NONE;
|
||||||
|
|
||||||
|
ParseError mParseError;
|
||||||
|
BuildError mBuildError;
|
||||||
|
|
||||||
|
SententialStack mStack;
|
||||||
|
Automation mAutomation;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -77,6 +77,7 @@ namespace tp {
|
||||||
|
|
||||||
Map<String, Terminal> mTerminals;
|
Map<String, Terminal> mTerminals;
|
||||||
Map<String, NonTerminal> mNonTerminals;
|
Map<String, NonTerminal> mNonTerminals;
|
||||||
|
bool mIsLooped = false;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
static struct CfGrammarParserState* initializeCfGrammarParser();
|
static struct CfGrammarParserState* initializeCfGrammarParser();
|
||||||
|
|
@ -89,7 +90,6 @@ namespace tp {
|
||||||
void generateSentences(List<Sentence>& out);
|
void generateSentences(List<Sentence>& out);
|
||||||
static void printSentence(Sentence& in);
|
static void printSentence(Sentence& in);
|
||||||
|
|
||||||
private:
|
[[nodiscard]] bool isLooped() const;
|
||||||
void optimize();
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "CfGrammar.hpp"
|
#include "CLR.hpp"
|
||||||
|
|
||||||
namespace tp {
|
namespace tp {
|
||||||
extern ModuleManifest gModuleParser;
|
extern ModuleManifest gModuleParser;
|
||||||
|
|
|
||||||
10
Parser/tests/CLRTests.cpp
Normal file
10
Parser/tests/CLRTests.cpp
Normal file
|
|
@ -0,0 +1,10 @@
|
||||||
|
|
||||||
|
#include "NewPlacement.hpp"
|
||||||
|
#include "Testing.hpp"
|
||||||
|
#include "Parser.hpp"
|
||||||
|
|
||||||
|
using namespace tp;
|
||||||
|
|
||||||
|
TEST_DEF(CLR) {
|
||||||
|
TEST(false);
|
||||||
|
}
|
||||||
48
Parser/tests/GrammarTests.cpp
Normal file
48
Parser/tests/GrammarTests.cpp
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
|
||||||
|
#include "NewPlacement.hpp"
|
||||||
|
#include "Testing.hpp"
|
||||||
|
#include "Parser.hpp"
|
||||||
|
|
||||||
|
using namespace tp;
|
||||||
|
|
||||||
|
TEST_DEF(Grammar) {
|
||||||
|
|
||||||
|
String source = R"(
|
||||||
|
Start Body
|
||||||
|
Body : [ Function ] | List | &;
|
||||||
|
List : [ LIST ];
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto state = CfGrammar::initializeCfGrammarParser();
|
||||||
|
|
||||||
|
CfGrammar grammar;
|
||||||
|
|
||||||
|
if (!grammar.parse(state, source)) {
|
||||||
|
TEST(0 && "Parsing is failed\n");
|
||||||
|
CfGrammar::deinitializeCfGrammarParser(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!grammar.compile()) {
|
||||||
|
TEST(0 && "Compilation is failed\n");
|
||||||
|
CfGrammar::deinitializeCfGrammarParser(state);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
CfGrammar::deinitializeCfGrammarParser(state);
|
||||||
|
|
||||||
|
printf("Grammar accepted.\n");
|
||||||
|
|
||||||
|
List<CfGrammar::Sentence> sentences;
|
||||||
|
grammar.generateSentences(sentences);
|
||||||
|
|
||||||
|
TEST_ASSERT(sentences.length() == 3);
|
||||||
|
TEST_ASSERT(sentences.first()->data.terms.length() == 1);
|
||||||
|
TEST_ASSERT(sentences.last()->data.terms.length() == 1);
|
||||||
|
|
||||||
|
TEST(sentences.first()->data.terms.first()->data.id == "Function");
|
||||||
|
TEST(sentences.last()->data.terms.first()->data.id == "LIST");
|
||||||
|
|
||||||
|
printf("Example sentences formed from grammar: \n");
|
||||||
|
for (auto sentence : sentences) tp::CfGrammar::printSentence(sentence.data());
|
||||||
|
}
|
||||||
|
|
@ -5,47 +5,8 @@
|
||||||
|
|
||||||
using namespace tp;
|
using namespace tp;
|
||||||
|
|
||||||
TEST_DEF(Simple) {
|
void testGrammar();
|
||||||
|
void testCLR();
|
||||||
String source = R"(
|
|
||||||
Start Body
|
|
||||||
Body : [ Function ] | List | &;
|
|
||||||
List : [ LIST ];
|
|
||||||
)";
|
|
||||||
|
|
||||||
auto state = CfGrammar::initializeCfGrammarParser();
|
|
||||||
|
|
||||||
CfGrammar grammar;
|
|
||||||
|
|
||||||
if (!grammar.parse(state, source)) {
|
|
||||||
TEST(0 && "Parsing is failed\n");
|
|
||||||
CfGrammar::deinitializeCfGrammarParser(state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!grammar.compile()) {
|
|
||||||
TEST(0 && "Compilation is failed\n");
|
|
||||||
CfGrammar::deinitializeCfGrammarParser(state);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
CfGrammar::deinitializeCfGrammarParser(state);
|
|
||||||
|
|
||||||
printf("Grammar accepted.\n");
|
|
||||||
|
|
||||||
List<CfGrammar::Sentence> sentences;
|
|
||||||
grammar.generateSentences(sentences);
|
|
||||||
|
|
||||||
TEST_ASSERT(sentences.length() == 3);
|
|
||||||
TEST_ASSERT(sentences.first()->data.terms.length() == 1);
|
|
||||||
TEST_ASSERT(sentences.last()->data.terms.length() == 1);
|
|
||||||
|
|
||||||
TEST(sentences.first()->data.terms.first()->data.id == "Function");
|
|
||||||
TEST(sentences.last()->data.terms.first()->data.id == "LIST");
|
|
||||||
|
|
||||||
printf("Example sentences formed from grammar: \n");
|
|
||||||
for (auto sentence : sentences) tp::CfGrammar::printSentence(sentence.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, const char* argv[]) {
|
int main(int argc, const char* argv[]) {
|
||||||
tp::ModuleManifest* deps[] = { &tp::gModuleParser, nullptr };
|
tp::ModuleManifest* deps[] = { &tp::gModuleParser, nullptr };
|
||||||
|
|
@ -55,7 +16,8 @@ int main(int argc, const char* argv[]) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
testSimple();
|
testGrammar();
|
||||||
|
testCLR();
|
||||||
|
|
||||||
testModule.deinitialize();
|
testModule.deinitialize();
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue