diff --git a/Parser/private/CLR.cpp b/Parser/private/CLR.cpp new file mode 100644 index 0000000..673693f --- /dev/null +++ b/Parser/private/CLR.cpp @@ -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& out, ASTNode** root) { + *root = nullptr; +} \ No newline at end of file diff --git a/Parser/private/CfGrammarParser.cpp b/Parser/private/CfGrammarParser.cpp index d20b27a..3502a2f 100644 --- a/Parser/private/CfGrammarParser.cpp +++ b/Parser/private/CfGrammarParser.cpp @@ -202,4 +202,8 @@ void CfGrammar::deinitializeCfGrammarParser(CfGrammarParserState* state) { bool CfGrammar::parse(CfGrammarParserState* context, const String& source) { return ::parse(source.read(), &context->automata, &context->tokenizer, this); -} \ No newline at end of file +} + +bool CfGrammar::isLooped() const { + return mIsLooped; +} diff --git a/Parser/public/CLR.hpp b/Parser/public/CLR.hpp new file mode 100644 index 0000000..5d9d8ff --- /dev/null +++ b/Parser/public/CLR.hpp @@ -0,0 +1,65 @@ +#pragma once + +#include "CfGrammar.hpp" + +namespace tp { + class CLR { + public: + struct ASTNode { + const CfGrammar::Rule* production = nullptr; + Map 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& 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; + }; +} \ No newline at end of file diff --git a/Parser/public/CfGrammar.hpp b/Parser/public/CfGrammar.hpp index f61d9f9..c99ce55 100644 --- a/Parser/public/CfGrammar.hpp +++ b/Parser/public/CfGrammar.hpp @@ -77,6 +77,7 @@ namespace tp { Map mTerminals; Map mNonTerminals; + bool mIsLooped = false; public: static struct CfGrammarParserState* initializeCfGrammarParser(); @@ -89,7 +90,6 @@ namespace tp { void generateSentences(List& out); static void printSentence(Sentence& in); - private: - void optimize(); + [[nodiscard]] bool isLooped() const; }; } \ No newline at end of file diff --git a/Parser/public/Parser.hpp b/Parser/public/Parser.hpp index 5f3f488..10544da 100644 --- a/Parser/public/Parser.hpp +++ b/Parser/public/Parser.hpp @@ -1,6 +1,6 @@ #pragma once -#include "CfGrammar.hpp" +#include "CLR.hpp" namespace tp { extern ModuleManifest gModuleParser; diff --git a/Parser/tests/CLRTests.cpp b/Parser/tests/CLRTests.cpp new file mode 100644 index 0000000..b8eff56 --- /dev/null +++ b/Parser/tests/CLRTests.cpp @@ -0,0 +1,10 @@ + +#include "NewPlacement.hpp" +#include "Testing.hpp" +#include "Parser.hpp" + +using namespace tp; + +TEST_DEF(CLR) { + TEST(false); +} \ No newline at end of file diff --git a/Parser/tests/GrammarTests.cpp b/Parser/tests/GrammarTests.cpp new file mode 100644 index 0000000..28697f5 --- /dev/null +++ b/Parser/tests/GrammarTests.cpp @@ -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 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()); +} \ No newline at end of file diff --git a/Parser/tests/Tests.cpp b/Parser/tests/Tests.cpp index 892394f..fb2fd04 100644 --- a/Parser/tests/Tests.cpp +++ b/Parser/tests/Tests.cpp @@ -5,47 +5,8 @@ using namespace tp; -TEST_DEF(Simple) { - - 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 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()); -} +void testGrammar(); +void testCLR(); int main(int argc, const char* argv[]) { tp::ModuleManifest* deps[] = { &tp::gModuleParser, nullptr }; @@ -55,7 +16,8 @@ int main(int argc, const char* argv[]) { return 1; } - testSimple(); + testGrammar(); + testCLR(); testModule.deinitialize(); return 0;