#include "knowledge_base.h" #include "lexer.h" #include "main.h" #include "obelisk.h" #include "parser.h" #include "version.h" #include #include #include #include int obelisk::mainLoop(const std::vector& sourceFiles, const std::string& kbFile) { std::unique_ptr kb; try { kb = std::unique_ptr { new obelisk::KnowledgeBase(kbFile.c_str())}; } catch (obelisk::KnowledgeBaseException& exception) { std::cout << exception.what() << std::endl; return EXIT_FAILURE; } size_t file = 0; std::shared_ptr lexer; try { lexer = std::shared_ptr { new obelisk::Lexer(sourceFiles[file++])}; } catch (obelisk::LexerException& exception) { std::cout << exception.what() << std::endl; return EXIT_FAILURE; } auto parser = std::unique_ptr {new obelisk::Parser(lexer)}; // prime the first token try { parser->getNextToken(); } catch (obelisk::LexerException& exception) { std::cout << "Error: " << exception.what() << std::endl; return EXIT_FAILURE; } while (true) { switch (parser->getCurrentToken()) { case obelisk::Lexer::kTokenEof : // end of source file found, create a new lexer and pass it to // the parser to use if (file >= sourceFiles.size()) { return EXIT_SUCCESS; } try { lexer = std::shared_ptr { new obelisk::Lexer(sourceFiles[file++])}; parser->setLexer(lexer); // prime the first token in the parser parser->getNextToken(); } catch (obelisk::LexerException& exception) { std::cout << exception.what() << std::endl; return EXIT_FAILURE; } break; case ';' : // semicolon found, the end of a statement try { parser->getNextToken(); } catch (obelisk::LexerException& exception) { std::cout << "Error: " << exception.what() << std::endl; return EXIT_FAILURE; } break; case obelisk::Lexer::kTokenFact : try { parser->handleFact(kb); } catch (obelisk::ParserException& exception) { std::cout << "Error: " << exception.what() << std::endl; return EXIT_FAILURE; } break; case obelisk::Lexer::kTokenRule : try { parser->handleRule(kb); } catch (obelisk::ParserException& exception) { std::cout << "Error: " << exception.what() << std::endl; return EXIT_FAILURE; } break; case obelisk::Lexer::kTokenAction : try { parser->handleAction(kb); } catch (obelisk::ParserException& exception) { std::cout << "Error: " << exception.what() << std::endl; return EXIT_FAILURE; } break; default : parser->getNextToken(); break; } } return EXIT_SUCCESS; } static void obelisk::showUsage() { std::cout << obelisk::usageMessage << std::endl; } int main(int argc, char** argv) { std::vector sourceFiles; std::string kbFile = "obelisk.kb"; while (true) { int option_index = 0; switch (getopt_long(argc, argv, "k:hv", obelisk::long_options, &option_index)) { case 'k' : kbFile = std::string(optarg); continue; case 'h' : obelisk::showUsage(); return EXIT_SUCCESS; break; case 'v' : std::cout << "obelisk " << obelisk::version << std::endl; return EXIT_SUCCESS; break; default : obelisk::showUsage(); return EXIT_FAILURE; break; case -1 : break; } break; } if (optind < argc) { while (optind < argc) { sourceFiles.push_back(argv[optind++]); } } if (sourceFiles.size() == 0) { obelisk::showUsage(); return EXIT_FAILURE; } return obelisk::mainLoop(sourceFiles, kbFile); }