Merge branch 'master' of https://github.com/Limvot/kraken
Added Christopher Fadden as contributor
This commit is contained in:
@@ -6,6 +6,8 @@
|
|||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
#include "Parser.h"
|
#include "Parser.h"
|
||||||
#include "NodeTree.h"
|
#include "NodeTree.h"
|
||||||
#include "ASTData.h"
|
#include "ASTData.h"
|
||||||
@@ -18,7 +20,7 @@ class ASTTransformation;
|
|||||||
|
|
||||||
class Importer {
|
class Importer {
|
||||||
public:
|
public:
|
||||||
Importer(Parser* parserIn, std::vector<std::string> includePaths);
|
Importer(Parser* parserIn, std::vector<std::string> includePaths, std::string outputName);
|
||||||
~Importer();
|
~Importer();
|
||||||
void import(std::string fileName);
|
void import(std::string fileName);
|
||||||
NodeTree<ASTData>* getUnit(std::string fileName);
|
NodeTree<ASTData>* getUnit(std::string fileName);
|
||||||
@@ -27,6 +29,7 @@ class Importer {
|
|||||||
void registerAST(std::string name, NodeTree<ASTData>* ast, NodeTree<Symbol>* syntaxTree);
|
void registerAST(std::string name, NodeTree<ASTData>* ast, NodeTree<Symbol>* syntaxTree);
|
||||||
std::map<std::string, NodeTree<ASTData>*> getASTMap();
|
std::map<std::string, NodeTree<ASTData>*> getASTMap();
|
||||||
private:
|
private:
|
||||||
|
std::string outputName;
|
||||||
ASTTransformation *ASTTransformer;
|
ASTTransformation *ASTTransformer;
|
||||||
struct importTriplet {
|
struct importTriplet {
|
||||||
std::string name;
|
std::string name;
|
||||||
@@ -41,4 +44,4 @@ class Importer {
|
|||||||
std::map<std::string, NodeTree<ASTData>*> imported;
|
std::map<std::string, NodeTree<ASTData>*> imported;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -50,14 +50,4 @@ bool subset(std::set<T> a, std::set<T> b) {
|
|||||||
return false;
|
return false;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
/*
|
|
||||||
std::vector<std::string> split(std::string str, char delim) {
|
|
||||||
std::stringstream stream(str);
|
|
||||||
std::string item;
|
|
||||||
std::vector<std::string> results;
|
|
||||||
while(std::getline(stream, item, delim))
|
|
||||||
results.push_back(item);
|
|
||||||
return results;
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
26
main.cpp
26
main.cpp
@@ -24,7 +24,9 @@ int main(int argc, char* argv[]) {
|
|||||||
includePaths.push_back(""); //Local
|
includePaths.push_back(""); //Local
|
||||||
|
|
||||||
if (argc <= 1) {
|
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;
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -64,9 +66,21 @@ int main(int argc, char* argv[]) {
|
|||||||
std::string krakenDir = argv[0];
|
std::string krakenDir = argv[0];
|
||||||
krakenDir = strSlice(krakenDir, 0, -(std::string("kraken").length()+1));
|
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
|
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 grammerFileString = "../krakenGrammer.kgm";
|
||||||
std::string outputName = argv[3];
|
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::ifstream grammerInFile, compiledGrammerInFile;
|
||||||
std::ofstream compiledGrammerOutFile;
|
std::ofstream compiledGrammerOutFile;
|
||||||
@@ -147,7 +161,9 @@ int main(int argc, char* argv[]) {
|
|||||||
|
|
||||||
std::cout << "\nParsing" << std::endl;
|
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)
|
for (auto i : includePaths)
|
||||||
std::cout << i << std::endl;
|
std::cout << i << std::endl;
|
||||||
|
|||||||
@@ -18,6 +18,7 @@ ASTTransformation::ASTTransformation(Importer *importerIn) {
|
|||||||
languageLevelOperators["--"].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol("--", true), NULL)));
|
languageLevelOperators["--"].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol("--", true), NULL)));
|
||||||
languageLevelOperators["++"].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol("++", true), NULL)));
|
languageLevelOperators["++"].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol("++", true), NULL)));
|
||||||
languageLevelOperators["=="].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol("==", true), new Type(boolean))));
|
languageLevelOperators["=="].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol("==", true), new Type(boolean))));
|
||||||
|
languageLevelOperators["!="].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol("!=", true), new Type(boolean))));
|
||||||
languageLevelOperators["<="].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol("<=", true), new Type(boolean))));
|
languageLevelOperators["<="].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol("<=", true), new Type(boolean))));
|
||||||
languageLevelOperators[">="].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol(">=", true), new Type(boolean))));
|
languageLevelOperators[">="].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol(">=", true), new Type(boolean))));
|
||||||
languageLevelOperators["<"].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol("<", true), new Type(boolean))));
|
languageLevelOperators["<"].push_back(new NodeTree<ASTData>("function", ASTData(function, Symbol("<", true), new Type(boolean))));
|
||||||
|
|||||||
@@ -11,11 +11,12 @@ void CGenerator::generateCompSet(std::map<std::string, NodeTree<ASTData>*> ASTs,
|
|||||||
//Generate an entire set of files
|
//Generate an entire set of files
|
||||||
std::string buildString = "#!/bin/sh\ncc -std=c99 ";
|
std::string buildString = "#!/bin/sh\ncc -std=c99 ";
|
||||||
std::cout << "\n\n =====GENERATE PASS===== \n\n" << std::endl;
|
std::cout << "\n\n =====GENERATE PASS===== \n\n" << std::endl;
|
||||||
if (mkdir(("./" + outputName).c_str(), 0755)) {
|
// This is made earlier now, as we want to put the dot files here too
|
||||||
std::cerr << "\n\n =====GENERATE PASS===== \n\n" << std::endl;
|
//if (mkdir(("./" + outputName).c_str(), 0755)) {
|
||||||
std::cerr << "Could not make directory " << outputName << std::endl;
|
//std::cerr << "\n\n =====GENERATE PASS===== \n\n" << std::endl;
|
||||||
//throw "could not make directory ";
|
//std::cerr << "Could not make directory " << outputName << std::endl;
|
||||||
}
|
////throw "could not make directory ";
|
||||||
|
//}
|
||||||
|
|
||||||
std::cout << "\n\nGenerate pass for: " << outputName << std::endl;
|
std::cout << "\n\nGenerate pass for: " << outputName << std::endl;
|
||||||
buildString += outputName + ".c ";
|
buildString += outputName + ".c ";
|
||||||
@@ -322,7 +323,17 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
case statement:
|
case statement:
|
||||||
return tabs() + generate(children[0], enclosingObject) + ";\n";
|
return tabs() + generate(children[0], enclosingObject) + ";\n";
|
||||||
case if_statement:
|
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)
|
if (children.size() > 2)
|
||||||
output += " else " + generate(children[2], enclosingObject);
|
output += " else " + generate(children[2], enclosingObject);
|
||||||
return output;
|
return output;
|
||||||
@@ -377,9 +388,10 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
return "(" + generate(children[1], enclosingObject) + ")[" +generate(children[2],enclosingObject) + "]";
|
return "(" + generate(children[1], enclosingObject) + ")[" +generate(children[2],enclosingObject) + "]";
|
||||||
if (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 == ">" || 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) + "))";
|
return "((" + generate(children[1], enclosingObject) + ")" + name + "(" + generate(children[2], enclosingObject) + "))";
|
||||||
else if (name == "." || name == "->") {
|
} else if (name == "." || name == "->") {
|
||||||
if (children.size() == 1)
|
if (children.size() == 1)
|
||||||
return "/*dot operation with one child*/" + generate(children[0], enclosingObject) + "/*end one child*/";
|
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
|
//If this is accessing an actual function, find the function in scope and take the appropriate action. Probabally an object method
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
#include "Importer.h"
|
#include "Importer.h"
|
||||||
|
|
||||||
Importer::Importer(Parser* parserIn, std::vector<std::string> includePaths) {
|
Importer::Importer(Parser* parserIn, std::vector<std::string> includePaths, std::string outputNameIn) {
|
||||||
//constructor
|
//constructor
|
||||||
|
outputName = outputNameIn;
|
||||||
parser = parserIn;
|
parser = parserIn;
|
||||||
this->includePaths = includePaths;
|
this->includePaths = includePaths;
|
||||||
ASTTransformer = new ASTTransformation(this);
|
ASTTransformer = new ASTTransformation(this);
|
||||||
@@ -104,10 +105,10 @@ void Importer::import(std::string fileName) {
|
|||||||
|
|
||||||
std::ofstream outFileAST;
|
std::ofstream outFileAST;
|
||||||
for (importTriplet i : importedTrips) {
|
for (importTriplet i : importedTrips) {
|
||||||
std::string outputName = i.name + "out";
|
std::string outputFileName = outputName + "/" + i.name + "out";
|
||||||
outFileAST.open((outputName + ".AST.dot").c_str());
|
outFileAST.open((outputFileName + ".AST.dot").c_str());
|
||||||
if (!outFileAST.is_open()) {
|
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;
|
return;
|
||||||
}
|
}
|
||||||
if (i.ast) {
|
if (i.ast) {
|
||||||
@@ -125,7 +126,17 @@ NodeTree<Symbol>* Importer::parseAndTrim(std::string fileName) {
|
|||||||
std::ofstream outFile, outFileTransformed;
|
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) {
|
for (auto i : includePaths) {
|
||||||
programInFile.open(i+fileName);
|
programInFile.open(i+fileName);
|
||||||
@@ -139,15 +150,15 @@ NodeTree<Symbol>* Importer::parseAndTrim(std::string fileName) {
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
outFile.open(outputName);
|
outFile.open(outputFileName);
|
||||||
if (!outFile.is_open()) {
|
if (!outFile.is_open()) {
|
||||||
std::cout << "Probelm opening output file " << outputName << "\n";
|
std::cout << "Probelm opening output file " << outputFileName << "\n";
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
outFileTransformed.open((outputName + ".transformed.dot").c_str());
|
outFileTransformed.open((outputFileName + ".transformed.dot").c_str());
|
||||||
if (!outFileTransformed.is_open()) {
|
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;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -189,6 +200,7 @@ NodeTree<Symbol>* Importer::parseAndTrim(std::string fileName) {
|
|||||||
}
|
}
|
||||||
outFileTransformed.close();
|
outFileTransformed.close();
|
||||||
|
|
||||||
|
std::cout << "Returning parse tree" << std::endl;
|
||||||
return parseTree;
|
return parseTree;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ bool Tester::run(std::string path) {
|
|||||||
std::cout << "Testing: " << fileName << " with " << krakenInvocation << " and " << krakenGrammerLocation << std::endl;
|
std::cout << "Testing: " << fileName << " with " << krakenInvocation << " and " << krakenGrammerLocation << std::endl;
|
||||||
|
|
||||||
cleanExtras(path);
|
cleanExtras(path);
|
||||||
ssystem(krakenInvocation + " " + path + krakenExtention + " " + krakenGrammerLocation + " " + path);
|
ssystem(krakenInvocation + " " + path + krakenExtention + " " + path);
|
||||||
ssystem(changePermissions + " " + path + sep + fileName + ".sh");
|
ssystem(changePermissions + " " + path + sep + fileName + ".sh");
|
||||||
ssystem(cd + " " + path + "; " + "./" + fileName + ".sh");
|
ssystem(cd + " " + path + "; " + "./" + fileName + ".sh");
|
||||||
ssystem(changePermissions + " " + path + sep + fileName);
|
ssystem(changePermissions + " " + path + sep + fileName);
|
||||||
|
|||||||
@@ -51,6 +51,7 @@ int findPerenEnd(std::string str, int i) {
|
|||||||
if (numHangingOpen == 0)
|
if (numHangingOpen == 0)
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<std::string> split(const std::string &str, char delim) {
|
std::vector<std::string> split(const std::string &str, char delim) {
|
||||||
|
|||||||
2
tests/test_else.expected_results
Normal file
2
tests/test_else.expected_results
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
Right
|
||||||
|
Right
|
||||||
16
tests/test_else.krak
Normal file
16
tests/test_else.krak
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import io:*;
|
||||||
|
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
if (1>2) {
|
||||||
|
println("Wrong");
|
||||||
|
} else {
|
||||||
|
println("Right");
|
||||||
|
}
|
||||||
|
if (3>4)
|
||||||
|
println("Wrong");
|
||||||
|
else
|
||||||
|
println("Right");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
1
tests/test_nequals.expected_results
Normal file
1
tests/test_nequals.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Correct
|
||||||
10
tests/test_nequals.krak
Normal file
10
tests/test_nequals.krak
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
import io:*;
|
||||||
|
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
if (1 != 2)
|
||||||
|
println("Correct");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Reference in New Issue
Block a user