From 62933af8f8f8bf65e46afabd4fdea0cceaae6827 Mon Sep 17 00:00:00 2001 From: Nathan Braswell Date: Sun, 19 Jan 2014 18:20:52 -0500 Subject: [PATCH] Basic structures work, prep work for function pointers and other stuff,a couple of bugs fixed. --- include/State.h | 1 + include/util.h | 3 +++ krakenGrammer.kgm | 8 +++--- main.cpp | 5 ++-- src/ASTTransformation.cpp | 56 ++++++++++++++++++++++++++++++--------- src/CGenerator.cpp | 16 ++++++++--- src/Importer.cpp | 1 + src/RNGLRParser.cpp | 1 + src/RegEx.cpp | 3 +-- src/State.cpp | 4 +++ src/Type.cpp | 3 +++ src/util.cpp | 19 +++++++++++++ 12 files changed, 95 insertions(+), 25 deletions(-) diff --git a/include/State.h b/include/State.h index 7a6a52c..13bd3e0 100644 --- a/include/State.h +++ b/include/State.h @@ -33,6 +33,7 @@ class State { void addParents(std::vector* parents); std::vector* getParents(); std::vector* getDeepParents(int depth); + int getNumber(); std::vector basis; diff --git a/include/util.h b/include/util.h index 4cf10a6..7e95b9e 100644 --- a/include/util.h +++ b/include/util.h @@ -8,10 +8,13 @@ #include #include #include +#include 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); int findPerenEnd(std::string str, int i); +std::vector split(const std::string &str, char delim); +std::string join(const std::vector &strVec, std::string joinStr); #endif diff --git a/krakenGrammer.kgm b/krakenGrammer.kgm index faa26eb..610816d 100644 --- a/krakenGrammer.kgm +++ b/krakenGrammer.kgm @@ -56,8 +56,7 @@ code_block = "{" WS statement_list WS "}" ; statement_list = statement_list WS statement | statement ; statement = if_statement | while_loop | for_loop | return_statement WS ";" | boolean_expression WS ";" | assignment_statement WS ";" | declaration_statement WS ";" | code_block | if_comp | simple_passthrough ; -function_call = scope identifier "\(" WS opt_parameter_list WS "\)" ; -scope = scope identifier "::" | ; +function_call = unarad "\(" WS opt_parameter_list WS "\)" ; boolean_expression = boolean_expression WS "\|\|" WS and_boolean_expression | and_boolean_expression ; and_boolean_expression = and_boolean_expression "&&" bool_exp | bool_exp ; @@ -68,10 +67,11 @@ expression = expression WS "<<" WS term | expression WS ">>" WS shiftand | shift shiftand = shiftand WS "-" WS term | shiftand WS "\+" WS term | term ; term = term WS forward_slash WS factor | term WS "\*" WS factor | term WS "%" WS factor | factor ; factor = "\+\+" WS unarad | unarad WS "\+\+" | "--" WS unarad | unarad WS "--" | "\+" WS unarad | "-" WS unarad | "!" WS unarad | "~" WS unarad | "\(" WS type WS "\)" WS unarad | "\*" WS unarad | "&" WS unarad | unarad ; -unarad = number | identifier | function_call | bool | string | character | "\(" WS boolean_expression WS "\)" ; +unarad = number | identifier | function_call | bool | string | character | "\(" WS boolean_expression WS "\)" | access_operation ; number = integer | float | double ; +access_operation = expression "." identifier | expression "->" identifier ; -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 = factor WS "=" WS boolean_expression | factor WS "\+=" WS boolean_expression | factor WS "-=" WS boolean_expression | factor WS "\*=" WS boolean_expression | factor WS "/=" WS boolean_expression ; declaration_statement = type WS identifier WS "=" WS boolean_expression | type WS identifier ; alphanumeric = alphanumeric numeric | alphanumeric alpha | numeric | alpha ; diff --git a/main.cpp b/main.cpp index 9ca06ef..c0f6036 100644 --- a/main.cpp +++ b/main.cpp @@ -104,14 +104,15 @@ int main(int argc, char* argv[]) { compiledGrammerOutFile.open(grammerFileString + ".comp", std::ios::binary); if (!compiledGrammerOutFile.is_open()) std::cout << "Could not open compiled file to write either!" << std::endl; - compiledGrammerOutFile.write("KRAK", sizeof(char)*4); + compiledGrammerOutFile.write("KRAK", sizeof(char)*4); //Let us know when we load it that this is a kraken grammer file, but don't write out + compiledGrammerOutFile.flush(); // the grammer txt until we create the set, so that if we fail creating it it won't look valid + parser.createStateSet(); int* intBuffer = new int; *intBuffer = grammerInputFileString.length()+1; compiledGrammerOutFile.write((char*)intBuffer, sizeof(int)); delete intBuffer; compiledGrammerOutFile.write(grammerInputFileString.c_str(), grammerInputFileString.length()+1); //Don't forget null terminator - parser.createStateSet(); parser.exportTable(compiledGrammerOutFile); compiledGrammerOutFile.close(); } diff --git a/src/ASTTransformation.cpp b/src/ASTTransformation.cpp index 85a0cc1..0543fb1 100644 --- a/src/ASTTransformation.cpp +++ b/src/ASTTransformation.cpp @@ -42,6 +42,8 @@ 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(); } else if (name == "interpreter_directive") { newNode = new NodeTree(name, ASTData(interpreter_directive)); @@ -56,19 +58,31 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree 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]); + //Make sure we get the entire name + std::string lookupName = concatSymbolTree(from); //std::cout << "scope lookup from identifier" << std::endl; newNode = scopeLookup(scope, lookupName); if (newNode == NULL) { std::cout << "scope lookup error! Could not find " << lookupName << std::endl; throw "LOOKUP ERROR: " + lookupName; + } else if (newNode->getDataRef()->symbol.getName() !=lookupName) { + //This happens when the lookup name denotes a member of an object, i.e. obj.foo + //The newNode points to obj, not foo. } //newNode = new NodeTree(name, ASTData(identifier, Symbol(concatSymbolTree(children[0]), true))); } else if (name == "type_def") { std::string typeAlias = concatSymbolTree(children[0]); - newNode = new NodeTree(name, ASTData(type_def, Symbol(typeAlias, true, typeAlias), typeFromString(concatSymbolTree(children[1]), scope))); + //If it is an alisis of a type + if (children[1]->getData().getName() == "type") { + newNode = new NodeTree(name, ASTData(type_def, Symbol(typeAlias, true, typeAlias), typeFromString(concatSymbolTree(children[1]), scope))); + skipChildren.insert(1); //Don't want any children, it's unnecessary for ailising + } else { //Is a struct or class + newNode = new NodeTree(name, ASTData(type_def, Symbol(typeAlias, true, typeAlias))); + newNode->getDataRef()->valueType = new Type(newNode); //Type is self-referential since this is the definition + } scope->getDataRef()->scope[typeAlias] = newNode; - return newNode; + skipChildren.insert(0); //Identifier lookup will be ourselves, as we just added ourselves to the scope + //return newNode; } else if (name == "function") { std::string functionName = concatSymbolTree(children[1]); newNode = new NodeTree(name, ASTData(function, Symbol(functionName, true), typeFromString(concatSymbolTree(children[0]), scope))); @@ -108,7 +122,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree return transform(children[0], scope); //Just a promoted term, so do child } //Here's the order of ops stuff - } else if (name == "expression" || name == "shiftand" || name == "term" || name == "unarad") { //unarad can ride through, it should always just be a promoted child + } else if (name == "expression" || name == "shiftand" || name == "term" || name == "unarad" || name == "access_operation") { //unarad can ride through, it should always just be a promoted child //If this is an actual part of an expression, not just a premoted child if (children.size() > 2) { std::string functionCallName = concatSymbolTree(children[1]); @@ -187,8 +201,18 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree // newIdentifier->getDataRef()->valueType = Type(concatSymbolTree(children[0]));//set the type of the identifier std::string newIdentifierStr = concatSymbolTree(children[1]); std::string typeString = concatSymbolTree(children[0]);//Get the type (left child) and set our new identifer to be that type - NodeTree* newIdentifier = new NodeTree("identifier", ASTData(identifier, Symbol(newIdentifierStr, true), typeFromString(typeString, scope))); + Type* identifierType = typeFromString(typeString, scope); + NodeTree* newIdentifier = new NodeTree("identifier", ASTData(identifier, Symbol(newIdentifierStr, true), identifierType)); scope->getDataRef()->scope[newIdentifierStr] = newIdentifier; + //Now we don't do this thing + // if (identifierType->typeDefinition) { + // //Is a custom type. Populate this declaration's scope with it's inner declarations + // std::vector*> definitions = identifierType->typeDefinition->getChildren(); + // for (auto i : definitions) { + // //Point to the identifier. May need to change so it points to the declaration or something, with new declarations..... + // newIdentifier->getDataRef()->scope[i->get(0)->getDataRef()->symbol.getName()] = i->get(0); //make each declaration's name point to it's definition, like above + // } + // } newNode->addChild(newIdentifier); skipChildren.insert(0); //These, the type and the identifier, have been taken care of. @@ -200,8 +224,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree } else if (name == "simple_passthrough") { newNode = new NodeTree(name, ASTData(simple_passthrough)); } else if (name == "function_call") { - //children[0] is scope - std::string functionCallName = concatSymbolTree(children[1]); + std::string functionCallName = concatSymbolTree(children[0]); newNode = new NodeTree(functionCallName, ASTData(function_call, Symbol(functionCallName, true))); //std::cout << "scope lookup from function_call" << std::endl; NodeTree* function = scopeLookup(scope, functionCallName); @@ -210,7 +233,7 @@ NodeTree* ASTTransformation::transform(NodeTree* from, NodeTree throw "LOOKUP ERROR: " + functionCallName; } newNode->addChild(function); - skipChildren.insert(1); + skipChildren.insert(0); } else if (name == "parameter") { return transform(children[0], scope); //Don't need a parameter node, just the value } else if (name == "parameter") { @@ -261,12 +284,18 @@ std::string ASTTransformation::concatSymbolTree(NodeTree* root) { } NodeTree* ASTTransformation::scopeLookup(NodeTree* scope, std::string lookup) { - //Seach the map + //First, if it is a struct or object, get it's base. + std::vector splitString = split(lookup, '.'); + if (splitString.size() > 1) { + std::string base = splitString[0]; + // NodeTree* baseDef = scopeLookup(scope, base); + // splitString.erase(splitString.begin()); //Get rid of the base in the split str + // //Now the base is the scope. + // return scopeLookup(baseDef, join(splitString, ".")); //So the joined version doesn't have the base. + return scopeLookup(scope, base); + } + //Search the map auto scopeMap = scope->getDataRef()->scope; - //std::cout << "scope size: " << scopeMap.size() << ", scope from " << scope->getName() << std::endl; - // for (auto i = scopeMap.begin(); i != scopeMap.end(); i++) - // std::cout << i->first << " : " << i-> second << " - " << i->second->getName() << std::endl; - auto elementIterator = scopeMap.find(lookup); if (elementIterator != scopeMap.end()) { // std::cout << "lookup of " << lookup << " succeded in first scope!" << std::endl; @@ -280,6 +309,7 @@ NodeTree* ASTTransformation::scopeLookup(NodeTree* scope, std: return scopeLookup(enclosingIterator->second, lookup); } //std::cout << "upper scope does not exist" << std::endl; + std::cout << "could not find " << lookup << std::endl; return NULL; } diff --git a/src/CGenerator.cpp b/src/CGenerator.cpp index 3257091..5d88a66 100644 --- a/src/CGenerator.cpp +++ b/src/CGenerator.cpp @@ -87,7 +87,15 @@ std::string CGenerator::generate(NodeTree* from) { case identifier: return data.symbol.getName(); case type_def: - return "typedef " + ValueTypeToCType(data.valueType) + " " + data.symbol.getName() + ";"; + if (children.size() == 0) { + return "typedef " + ValueTypeToCType(data.valueType) + " " + data.symbol.getName() + ";"; + } else { + std::string objectString = "typedef struct __struct_dummy_" + data.symbol.getName() + "__ {\n"; + for (int i = 0; i < children.size(); i++) + objectString += generate(children[i]) + "\n"; + objectString += "} " + data.symbol.getName() + ";"; + return objectString; + } case function: output += "\n" + ValueTypeToCType(data.valueType) + " " + data.symbol.getName() + "("; for (int i = 0; i < children.size()-1; i++) { @@ -155,10 +163,10 @@ std::string CGenerator::generate(NodeTree* from) { return "*(" + generate(children[1]) + ")"; if (name == "+" || name == "-" || 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]) + "))"; - } + else if (name == "." || name == "->") + return "((" + generate(children[1]) + ")" + name + generate(children[2]) + ")"; output += data.symbol.getName() + "("; for (int i = 1; i < children.size(); i++) //children[0] is the declaration if (i < children.size()-1) diff --git a/src/Importer.cpp b/src/Importer.cpp index 76d8231..d158470 100644 --- a/src/Importer.cpp +++ b/src/Importer.cpp @@ -30,6 +30,7 @@ Importer::Importer(Parser* parserIn) { collapseSymbols.push_back(Symbol("typed_parameter_list", false)); collapseSymbols.push_back(Symbol("unorderd_list_part", false)); collapseSymbols.push_back(Symbol("if_comp_pred", false)); + collapseSymbols.push_back(Symbol("declaration_block", false)); } Importer::~Importer() { diff --git a/src/RNGLRParser.cpp b/src/RNGLRParser.cpp index 274558f..f42f189 100644 --- a/src/RNGLRParser.cpp +++ b/src/RNGLRParser.cpp @@ -377,6 +377,7 @@ void RNGLRParser::addStates(std::vector< State* >* stateSets, State* state, std: void RNGLRParser::addStateReductionsToTable(State* state) { std::vector* currStateTotal = state->getTotal(); + //std::cout << currStateTotal->size() << "::" << state->getNumber() << std::endl; for (std::vector::size_type i = 0; i < currStateTotal->size(); i++) { //See if reduce //Also, this really only needs to be done for the state's basis, but we're already iterating through, so... diff --git a/src/RegEx.cpp b/src/RegEx.cpp index 5a408a6..18acabe 100644 --- a/src/RegEx.cpp +++ b/src/RegEx.cpp @@ -223,8 +223,7 @@ void RegEx::test() { } { RegEx re("bbb((bba+)|(ba+))*a*((a+b)|(a+bb)|(a+))*bbb") ; - std::cout << re.longMatch("bbbababbbaaaaaaaaaaaaaaaaaaabbb") << std::endl; - + assert(re.longMatch("bbbababbbaaaaaaaaaaaaaaaaaaabbb") == 9); } std::cout << "RegEx tests pass\n"; diff --git a/src/State.cpp b/src/State.cpp index 012d468..fc8621b 100644 --- a/src/State.cpp +++ b/src/State.cpp @@ -158,4 +158,8 @@ std::vector* State::getDeepParents(int depth) { recursiveParents->insert(recursiveParents->end(), recursiveParentsToAdd->begin(), recursiveParentsToAdd->end()); } return recursiveParents; +} + +int State::getNumber() { + return number; } \ No newline at end of file diff --git a/src/Type.cpp b/src/Type.cpp index 83b638f..613324d 100644 --- a/src/Type.cpp +++ b/src/Type.cpp @@ -3,16 +3,19 @@ Type::Type() { indirection = 0; baseType = none; + typeDefinition = NULL; } Type::Type(ValueType typeIn) { indirection = 0; baseType = typeIn; + typeDefinition = NULL; } Type::Type(ValueType typeIn, int indirectionIn) { indirection = indirectionIn; baseType = typeIn; + typeDefinition = NULL; } Type::Type(NodeTree* typeDefinitionIn) { diff --git a/src/util.cpp b/src/util.cpp index a08e776..cb1fa4c 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -52,3 +52,22 @@ int findPerenEnd(std::string str, int i) { return i; } } + +std::vector split(const std::string &str, char delim) { + std::stringstream ss(str); + std::string word; + std::vector splitVec; + while (std::getline(ss, word, delim)) + splitVec.push_back(word); + return splitVec; +} + +std::string join(const std::vector &strVec, std::string joinStr) { + if (strVec.size() == 0) + return ""; + std::string joinedStr = strVec[0]; + for (int i = 1; i < strVec.size(); i++) + joinedStr += joinStr + strVec[i]; + return joinedStr; +} +