From 6ad406e42de51e2184102d1c22133f4e08eae415 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Thu, 19 Dec 2013 10:39:36 -0600 Subject: [PATCH] Small fixes to the grammer, ASTTransformation and CGenerator. Should now be ready to begin implementation of multiple files, conditional inclusion, and code passthrough. --- include/CGenerator.h | 2 ++ include/util.h | 1 + krakenGrammer.kgm | 11 +++++------ main.cpp | 2 ++ src/ASTTransformation.cpp | 7 +++---- src/CGenerator.cpp | 9 ++++++--- src/util.cpp | 9 +++++++++ 7 files changed, 28 insertions(+), 13 deletions(-) diff --git a/include/CGenerator.h b/include/CGenerator.h index 9b43889..f18fadd 100644 --- a/include/CGenerator.h +++ b/include/CGenerator.h @@ -7,6 +7,8 @@ #include "NodeTree.h" #include "ASTData.h" +#include "util.h" + class CGenerator { public: diff --git a/include/util.h b/include/util.h index 2041601..42b3d8d 100644 --- a/include/util.h +++ b/include/util.h @@ -11,5 +11,6 @@ std::string intToString(int theInt); std::string replaceExEscape(std::string first, std::string search, std::string replace); +std::string strSlice(std::string str, int begin, int end); #endif diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index 386b738..63618c5 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -34,15 +34,14 @@ if_statement = "if" WS "\(" WS boolean_expression WS "\)" WS statement ; while_loop = "while" WS boolean_expression WS statement ; -for_update = "\(" WS statement_list WS "\)" ; -for_loop = "for" WS for_update WS statement ; +for_loop = "for" WS "\(" WS statement WS boolean_expression WS ";" WS statement WS "\)" WS statement ; -return_statement = "return" WS boolean_expression WS ";" ; +return_statement = "return" WS boolean_expression ; code_block = "{" WS statement_list WS "}" ; statement_list = statement_list WS statement | statement ; -statement = if_statement | while_loop | for_loop | return_statement | boolean_expression WS ";" | assignment_statement WS ";" | declaration_statement WS ";" | code_block ; +statement = if_statement | while_loop | for_loop | return_statement WS ";" | boolean_expression WS ";" | assignment_statement WS ";" | declaration_statement WS ";" | code_block ; function_call = scope identifier "\(" WS opt_parameter_list WS "\)" ; scope = scope identifier "::" | ; @@ -58,7 +57,7 @@ factor = "\+\+" WS unarad | unarad WS "\+\+" | "--" WS unarad | unarad WS "--" | unarad = number | identifier | function_call | bool | string | "\(" WS boolean_expression WS "\)" ; number = integer | float | double ; -assignment_statement = identifier WS "=" WS boolean_expression | identifier WS "+=" WS boolean_expression | identifier WS "-=" WS boolean_expression | identifier WS "\*=" WS boolean_expression | identifier WS "/=" WS boolean_expression ; +assignment_statement = identifier WS "=" WS boolean_expression | identifier WS "\+=" WS boolean_expression | identifier WS "-=" WS boolean_expression | identifier WS "\*=" WS boolean_expression | identifier WS "/=" WS boolean_expression ; declaration_statement = type WS identifier WS "=" WS boolean_expression ; alphanumeric = alphanumeric numeric | alphanumeric alpha | numeric | alpha ; @@ -70,4 +69,4 @@ double = sign numeric "." numeric | sign numeric "." numeric "d" ; bool = "true" | "false" | "True" | "False" ; alpha = "(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|_)+" ; numeric = "(0|1|2|3|4|5|6|7|8|9)+" ; -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)+\"" ; \ No newline at end of file +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)+\"" ; \ No newline at end of file diff --git a/main.cpp b/main.cpp index 0cce3f8..955a7c6 100644 --- a/main.cpp +++ b/main.cpp @@ -16,12 +16,14 @@ #include "ASTData.h" #include "CGenerator.h" +#include "util.h" int main(int argc, char* argv[]) { if (argc == 2 && std::string(argv[1]) == "--test") { StringReader::test(); RegEx::test(); Lexer::test(); + //std::cout << strSlice("123", 0, -1) << std::endl; return 0; } diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 2802b20..9ccd943 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -62,17 +62,16 @@ NodeTree* ASTTransformation::transform(NodeTree* from) { return transform(children[0]); //Just a promoted bool_exp, so do child } //Here's the order of ops stuff - } else if (name == "expression" || name == "shiftand" || name == "term" || name == "unarad") { + } else if (name == "expression" || name == "shiftand" || name == "term" || name == "factor" || name == "unarad") { //If this is an actual part of an expression, not just a premoted child if (children.size() > 1) { std::string functionCallName = concatSymbolTree(children[1]); + std::cout << functionCallName << std::endl; newNode = new NodeTree(functionCallName, ASTData(function_call, Symbol(functionCallName, true))); skipChildren.insert(1); } else { return transform(children[0]); //Just a promoted child, so do it instead } - } else if (name == "factor") { - return transform(children[0]); //Just a premoted number or function call or something, so use it instead } else if (name == "statement") { newNode = new NodeTree(name, ASTData(statement)); } else if (name == "if_statement") { @@ -92,7 +91,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from) { } else { //For assignments like += or *=, expand the syntatic sugar. NodeTree* lhs = transform(children[0]); - NodeTree* childCall = new NodeTree(assignFuncName, ASTData(function_call, Symbol(assignFuncName, true))); + NodeTree* childCall = new NodeTree(assignFuncName.substr(0,1), ASTData(function_call, Symbol(assignFuncName.substr(0,1), true))); childCall->addChild(lhs); childCall->addChild(transform(children[2])); newNode->addChild(lhs); diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 45e25e3..53575cf 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -58,10 +58,11 @@ std::string CGenerator::generate(NodeTree* from) { output += " else " + generate(children[2]); return output; case while_loop: - output += "if (" + generate(children[0]) + ")\n\t" + generate(children[1]); + output += "while (" + generate(children[0]) + ")\n\t" + generate(children[1]); return output; case for_loop: - output += "if (" + generate(children[0]) + ")\n\t" + generate(children[1]); + //The strSlice's are there to get ride of an unwanted return and an unwanted semicolon + output += "for (" + strSlice(generate(children[0]),0,-2) + generate(children[1]) + ";" + strSlice(generate(children[2]),0,-3) + ")\n\t" + generate(children[3]); return output; case return_statement: return "return " + generate(children[0]); @@ -74,7 +75,9 @@ std::string CGenerator::generate(NodeTree* from) { //Handle operators specially for now. Will later replace with //Inlined functions in the standard library std::string name = data.symbol.getName(); - if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!=" || name == "%") { + if (name == "++" || name == "--") + return generate(children[0]) + name; + if (name == "+" || name == "-" || name == "*" || name == "/" || name == "==" || name == ">=" || name == "<=" || name == "!=" || name == "<" || name == ">" || name == "%" || name == "+=" || name == "-=" || name == "*=" || name == "/=") { return "((" + generate(children[0]) + ")" + name + "(" + generate(children[1]) + "))"; } output += data.symbol.getName() + "("; diff --git a/src/util.cpp b/src/util.cpp index b71e6b0..ce48395 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -31,3 +31,12 @@ std::string replaceExEscape(std::string first, std::string search, std::string r } return first; } + +//String slicing is crazy useful. substr isn't bad, but slicing with negative indicies is wonderful +std::string strSlice(std::string str, int begin, int end) { + if (begin < 0) + begin += str.length()+1; + if (end < 0) + end += str.length()+1; + return str.substr(begin, end-begin); +}