diff --git a/include/Importer.h b/include/Importer.h index 8ec0646..48e933e 100644 --- a/include/Importer.h +++ b/include/Importer.h @@ -6,6 +6,8 @@ #include #include +#include + #include "Parser.h" #include "NodeTree.h" #include "ASTData.h" @@ -18,7 +20,7 @@ class ASTTransformation; class Importer { public: - Importer(Parser* parserIn, std::vector includePaths); + Importer(Parser* parserIn, std::vector includePaths, std::string outputName); ~Importer(); void import(std::string fileName); NodeTree* getUnit(std::string fileName); @@ -27,6 +29,7 @@ class Importer { void registerAST(std::string name, NodeTree* ast, NodeTree* syntaxTree); std::map*> getASTMap(); private: + std::string outputName; ASTTransformation *ASTTransformer; struct importTriplet { std::string name; @@ -41,4 +44,4 @@ class Importer { std::map*> imported; }; -#endif \ No newline at end of file +#endif diff --git a/include/util.h b/include/util.h index 20df609..8dca24f 100644 --- a/include/util.h +++ b/include/util.h @@ -50,14 +50,4 @@ bool subset(std::set a, std::set b) { return false; return true; } -/* -std::vector split(std::string str, char delim) { - std::stringstream stream(str); - std::string item; - std::vector results; - while(std::getline(stream, item, delim)) - results.push_back(item); - return results; -} -*/ #endif diff --git a/main.cpp b/main.cpp index f55cf5f..b12f34b 100644 --- a/main.cpp +++ b/main.cpp @@ -24,7 +24,9 @@ int main(int argc, char* argv[]) { includePaths.push_back(""); //Local if (argc <= 1) { - std::cerr << "Kraken invocation: kraken sourceFile.krak grammerFile.kgm outputName" << std::endl; + std::cerr << "Kraken invocation: kraken sourceFile.krak" << std::endl; + std::cerr << "Kraken invocation: kraken sourceFile.krak outputName" << std::endl; + std::cerr << "Kraken invocation: kraken grammerFile.kgm sourceFile.krak outputName" << std::endl; std::cerr << "Or for testing do: kraken --test [optional list of names of file (.krak .expected_results) without extentions to run]" << std::endl; return 0; } @@ -64,9 +66,21 @@ int main(int argc, char* argv[]) { std::string krakenDir = argv[0]; krakenDir = strSlice(krakenDir, 0, -(std::string("kraken").length()+1)); includePaths.push_back(krakenDir + "stdlib/"); //Add the stdlib directory that exists in the same directory as the kraken executable to the path - std::string programName = argv[1]; - std::string grammerFileString = argv[2]; - std::string outputName = argv[3]; + + std::string grammerFileString = "../krakenGrammer.kgm"; + std::string programName; + std::string outputName; + if (argc > 3) { + grammerFileString = argv[1]; + programName = argv[2]; + outputName = argv[3]; + } else if (argc == 3) { + programName = argv[1]; + outputName = argv[2]; + } else { + programName = argv[1]; + outputName = join(slice(split(programName, '.'), 0, -2), "."); // without extension + } std::ifstream grammerInFile, compiledGrammerInFile; std::ofstream compiledGrammerOutFile; @@ -147,7 +161,9 @@ int main(int argc, char* argv[]) { std::cout << "\nParsing" << std::endl; - Importer importer(&parser, includePaths); + std::cout << "\n output name: " << outputName << std::endl; + std::cout << "\n program name: " << programName << std::endl; + Importer importer(&parser, includePaths, outputName); // Output name for directory to put stuff in for (auto i : includePaths) std::cout << i << std::endl; diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index edcece1..6b34257 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -18,6 +18,7 @@ ASTTransformation::ASTTransformation(Importer *importerIn) { languageLevelOperators["--"].push_back(new NodeTree("function", ASTData(function, Symbol("--", true), NULL))); languageLevelOperators["++"].push_back(new NodeTree("function", ASTData(function, Symbol("++", true), NULL))); languageLevelOperators["=="].push_back(new NodeTree("function", ASTData(function, Symbol("==", true), new Type(boolean)))); + languageLevelOperators["!="].push_back(new NodeTree("function", ASTData(function, Symbol("!=", true), new Type(boolean)))); languageLevelOperators["<="].push_back(new NodeTree("function", ASTData(function, Symbol("<=", true), new Type(boolean)))); languageLevelOperators[">="].push_back(new NodeTree("function", ASTData(function, Symbol(">=", true), new Type(boolean)))); languageLevelOperators["<"].push_back(new NodeTree("function", ASTData(function, Symbol("<", true), new Type(boolean)))); diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 00dae33..8b58b2b 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -11,11 +11,12 @@ void CGenerator::generateCompSet(std::map*> ASTs, //Generate an entire set of files std::string buildString = "#!/bin/sh\ncc -std=c99 "; std::cout << "\n\n =====GENERATE PASS===== \n\n" << std::endl; - if (mkdir(("./" + outputName).c_str(), 0755)) { - std::cerr << "\n\n =====GENERATE PASS===== \n\n" << std::endl; - std::cerr << "Could not make directory " << outputName << std::endl; - //throw "could not make directory "; - } + // This is made earlier now, as we want to put the dot files here too + //if (mkdir(("./" + outputName).c_str(), 0755)) { + //std::cerr << "\n\n =====GENERATE PASS===== \n\n" << std::endl; + //std::cerr << "Could not make directory " << outputName << std::endl; + ////throw "could not make directory "; + //} std::cout << "\n\nGenerate pass for: " << outputName << std::endl; buildString += outputName + ".c "; @@ -322,7 +323,17 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc case statement: return tabs() + generate(children[0], enclosingObject) + ";\n"; case if_statement: - output += "if (" + generate(children[0], enclosingObject) + ")\n\t" + generate(children[1], enclosingObject); + output += "if (" + generate(children[0], enclosingObject) + ")\n\t"; + // We have to see if the then statement is a regular single statement or a block. + // If it's a block, because it's also a statement a semicolon will be emitted even though + // we don't want it to be, as if (a) {b}; else {c}; is not legal C, but if (a) {b} else {c}; is. + if (children[1]->getChildren()[0]->getDataRef()->type == code_block) { + std::cout << "Then statement is a block, emitting the block not the statement so no trailing semicolon" << std::endl; + output += generate(children[1]->getChildren()[0], enclosingObject); + } else { + std::cout << "Then statement is a simple statement, regular emitting the statement so trailing semicolon" << std::endl; + output += generate(children[1], enclosingObject); + } if (children.size() > 2) output += " else " + generate(children[2], enclosingObject); return output; @@ -377,9 +388,10 @@ std::string CGenerator::generate(NodeTree* from, NodeTree* enc return "(" + generate(children[1], enclosingObject) + ")[" +generate(children[2],enclosingObject) + "]"; if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!=" || name == "<" || name == ">" || name == "%" || name == "+=" || name == "-=" || name == "*=" || name == "/=" || name == "||" - || name == "&&") + || name == "&&") { + std::cout << "THIS IS IT NAME: " << name << std::endl; return "((" + generate(children[1], enclosingObject) + ")" + name + "(" + generate(children[2], enclosingObject) + "))"; - else if (name == "." || name == "->") { + } else if (name == "." || name == "->") { if (children.size() == 1) return "/*dot operation with one child*/" + generate(children[0], enclosingObject) + "/*end one child*/"; //If this is accessing an actual function, find the function in scope and take the appropriate action. Probabally an object method diff --git a/src/Importer.cpp b/src/Importer.cpp index 309142a..eee9bdf 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -1,7 +1,8 @@ #include "Importer.h" -Importer::Importer(Parser* parserIn, std::vector includePaths) { +Importer::Importer(Parser* parserIn, std::vector includePaths, std::string outputNameIn) { //constructor + outputName = outputNameIn; parser = parserIn; this->includePaths = includePaths; ASTTransformer = new ASTTransformation(this); @@ -104,10 +105,10 @@ void Importer::import(std::string fileName) { std::ofstream outFileAST; for (importTriplet i : importedTrips) { - std::string outputName = i.name + "out"; - outFileAST.open((outputName + ".AST.dot").c_str()); + std::string outputFileName = outputName + "/" + i.name + "out"; + outFileAST.open((outputFileName + ".AST.dot").c_str()); if (!outFileAST.is_open()) { - std::cout << "Problem opening second output file " << outputName + ".AST.dot" << "\n"; + std::cout << "Problem opening second output file " << outputFileName + ".AST.dot" << "\n"; return; } if (i.ast) { @@ -125,7 +126,17 @@ NodeTree* Importer::parseAndTrim(std::string fileName) { std::ofstream outFile, outFileTransformed; - std::string outputName = fileName + "out"; + std::cout << "outputName " << outputName << std::endl; + std::cout << "fileName " << fileName << std::endl; + + if (mkdir(("./" + outputName).c_str(), 0755)) { + std::cerr << "\n\n =====IMPORTER===== \n\n" << std::endl; + std::cerr << "Could not make directory " << outputName << std::endl; + } + + auto pathPieces = split(fileName, '/'); + std::string outputFileName = outputName + "/" + pathPieces[pathPieces.size()-1] + "out"; + std::cout << "outputFileName " << outputFileName << std::endl; for (auto i : includePaths) { programInFile.open(i+fileName); @@ -139,15 +150,15 @@ NodeTree* Importer::parseAndTrim(std::string fileName) { return NULL; } - outFile.open(outputName); + outFile.open(outputFileName); if (!outFile.is_open()) { - std::cout << "Probelm opening output file " << outputName << "\n"; + std::cout << "Probelm opening output file " << outputFileName << "\n"; return NULL; } - outFileTransformed.open((outputName + ".transformed.dot").c_str()); + outFileTransformed.open((outputFileName + ".transformed.dot").c_str()); if (!outFileTransformed.is_open()) { - std::cout << "Probelm opening second output file " << outputName + ".transformed.dot" << "\n"; + std::cout << "Probelm opening second output file " << outputFileName + ".transformed.dot" << "\n"; return NULL; } @@ -189,6 +200,7 @@ NodeTree* Importer::parseAndTrim(std::string fileName) { } outFileTransformed.close(); + std::cout << "Returning parse tree" << std::endl; return parseTree; } diff --git a/src/Tester.cpp b/src/Tester.cpp index d2a2c9e..01f07b3 100644 --- a/src/Tester.cpp +++ b/src/Tester.cpp @@ -30,7 +30,7 @@ bool Tester::run(std::string path) { std::cout << "Testing: " << fileName << " with " << krakenInvocation << " and " << krakenGrammerLocation << std::endl; cleanExtras(path); - ssystem(krakenInvocation + " " + path + krakenExtention + " " + krakenGrammerLocation + " " + path); + ssystem(krakenInvocation + " " + path + krakenExtention + " " + path); ssystem(changePermissions + " " + path + sep + fileName + ".sh"); ssystem(cd + " " + path + "; " + "./" + fileName + ".sh"); ssystem(changePermissions + " " + path + sep + fileName); diff --git a/src/util.cpp b/src/util.cpp index 2679f8f..689af72 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -51,6 +51,7 @@ int findPerenEnd(std::string str, int i) { if (numHangingOpen == 0) return i; } + return -1; } std::vector split(const std::string &str, char delim) { diff --git a/tests/test_else.expected_results b/tests/test_else.expected_results new file mode 100644 index 0000000..87dfef2 --- /dev/null +++ b/tests/test_else.expected_results @@ -0,0 +1,2 @@ +Right +Right diff --git a/tests/test_else.krak b/tests/test_else.krak new file mode 100644 index 0000000..a9dd61e --- /dev/null +++ b/tests/test_else.krak @@ -0,0 +1,16 @@ +import io:*; + + +|int| main() { + if (1>2) { + println("Wrong"); + } else { + println("Right"); + } + if (3>4) + println("Wrong"); + else + println("Right"); +} + + diff --git a/tests/test_nequals.expected_results b/tests/test_nequals.expected_results new file mode 100644 index 0000000..eb10e6d --- /dev/null +++ b/tests/test_nequals.expected_results @@ -0,0 +1 @@ +Correct diff --git a/tests/test_nequals.krak b/tests/test_nequals.krak new file mode 100644 index 0000000..98eb56f --- /dev/null +++ b/tests/test_nequals.krak @@ -0,0 +1,10 @@ +import io:*; + + +|int| main() { + if (1 != 2) + println("Correct"); +} + + +