diff --git a/include/Parsodus/driver.h b/include/Parsodus/driver.h new file mode 100644 index 0000000..a22a8d7 --- /dev/null +++ b/include/Parsodus/driver.h @@ -0,0 +1,64 @@ +#pragma once +#ifndef PARSODUS_DRIVER_H +#define PARSODUS_DRIVER_H + +#include +#include + +#include "Parsodus/backendmanager.h" + +namespace pds { + + /** + * The main driver for Parsodus + */ + class Driver { + public: + /** + * Constructor + * + * @param backends The backendmanager, prepared with all needed supported backends + * @param inputfile An istream which should be read to be used as token rules specifications + * @param outputdir A string representing the directory where generated files should be places + * @param language The language to generate output for (backends is queried for this language) + * @param lexername The name to give to the generated lexer that is used by the parser, this gets cleaned to only contains alphanumeric chars or underscore and start with a non-digit (AKA a valid identifier) + * @param parsername The name to give to the generated parser, this gets cleaned to only contains alphanumeric chars or underscore and start with a non-digit (AKA a valid identifier) + */ + Driver(std::unique_ptr backends, std::istream& inputfile, std::string outputdir, std::string language, std::string lexername, std::string parsername); + + /** + * Destructor + */ + ~Driver(); + + /** + * Run this driver, all the preparation should happen when calling the constructor + * + * @return The status code this would return if it were a main function + */ + int run(); + + private: + std::unique_ptr m_backends; + std::istream& m_inputfile; + std::string m_outputdir; + std::string m_language; + std::string m_lexername; + std::string m_parsername; + }; + + /** + * Used to throw errors when the driver could generate a valid lexer name or find the backend for a language + */ + + class DriverException: public std::exception { + public: + DriverException(std::string what); + virtual const char* what() const throw(); + + private: + std::string m_what; + }; +} + +#endif //PARSODUS_DRIVER_H diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 8ac1da0..227e518 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -25,13 +25,15 @@ add_library(Parsodus-tables lrtables/SLR1Itemset.cpp ) -add_library(Parsodus-backends - backends/cpp.cpp - ) +# add_library(Parsodus-backends +# ) add_library(pds + backend.cpp driver.cpp + template.cpp inputparser.cpp + backendmanager.cpp "${CMAKE_CURRENT_BINARY_DIR}/ParsodusLexer.cpp" ) @@ -42,7 +44,7 @@ add_executable(Parsodus target_link_libraries(Parsodus Parsodus-util Parsodus-tables - Parsodus-backends + # Parsodus-backends pds mstch::mstch) diff --git a/src/driver.cpp b/src/driver.cpp index 2aeb2f1..8f5dcd3 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -1,2 +1,43 @@ -#include "Parsodus/grammar.h" +#include "Parsodus/driver.h" +#include "Parsodus/inputparser.h" +#include "Parsodus/config.h" + +#include + +namespace { + /** + * Filter only valid identifier chars: alphanumeric, and not starting with a digit + */ + std::string clean(std::string in) { + std::string s; + for (char c : in) { + if ((s.length() && std::isalnum(c)) || std::isalpha(c) || c == '_') + s += c; + } + return s; + } +} + + +namespace pds { + + Driver::Driver(std::unique_ptr backends, std::istream& inputfile, std::string outputdir, std::string language, std::string lexername, std::string parsername): + m_backends(std::move(backends)), m_inputfile(inputfile), m_outputdir(outputdir), m_language(language), m_lexername(clean(lexername)), m_parsername(clean(parsername)) { + } + + Driver::~Driver(){} + int Driver::run() { + if (!m_lexername.length()) throw DriverException("no valid lexer name possible"); + if (!m_parsername.length()) throw DriverException("no valid parser name possible"); + Config config = InputParser::parseInput(m_inputfile); + Backend* back = m_backends->findBackend(m_language, config.parserType); + if (!back) throw DriverException("Could not find a valid backend for language " + m_language + " and the given type of parser"); + back->generateParser([this](std::string filename) -> std::unique_ptr { + return std::unique_ptr(new std::ofstream(m_outputdir + "/" + filename)); + }, + m_lexername, config); + + return 0; + } +} diff --git a/src/inputparser.cpp b/src/inputparser.cpp index 434110e..eaa5a07 100644 --- a/src/inputparser.cpp +++ b/src/inputparser.cpp @@ -1,5 +1,6 @@ #include "ParsodusLexer.h" #include "Parsodus/inputparser.h" +#include "Parsodus/util/parserType.h" namespace pds { @@ -32,7 +33,7 @@ namespace pds { lexColon(lex, token); if(token.type == ParsodusLexer::PARSERTYPE) { if(token.content == "lalr(1)") { - config.parserType = Config::ParserType::LALR_1; + config.parserType = util::ParserType::LALR_1; } else throw InputParserException("Unkown parser type"); } else { diff --git a/src/main.cpp b/src/main.cpp index 46c1c55..b91c3b6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,9 +2,11 @@ #include #include "optparse.h" #include "Parsodus/inputparser.h" - +#include "Parsodus/backendmanager.h" #include "Parsodus/lrtables/generator.h" #include "Parsodus/lrtables/SLR1Itemset.h" +#include "Parsodus/backends/cppLR.h" +#include "Parsodus/util/parserType.h" int main(int argc, char** argv) { @@ -30,8 +32,11 @@ int main(int argc, char** argv) { auto config = pds::InputParser::parseInput(infile); - - + pds::BackendManager b; + b.registerLR(); + pds::Backend* back = b.findBackend("c++", pds::util::ParserType::LR_0); + std::cout << back->getName() << std::endl; + // Reporting what the inputparser found, to be removed... std::cout << "Start: " << config.grammar.start << std::endl; for(auto a: config.grammar.terminals) diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index 5baf0bb..2a82d3d 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -3,7 +3,7 @@ add_executable(Parsodus-test ) target_link_libraries(Parsodus-test #Parsodus-tables - Parsodus-backends + # Parsodus-backends pds mstch::mstch ${GTEST_BOTH_LIBRARIES}