From dbf1820428070042da4f4ae33d333a61c7b88c23 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Tue, 31 Dec 2013 23:43:49 -0600 Subject: [PATCH] Can import other files now. (in same directory, use filename without .krak file extention) Right now, still need to compile both files with kraken. --- CMakeLists.txt | 2 +- include/ASTTransformation.h | 7 +- include/GraphStructuredStack.h | 1 + include/Importer.h | 28 ++++++++ include/Lexer.h | 1 + krakenGrammer.kgm | 2 +- main.cpp | 115 ++++----------------------------- src/ASTTransformation.cpp | 25 ++++--- src/CGenerator.cpp | 5 +- src/GraphStructuredStack.cpp | 5 ++ src/Importer.cpp | 113 ++++++++++++++++++++++++++++++++ src/Lexer.cpp | 4 ++ src/RNGLRParser.cpp | 11 +++- 13 files changed, 203 insertions(+), 116 deletions(-) create mode 100644 include/Importer.h create mode 100644 src/Importer.cpp diff --git a/CMakeLists.txt b/CMakeLists.txt index ad4cfeb..db3eb07 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -6,7 +6,7 @@ set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11") set( MY_INCLUDES ${PROJECT_SOURCE_DIR}/include) -set( MY_SOURCES main.cpp src/Parser.cpp src/LALRParser.cpp src/GraphStructuredStack.cpp src/RNGLRParser.cpp src/ParseAction.cpp src/ParseRule.cpp src/Symbol.cpp src/StringReader.cpp src/State.cpp src/util.cpp src/Lexer.cpp src/RegEx.cpp src/RegExState.cpp src/Table.cpp src/ASTData.cpp src/ASTTransformation.cpp src/CGenerator.cpp src/Type.cpp ) +set( MY_SOURCES main.cpp src/Parser.cpp src/LALRParser.cpp src/GraphStructuredStack.cpp src/RNGLRParser.cpp src/ParseAction.cpp src/ParseRule.cpp src/Symbol.cpp src/StringReader.cpp src/State.cpp src/util.cpp src/Lexer.cpp src/RegEx.cpp src/RegExState.cpp src/Table.cpp src/ASTData.cpp src/ASTTransformation.cpp src/CGenerator.cpp src/Type.cpp src/Importer.cpp ) include_directories( ${MY_INCLUDES} ) diff --git a/include/ASTTransformation.h b/include/ASTTransformation.h index c9d1c41..f93ce65 100644 --- a/include/ASTTransformation.h +++ b/include/ASTTransformation.h @@ -6,16 +6,19 @@ #include "ASTData.h" #include "NodeTransformation.h" +#include "Importer.h" + +class Importer; class ASTTransformation: public NodeTransformation { public: - ASTTransformation(); + ASTTransformation(Importer* importerIn); ~ASTTransformation(); virtual NodeTree* transform(NodeTree* from); NodeTree* transform(NodeTree* from, NodeTree* scope); std::string concatSymbolTree(NodeTree* root); NodeTree* scopeLookup(NodeTree* scope, std::string lookup); private: - //Nothing + Importer * importer; }; #endif diff --git a/include/GraphStructuredStack.h b/include/GraphStructuredStack.h index 302fd60..e79a8fe 100644 --- a/include/GraphStructuredStack.h +++ b/include/GraphStructuredStack.h @@ -25,6 +25,7 @@ class GraphStructuredStack { bool hasEdge(NodeTree* start, NodeTree* end); NodeTree* getEdge(NodeTree* start, NodeTree* end); void addEdge(NodeTree* start, NodeTree* end, NodeTree* edge); + void clear(); std::string toString(); private: diff --git a/include/Importer.h b/include/Importer.h new file mode 100644 index 0000000..187d054 --- /dev/null +++ b/include/Importer.h @@ -0,0 +1,28 @@ +#ifndef __IMPORTER__H_ +#define __IMPORTER__H_ + +#include +#include +#include +#include + +#include "Parser.h" +#include "NodeTree.h" +#include "ASTData.h" +#include "Symbol.h" +#include "RemovalTransformation.h" +#include "CollapseTransformation.h" +#include "ASTTransformation.h" + +class Importer { + public: + Importer(Parser* parserIn); + ~Importer(); + NodeTree* import(std::string fileName); + private: + Parser* parser; + std::vector removeSymbols; + std::vector collapseSymbols; +}; + +#endif \ No newline at end of file diff --git a/include/Lexer.h b/include/Lexer.h index 02223a9..1574a02 100644 --- a/include/Lexer.h +++ b/include/Lexer.h @@ -16,6 +16,7 @@ class Lexer { void addRegEx(std::string regExString); void setInput(std::string inputString); Symbol next(); + void reset(); static void test(); private: std::vector regExs; diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index b7e2fe6..2234034 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -18,7 +18,7 @@ WS = "( | | if_comp = "__if_comp__" WS identifier WS if_comp_pred ; if_comp_pred = code_block | simple_passthrough ; -simple_passthrough = "comp_simple_passthrough" WS triple_quoted_string ; +simple_passthrough = "__simple_passthrough__" WS triple_quoted_string ; triple_quoted_string = "\"\"\"(a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|u|v|w|x|y|z|A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z|.|,|!|\?|_|-|:|;|%|=|\+| | | |\\|/|\||\(|\)|\"|#|<|\*|>|0|1|2|3|4|5|6|7|8|9)+\"\"\"" ; diff --git a/main.cpp b/main.cpp index a6ee9d4..41de216 100644 --- a/main.cpp +++ b/main.cpp @@ -11,10 +11,7 @@ #include "LALRParser.h" #include "RNGLRParser.h" -#include "NodeTransformation.h" -#include "RemovalTransformation.h" -#include "CollapseTransformation.h" -#include "ASTTransformation.h" +#include "Importer.h" #include "ASTData.h" #include "CGenerator.h" @@ -29,16 +26,12 @@ int main(int argc, char* argv[]) { return 0; } - std::ifstream programInFile, grammerInFile, compiledGrammerInFile; - std::ofstream outFile, outFileTransformed, outFileAST, outFileC, compiledGrammerOutFile; - - programInFile.open(argv[1]); - if (!programInFile.is_open()) { - std::cout << "Problem opening programInFile " << argv[1] << "\n"; - return(1); - } - + std::string programName = argv[1]; std::string grammerFileString = argv[2]; + std::string outputName = argv[3]; + + std::ifstream grammerInFile, compiledGrammerInFile; + std::ofstream outFileC, compiledGrammerOutFile; grammerInFile.open(grammerFileString); if (!grammerInFile.is_open()) { @@ -52,31 +45,13 @@ int main(int argc, char* argv[]) { //return(1); } - outFile.open(argv[3]); - if (!outFile.is_open()) { - std::cout << "Probelm opening output file " << argv[3] << "\n"; - return(1); - } - - outFileTransformed.open((std::string(argv[3]) + ".transformed.dot").c_str()); - if (!outFileTransformed.is_open()) { - std::cout << "Probelm opening second output file " << std::string(argv[3]) + ".transformed.dot" << "\n"; - return(1); - } - - outFileAST.open((std::string(argv[3]) + ".AST.dot").c_str()); - if (!outFileAST.is_open()) { - std::cout << "Probelm opening second output file " << std::string(argv[3]) + ".AST.dot" << "\n"; - return(1); - } - - outFileC.open((std::string(argv[3]) + ".c").c_str()); + outFileC.open((outputName + ".c").c_str()); if (!outFileC.is_open()) { - std::cout << "Probelm opening third output file " << std::string(argv[3]) + ".c" << "\n"; + std::cout << "Probelm opening third output file " << outputName + ".c" << "\n"; return(1); } //Read the input file into a string - std::string programInputFileString, grammerInputFileString; + std::string grammerInputFileString; std::string line; while(grammerInFile.good()) { getline(grammerInFile, line); @@ -84,12 +59,6 @@ int main(int argc, char* argv[]) { } grammerInFile.close(); - while(programInFile.good()) { - getline(programInFile, line); - programInputFileString.append(line+"\n"); - } - programInFile.close(); - //LALRParser parser; RNGLRParser parser; parser.loadGrammer(grammerInputFileString); @@ -105,6 +74,7 @@ int main(int argc, char* argv[]) { compiledGrammerInFile.seekg(0, std::ios::beg); compiledGrammerInFile.read(binaryTablePointer, compGramSize); compiledGrammerInFile.close(); + //Check magic number if (binaryTablePointer[0] == 'K' && binaryTablePointer[1] == 'R' && binaryTablePointer[2] == 'A' && binaryTablePointer[3] == 'K') { std::cout << "Valid Kraken Compiled Grammer File" << std::endl; int gramStringLength = *((int*)(binaryTablePointer+4)); @@ -162,70 +132,11 @@ int main(int argc, char* argv[]) { //outFile << parser.grammerToDOT() << std::endl; std::cout << "\nParsing" << std::endl; - std::cout << programInputFileString << std::endl; - NodeTree* parseTree = parser.parseInput(programInputFileString); + Importer importer(&parser); - if (parseTree) { - //std::cout << parseTree->DOTGraphString() << std::endl; - outFile << parseTree->DOTGraphString() << std::endl; - } else { - std::cout << "ParseTree returned from parser is NULL!" << std::endl; - } - outFile.close(); + NodeTree* AST = importer.import(programName); - //Remove Transformations - std::vector removeSymbols; - removeSymbols.push_back(Symbol("WS", false)); - removeSymbols.push_back(Symbol("\\(", true)); - removeSymbols.push_back(Symbol("\\)", true)); - removeSymbols.push_back(Symbol("::", true)); - removeSymbols.push_back(Symbol(";", true)); - removeSymbols.push_back(Symbol("{", true)); - removeSymbols.push_back(Symbol("}", true)); - removeSymbols.push_back(Symbol("(", true)); - removeSymbols.push_back(Symbol(")", true)); - removeSymbols.push_back(Symbol("import", true)); //Don't need the actual text of the symbol - removeSymbols.push_back(Symbol("interpreter_directive", false)); - removeSymbols.push_back(Symbol("if", true)); - removeSymbols.push_back(Symbol("while", true)); - removeSymbols.push_back(Symbol("__if_comp__", true)); - removeSymbols.push_back(Symbol("comp_simple_passthrough", true)); - - for (int i = 0; i < removeSymbols.size(); i++) - parseTree = RemovalTransformation(removeSymbols[i]).transform(parseTree); - - //Collapse Transformations - std::vector collapseSymbols; - - collapseSymbols.push_back(Symbol("opt_typed_parameter_list", false)); - collapseSymbols.push_back(Symbol("opt_parameter_list", false)); - collapseSymbols.push_back(Symbol("opt_import_list", false)); - collapseSymbols.push_back(Symbol("import_list", false)); - collapseSymbols.push_back(Symbol("statement_list", false)); - collapseSymbols.push_back(Symbol("parameter_list", false)); - collapseSymbols.push_back(Symbol("typed_parameter_list", false)); - collapseSymbols.push_back(Symbol("unorderd_list_part", false)); - collapseSymbols.push_back(Symbol("if_comp_pred", false)); - - for (int i = 0; i < collapseSymbols.size(); i++) - parseTree = CollapseTransformation(collapseSymbols[i]).transform(parseTree); - - if (parseTree) { - outFileTransformed << parseTree->DOTGraphString() << std::endl; - } else { - std::cout << "Tree returned from transformation is NULL!" << std::endl; - } - outFileTransformed.close(); - - NodeTree* AST = ASTTransformation().transform(parseTree); - if (AST) { - outFileAST << AST->DOTGraphString() << std::endl; - } else { - std::cout << "Tree returned from ASTTransformation is NULL!" << std::endl; - } - outFileAST.close(); - - //Do type checking, scope creation, etc. here. + //Do optomization, etc. here. //None at this time, instead going straight to C in this first (more naive) version //Code generation diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 3097243..7ca4937 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -1,7 +1,8 @@ #include "ASTTransformation.h" -ASTTransformation::ASTTransformation() { +ASTTransformation::ASTTransformation(Importer *importerIn) { // + importer = importerIn; } ASTTransformation::~ASTTransformation() { @@ -28,23 +29,31 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree scope->getDataRef()->scope["-"] = new NodeTree(); scope->getDataRef()->scope["*"] = new NodeTree(); scope->getDataRef()->scope["&"] = new NodeTree(); - scope->getDataRef()->scope["=="] = new NodeTree(); scope->getDataRef()->scope["--"] = new NodeTree(); scope->getDataRef()->scope["++"] = new NodeTree(); + scope->getDataRef()->scope["=="] = new NodeTree(); scope->getDataRef()->scope["<="] = new NodeTree(); scope->getDataRef()->scope[">="] = new NodeTree(); + scope->getDataRef()->scope["<"] = new NodeTree(); + scope->getDataRef()->scope[">"] = new NodeTree(); + scope->getDataRef()->scope["&&"] = new NodeTree(); + scope->getDataRef()->scope["||"] = new NodeTree(); + scope->getDataRef()->scope["!"] = new NodeTree(); scope->getDataRef()->scope["*="] = new NodeTree(); scope->getDataRef()->scope["+="] = new NodeTree(); scope->getDataRef()->scope["-="] = new NodeTree(); - scope->getDataRef()->scope["<"] = new NodeTree(); - scope->getDataRef()->scope[">"] = new NodeTree(); + } else if (name == "interpreter_directive") { newNode = new NodeTree(name, ASTData(interpreter_directive)); } else if (name == "import" && !current.isTerminal()) { - newNode = new NodeTree(name, ASTData(import, Symbol(concatSymbolTree(children[0]), true))); - //Add to scope? - // - // + std::string toImport = concatSymbolTree(children[0]); + newNode = new NodeTree(name, ASTData(import, Symbol(toImport, true))); + //Do the imported file too + NodeTree* outsideTranslationUnit = importer->import(toImport + ".krak"); + scope->getDataRef()->scope[toImport] = outsideTranslationUnit; //Put this transation_unit in the scope as it's files name + //Now add it to scope + for (auto i = outsideTranslationUnit->getDataRef()->scope.begin(); i != outsideTranslationUnit->getDataRef()->scope.end(); i++) + scope->getDataRef()->scope[i->first] = i->second; return newNode; // Don't need children of import } else if (name == "identifier") { std::string lookupName = concatSymbolTree(children[0]); diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 007180a..1b9a108 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -114,7 +114,10 @@ std::string CGenerator::generate(NodeTree* from) { return generate(children[1]) + name; if (name == "*" && children.size() == 2) //Is dereference, not multiplication return "*(" + generate(children[1]) + ")"; - if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!=" || name == "<" || name == ">" || name == "%" || name == "+=" || name == "-=" || name == "*=" || name == "/=") { + if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!=" + || name == "<" || name == ">" || name == "%" || name == "+=" || name == "-=" || name == "*=" || name == "/=" || name == "||" + || name == "&&" || name == "!" ) { + return "((" + generate(children[1]) + ")" + name + "(" + generate(children[2]) + "))"; } output += data.symbol.getName() + "("; diff --git a/src/GraphStructuredStack.cpp b/src/GraphStructuredStack.cpp index fb37d18..dcdf2ff 100644 --- a/src/GraphStructuredStack.cpp +++ b/src/GraphStructuredStack.cpp @@ -128,3 +128,8 @@ std::string GraphStructuredStack::toString() { } return tostring; } + +void GraphStructuredStack::clear() { + gss.clear(); + edges.clear(); +} diff --git a/src/Importer.cpp b/src/Importer.cpp new file mode 100644 index 0000000..f4a1cf9 --- /dev/null +++ b/src/Importer.cpp @@ -0,0 +1,113 @@ +#include "Importer.h" + +Importer::Importer(Parser* parserIn) { + //constructor + parser = parserIn; + + removeSymbols.push_back(Symbol("WS", false)); + removeSymbols.push_back(Symbol("\\(", true)); + removeSymbols.push_back(Symbol("\\)", true)); + removeSymbols.push_back(Symbol("::", true)); + removeSymbols.push_back(Symbol(";", true)); + removeSymbols.push_back(Symbol("{", true)); + removeSymbols.push_back(Symbol("}", true)); + removeSymbols.push_back(Symbol("(", true)); + removeSymbols.push_back(Symbol(")", true)); + removeSymbols.push_back(Symbol("import", true)); //Don't need the actual text of the symbol + removeSymbols.push_back(Symbol("interpreter_directive", false)); + removeSymbols.push_back(Symbol("if", true)); + removeSymbols.push_back(Symbol("while", true)); + removeSymbols.push_back(Symbol("__if_comp__", true)); + removeSymbols.push_back(Symbol("comp_simple_passthrough", true)); + + collapseSymbols.push_back(Symbol("opt_typed_parameter_list", false)); + collapseSymbols.push_back(Symbol("opt_parameter_list", false)); + collapseSymbols.push_back(Symbol("opt_import_list", false)); + collapseSymbols.push_back(Symbol("import_list", false)); + collapseSymbols.push_back(Symbol("statement_list", false)); + collapseSymbols.push_back(Symbol("parameter_list", false)); + collapseSymbols.push_back(Symbol("typed_parameter_list", false)); + collapseSymbols.push_back(Symbol("unorderd_list_part", false)); + collapseSymbols.push_back(Symbol("if_comp_pred", false)); +} + +Importer::~Importer() { + //destructor +} + +NodeTree* Importer::import(std::string fileName) { + std::ifstream programInFile; + std::ofstream outFile, outFileTransformed, outFileAST; + + std::string outputName = fileName + "out"; + + programInFile.open(fileName); + if (!programInFile.is_open()) { + std::cout << "Problem opening programInFile " << fileName << "\n"; + return NULL; + } + + outFile.open(outputName); + if (!outFile.is_open()) { + std::cout << "Probelm opening output file " << outputName << "\n"; + return NULL; + } + + outFileTransformed.open((outputName + ".transformed.dot").c_str()); + if (!outFileTransformed.is_open()) { + std::cout << "Probelm opening second output file " << outputName + ".transformed.dot" << "\n"; + return NULL; + } + + outFileAST.open((outputName + ".AST.dot").c_str()); + if (!outFileAST.is_open()) { + std::cout << "Probelm opening second output file " << outputName + ".AST.dot" << "\n"; + return NULL; + } + //ljklj + std::string programInputFileString, line; + while(programInFile.good()) { + getline(programInFile, line); + programInputFileString.append(line+"\n"); + } + programInFile.close(); + + std::cout << programInputFileString << std::endl; + NodeTree* parseTree = parser->parseInput(programInputFileString); + + if (parseTree) { + //std::cout << parseTree->DOTGraphString() << std::endl; + outFile << parseTree->DOTGraphString() << std::endl; + } else { + std::cout << "ParseTree returned from parser is NULL!" << std::endl; + } + outFile.close(); + + //Remove Transformations + + for (int i = 0; i < removeSymbols.size(); i++) + parseTree = RemovalTransformation(removeSymbols[i]).transform(parseTree); + + //Collapse Transformations + + for (int i = 0; i < collapseSymbols.size(); i++) + parseTree = CollapseTransformation(collapseSymbols[i]).transform(parseTree); + + if (parseTree) { + outFileTransformed << parseTree->DOTGraphString() << std::endl; + } else { + std::cout << "Tree returned from transformation is NULL!" << std::endl; + } + outFileTransformed.close(); + + NodeTree* AST = ASTTransformation(this).transform(parseTree); + + if (AST) { + outFileAST << AST->DOTGraphString() << std::endl; + } else { + std::cout << "Tree returned from ASTTransformation is NULL!" << std::endl; + } + outFileAST.close(); + + return AST; +} \ No newline at end of file diff --git a/src/Lexer.cpp b/src/Lexer.cpp index b9cb367..b6f7033 100644 --- a/src/Lexer.cpp +++ b/src/Lexer.cpp @@ -114,3 +114,7 @@ void Lexer::test() { std::cout << "Lexer tests passed\n"; } + +void Lexer::reset() { + currentPosition = 0; +} diff --git a/src/RNGLRParser.cpp b/src/RNGLRParser.cpp index 392bc30..33989ff 100644 --- a/src/RNGLRParser.cpp +++ b/src/RNGLRParser.cpp @@ -9,6 +9,13 @@ RNGLRParser::~RNGLRParser() { } NodeTree* RNGLRParser::parseInput(std::string inputString) { + input.clear(); + gss.clear(); + while(!toReduce.empty()) toReduce.pop(); + while(!toShift.empty()) toReduce.pop(); + SPPFStepNodes.clear(); + nullableParts.clear(); + packedMap.clear(); //Check for no tokens bool accepting = false; @@ -27,6 +34,7 @@ NodeTree* RNGLRParser::parseInput(std::string inputString) { return new NodeTree(); } + lexer.reset(); lexer.setInput(inputString); //Now fully lex our input because this algorithm was designed in that manner and simplifies this first implementation. //It could be converted to on-line later. @@ -42,7 +50,8 @@ NodeTree* RNGLRParser::parseInput(std::string inputString) { input.push_back(currentToken); } - std::cout << "\nDone with Lexing\n" << std::endl; + std::cout << "\nDone with Lexing, length:" << input.size() << std::endl; + std::cout << input[0].toString() << std::endl; // for (int i = 0; i < input.size(); i++)