Merge branch 'master' of https://www.github.com/Limvot/kraken
This commit is contained in:
@@ -2,13 +2,22 @@ cmake_minimum_required (VERSION 2.6)
|
|||||||
|
|
||||||
project(Kraken)
|
project(Kraken)
|
||||||
|
|
||||||
|
|
||||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||||
|
|
||||||
set( MY_INCLUDES ${PROJECT_SOURCE_DIR}/include)
|
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 src/Importer.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 src/Tester.cpp )
|
||||||
|
|
||||||
|
add_custom_target(STDLibCopy ALL)
|
||||||
|
add_custom_command(TARGET STDLibCopy POST_BUILD
|
||||||
|
COMMAND ${CMAKE_COMMAND} -E copy_directory
|
||||||
|
"${PROJECT_SOURCE_DIR}/stdlib"
|
||||||
|
"${PROJECT_BINARY_DIR}/stdlib")
|
||||||
|
|
||||||
include_directories( ${MY_INCLUDES} )
|
include_directories( ${MY_INCLUDES} )
|
||||||
|
|
||||||
add_executable(kraken ${MY_SOURCES})
|
add_executable(kraken ${MY_SOURCES})
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
21
LICENCE.md
Normal file
21
LICENCE.md
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2014 Nathan Christopher Braswell
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
10
future_features.txt
Normal file
10
future_features.txt
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
Declaration of a pointer and multiplication are ambigious!
|
||||||
|
( T* a; maybe either a declaration or a multiplication)
|
||||||
|
|
||||||
|
Fix destructors being placed after return.
|
||||||
|
Fix functions before declaration? (in class? (this is from an old file))
|
||||||
|
Template instantiation without explicit type param
|
||||||
|
Fix // comment right before top level function declaration. Something to do
|
||||||
|
with the return as /* comment */ does not have that problem
|
||||||
|
for in or for each loops
|
||||||
|
Traits on aliases, maybe that keep their old traits?
|
||||||
@@ -4,6 +4,9 @@
|
|||||||
#include <set>
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
|
#include <iterator>
|
||||||
|
#include <algorithm>
|
||||||
|
|
||||||
#include "Type.h"
|
#include "Type.h"
|
||||||
#include "ASTData.h"
|
#include "ASTData.h"
|
||||||
#include "NodeTransformation.h"
|
#include "NodeTransformation.h"
|
||||||
@@ -15,17 +18,46 @@ class ASTTransformation: public NodeTransformation<Symbol,ASTData> {
|
|||||||
public:
|
public:
|
||||||
ASTTransformation(Importer* importerIn);
|
ASTTransformation(Importer* importerIn);
|
||||||
~ASTTransformation();
|
~ASTTransformation();
|
||||||
|
|
||||||
|
//First pass defines all type_defs (objects and ailises)
|
||||||
|
NodeTree<ASTData>* firstPass(std::string fileName, NodeTree<Symbol>* parseTree);
|
||||||
|
std::set<std::string> parseTraits(NodeTree<Symbol>* traitsNode);
|
||||||
|
|
||||||
|
//Second pass defines data inside objects, outside declaration statements, and function prototpyes (since we have type_defs now)
|
||||||
|
void secondPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* parseTree);
|
||||||
|
void secondPassDoClassInsides(NodeTree<ASTData>* typeDef, std::vector<NodeTree<Symbol>*> typedefChildren, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
|
NodeTree<ASTData>* secondPassDeclaration(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
|
NodeTree<ASTData>* secondPassFunction(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
|
|
||||||
|
//Third pass redoes all imports to import the new function prototypes and identifiers
|
||||||
|
void thirdPass(NodeTree<ASTData>* ast);
|
||||||
|
|
||||||
|
//The fourth pass finishes up by doing all function bodies
|
||||||
|
void fourthPass(NodeTree<ASTData>* ast, NodeTree<Symbol>* parseTree);
|
||||||
|
NodeTree<ASTData>* searchScopeForFunctionDef(NodeTree<ASTData>* scope, NodeTree<Symbol>* parseTree, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
|
void fourthPassFunction(NodeTree<Symbol>* from, NodeTree<ASTData>* functionDef, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
|
|
||||||
virtual NodeTree<ASTData>* transform(NodeTree<Symbol>* from);
|
virtual NodeTree<ASTData>* transform(NodeTree<Symbol>* from);
|
||||||
NodeTree<ASTData>* transform(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::vector<Type> types = std::vector<Type>());
|
NodeTree<ASTData>* transform(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
std::vector<NodeTree<ASTData>*> transformChildren(std::vector<NodeTree<Symbol>*> children, std::set<int> skipChildren, NodeTree<ASTData>* scope, std::vector<Type> types);
|
std::vector<NodeTree<ASTData>*> transformChildren(std::vector<NodeTree<Symbol>*> children, std::set<int> skipChildren, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
std::vector<Type> mapNodesToTypes(std::vector<NodeTree<ASTData>*> nodes);
|
std::vector<Type> mapNodesToTypes(std::vector<NodeTree<ASTData>*> nodes);
|
||||||
std::string concatSymbolTree(NodeTree<Symbol>* root);
|
std::string concatSymbolTree(NodeTree<Symbol>* root);
|
||||||
NodeTree<ASTData>* scopeLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<NodeTree<ASTData>*> nodes);
|
NodeTree<ASTData>* doFunction(NodeTree<ASTData>* scope, std::string lookup, std::vector<NodeTree<ASTData>*> nodes, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
NodeTree<ASTData>* scopeLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type> types = std::vector<Type>());
|
|
||||||
Type* typeFromString(std::string type, NodeTree<ASTData>* scope);
|
NodeTree<ASTData>* functionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type> types);
|
||||||
|
NodeTree<ASTData>* templateFunctionLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<Type*> templateInstantiationTypes, std::vector<Type> types);
|
||||||
|
std::vector<NodeTree<ASTData>*> scopeLookup(NodeTree<ASTData>* scope, std::string lookup, bool includeModules = false);
|
||||||
|
|
||||||
|
Type* typeFromTypeNode(NodeTree<Symbol>* typeNode, NodeTree<ASTData>* scope, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
|
NodeTree<ASTData>* templateClassLookup(NodeTree<ASTData>* scope, std::string name, std::vector<Type*> templateInstantiationTypes);
|
||||||
|
NodeTree<ASTData>* findOrInstantiateFunctionTemplate(std::vector<NodeTree<Symbol>*> children, NodeTree<ASTData>* scope, std::vector<Type> types, std::map<std::string, Type*> templateTypeReplacements);
|
||||||
|
std::map<std::string, Type*> makeTemplateFunctionTypeMap(NodeTree<Symbol>* templateNode, std::vector<Type*> types);
|
||||||
|
std::vector<std::pair<std::string, std::set<std::string>>> makeTemplateNameTraitPairs(NodeTree<Symbol>* templateNode);
|
||||||
private:
|
private:
|
||||||
Importer * importer;
|
Importer * importer;
|
||||||
std::map<std::string, std::vector<NodeTree<ASTData>*>> languageLevelScope;
|
std::map<std::string, std::vector<NodeTree<ASTData>*>> languageLevelReservedWords;
|
||||||
|
std::map<std::string, std::vector<NodeTree<ASTData>*>> languageLevelOperators;
|
||||||
|
NodeTree<ASTData>* topScope; //maintained for templates that need to add themselves to the top scope no matter where they are instantiated
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "Type.h"
|
#include "Type.h"
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "Poset.h"
|
||||||
|
|
||||||
|
|
||||||
class CGenerator {
|
class CGenerator {
|
||||||
@@ -17,12 +18,14 @@ class CGenerator {
|
|||||||
CGenerator();
|
CGenerator();
|
||||||
~CGenerator();
|
~CGenerator();
|
||||||
void generateCompSet(std::map<std::string, NodeTree<ASTData>*> ASTs, std::string outputName);
|
void generateCompSet(std::map<std::string, NodeTree<ASTData>*> ASTs, std::string outputName);
|
||||||
|
std::string generateClassStruct(NodeTree<ASTData>* from);
|
||||||
std::string generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject = NULL);
|
std::string generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject = NULL);
|
||||||
|
std::string generateAliasChains(NodeTree<ASTData>* scopeNode, NodeTree<ASTData>* definition);
|
||||||
static std::string ValueTypeToCType(Type *type);
|
static std::string ValueTypeToCType(Type *type);
|
||||||
static std::string ValueTypeToCTypeDecoration(Type *type);
|
static std::string ValueTypeToCTypeDecoration(Type *type);
|
||||||
static std::string CifyFunctionName(std::string name);
|
static std::string CifyName(std::string name);
|
||||||
std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from);
|
std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype);
|
||||||
|
NodeTree<ASTData>* getMethodsObjectType(NodeTree<ASTData>* scope, std::string functionName);
|
||||||
std::string generatorString;
|
std::string generatorString;
|
||||||
private:
|
private:
|
||||||
std::string tabs();
|
std::string tabs();
|
||||||
|
|||||||
@@ -27,6 +27,7 @@ class GraphStructuredStack {
|
|||||||
void addEdge(NodeTree<int>* start, NodeTree<int>* end, NodeTree<Symbol>* edge);
|
void addEdge(NodeTree<int>* start, NodeTree<int>* end, NodeTree<Symbol>* edge);
|
||||||
void clear();
|
void clear();
|
||||||
|
|
||||||
|
std::vector<int> getFrontier(int frontier);
|
||||||
std::string toString();
|
std::string toString();
|
||||||
private:
|
private:
|
||||||
std::vector<std::vector<NodeTree<int>*>*> gss;
|
std::vector<std::vector<NodeTree<int>*>*> gss;
|
||||||
|
|||||||
@@ -14,13 +14,27 @@
|
|||||||
#include "CollapseTransformation.h"
|
#include "CollapseTransformation.h"
|
||||||
#include "ASTTransformation.h"
|
#include "ASTTransformation.h"
|
||||||
|
|
||||||
|
class ASTTransformation;
|
||||||
|
|
||||||
class Importer {
|
class Importer {
|
||||||
public:
|
public:
|
||||||
Importer(Parser* parserIn);
|
Importer(Parser* parserIn, std::vector<std::string> includePaths);
|
||||||
~Importer();
|
~Importer();
|
||||||
NodeTree<ASTData>* import(std::string fileName);
|
void import(std::string fileName);
|
||||||
|
NodeTree<ASTData>* getUnit(std::string fileName);
|
||||||
|
NodeTree<ASTData>* importFirstPass(std::string fileName);
|
||||||
|
NodeTree<Symbol>* parseAndTrim(std::string fileName);
|
||||||
|
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:
|
||||||
|
ASTTransformation *ASTTransformer;
|
||||||
|
struct importTriplet {
|
||||||
|
std::string name;
|
||||||
|
NodeTree<ASTData>* ast;
|
||||||
|
NodeTree<Symbol>* syntaxTree;
|
||||||
|
};
|
||||||
|
std::vector<importTriplet> importedTrips;
|
||||||
|
std::vector<std::string> includePaths;
|
||||||
Parser* parser;
|
Parser* parser;
|
||||||
std::vector<Symbol> removeSymbols;
|
std::vector<Symbol> removeSymbols;
|
||||||
std::vector<Symbol> collapseSymbols;
|
std::vector<Symbol> collapseSymbols;
|
||||||
|
|||||||
@@ -11,6 +11,7 @@
|
|||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
|
||||||
class ParseAction {
|
class ParseAction {
|
||||||
public:
|
public:
|
||||||
enum ActionType { INVALID, REDUCE, SHIFT, ACCEPT, REJECT };
|
enum ActionType { INVALID, REDUCE, SHIFT, ACCEPT, REJECT };
|
||||||
@@ -18,10 +19,11 @@ class ParseAction {
|
|||||||
ParseAction(ActionType action, ParseRule* reduceRule);
|
ParseAction(ActionType action, ParseRule* reduceRule);
|
||||||
ParseAction(ActionType action, int shiftState);
|
ParseAction(ActionType action, int shiftState);
|
||||||
~ParseAction();
|
~ParseAction();
|
||||||
bool const equalsExceptLookahead(const ParseAction &other);
|
bool const equalsExceptLookahead(const ParseAction &other) const;
|
||||||
bool const operator==(const ParseAction &other);
|
bool const operator==(const ParseAction &other) const;
|
||||||
bool const operator!=(const ParseAction &other);
|
bool const operator!=(const ParseAction &other) const;
|
||||||
std::string toString();
|
bool const operator<(const ParseAction &other) const;
|
||||||
|
std::string toString(bool printRuleLookahead = true);
|
||||||
static std::string actionToString(ActionType action);
|
static std::string actionToString(ActionType action);
|
||||||
|
|
||||||
ActionType action;
|
ActionType action;
|
||||||
|
|||||||
@@ -16,10 +16,10 @@ class ParseRule {
|
|||||||
ParseRule();
|
ParseRule();
|
||||||
ParseRule(Symbol leftHandle, int pointerIndex, std::vector<Symbol> &rightSide, std::vector<Symbol>* lookahead);
|
ParseRule(Symbol leftHandle, int pointerIndex, std::vector<Symbol> &rightSide, std::vector<Symbol>* lookahead);
|
||||||
~ParseRule();
|
~ParseRule();
|
||||||
const bool equalsExceptLookahead(const ParseRule &other);
|
const bool equalsExceptLookahead(const ParseRule &other) const;
|
||||||
bool const operator==(const ParseRule &other);
|
bool const operator==(const ParseRule &other) const;
|
||||||
bool const operator!=(const ParseRule &other);
|
bool const operator!=(const ParseRule &other) const;
|
||||||
|
bool const operator<(const ParseRule &other) const; //Used for ordering so we can put ParseRule's in sets, and also so that ParseActions will have an ordering
|
||||||
ParseRule* clone();
|
ParseRule* clone();
|
||||||
|
|
||||||
void setLeftHandle(Symbol leftHandle);
|
void setLeftHandle(Symbol leftHandle);
|
||||||
@@ -40,7 +40,7 @@ class ParseRule {
|
|||||||
void addLookahead(std::vector<Symbol>* lookahead);
|
void addLookahead(std::vector<Symbol>* lookahead);
|
||||||
std::vector<Symbol>* getLookahead();
|
std::vector<Symbol>* getLookahead();
|
||||||
|
|
||||||
std::string toString();
|
std::string toString(bool printLookahead = true);
|
||||||
std::string toDOT();
|
std::string toDOT();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
#include "Table.h"
|
#include "Table.h"
|
||||||
|
|
||||||
#include <queue>
|
#include <queue>
|
||||||
|
#include <set>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -36,8 +37,13 @@ class Parser {
|
|||||||
void importTable(char* tableData);
|
void importTable(char* tableData);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
std::vector<Symbol>* firstSet(Symbol token);
|
std::vector<Symbol> firstSet(Symbol token, std::vector<Symbol> avoidList = std::vector<Symbol>(), bool addNewTokens = true);
|
||||||
std::vector<Symbol>* firstSet(Symbol token, std::vector<Symbol> avoidList);
|
bool isNullable(Symbol token);
|
||||||
|
bool isNullableHelper(Symbol token, std::set<Symbol> done);
|
||||||
|
|
||||||
|
std::map<Symbol, std::vector<Symbol>> tokenFirstSet;
|
||||||
|
std::map<Symbol, bool> tokenNullable;
|
||||||
|
|
||||||
std::vector<Symbol>* incrementiveFollowSet(ParseRule* rule);
|
std::vector<Symbol>* incrementiveFollowSet(ParseRule* rule);
|
||||||
virtual void closure(State* state);
|
virtual void closure(State* state);
|
||||||
virtual void addStates(std::vector< State* >* stateSets, State* state, std::queue<State*>* toDo);
|
virtual void addStates(std::vector< State* >* stateSets, State* state, std::queue<State*>* toDo);
|
||||||
|
|||||||
126
include/Poset.h
Normal file
126
include/Poset.h
Normal file
@@ -0,0 +1,126 @@
|
|||||||
|
|
||||||
|
#ifndef POSET_H
|
||||||
|
#define POSET_H
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
#include <queue>
|
||||||
|
|
||||||
|
#include <cassert>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
class Poset {
|
||||||
|
public:
|
||||||
|
Poset();
|
||||||
|
~Poset();
|
||||||
|
void addRelationship(T first, T second);
|
||||||
|
void addVertex(T vertex);
|
||||||
|
bool zeroDependencies(T vertex);
|
||||||
|
std::set<T> getDependsOn(T dependency);
|
||||||
|
std::vector<T> getTopoSort();
|
||||||
|
static void test();
|
||||||
|
private:
|
||||||
|
//backing data structures
|
||||||
|
std::map<T, std::map<T,bool>> adjMatrix;
|
||||||
|
std::set<T> verticies;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
Poset<T>::Poset() {
|
||||||
|
//Nothing needed
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
Poset<T>::~Poset() {
|
||||||
|
//Ditto
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void Poset<T>::addRelationship(T first, T second) {
|
||||||
|
verticies.insert(first);
|
||||||
|
verticies.insert(second);
|
||||||
|
adjMatrix[first][second] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
void Poset<T>::addVertex(T vertex) {
|
||||||
|
verticies.insert(vertex);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
bool Poset<T>::zeroDependencies(T vertex) {
|
||||||
|
auto depMapItr = adjMatrix.find(vertex);
|
||||||
|
if (depMapItr == adjMatrix.end())
|
||||||
|
return true;
|
||||||
|
for (auto i : depMapItr->second)
|
||||||
|
if (i.second == true)
|
||||||
|
return false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
std::set<T> Poset<T>::getDependsOn(T dependency) {
|
||||||
|
std::set<T> vertsThatDependOn;
|
||||||
|
for (auto i : adjMatrix) {
|
||||||
|
auto depItr = i.second.find(dependency);
|
||||||
|
if (depItr != i.second.end() && depItr->second)
|
||||||
|
vertsThatDependOn.insert(i.first);
|
||||||
|
}
|
||||||
|
return vertsThatDependOn;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <class T>
|
||||||
|
std::vector<T> Poset<T>::getTopoSort() {
|
||||||
|
std::vector<T> sorted;
|
||||||
|
std::queue<T> toDo;
|
||||||
|
for (auto i : verticies)
|
||||||
|
if (zeroDependencies(i))
|
||||||
|
toDo.push(i);
|
||||||
|
while(!toDo.empty()) {
|
||||||
|
T current = toDo.front(); toDo.pop();
|
||||||
|
sorted.push_back(current);
|
||||||
|
for (T depOnCurrent : getDependsOn(current)) {
|
||||||
|
adjMatrix[depOnCurrent][current] = false; //Remove the edge to current, since current's now been taken care of
|
||||||
|
if (zeroDependencies(depOnCurrent))
|
||||||
|
toDo.push(depOnCurrent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sorted;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
//would make it just an int specilization, but then we get multiple definition complaints....
|
||||||
|
template<class T>
|
||||||
|
void Poset<T>::test() {
|
||||||
|
std::string result;
|
||||||
|
{
|
||||||
|
Poset<int> poset;
|
||||||
|
poset.addVertex(1000);
|
||||||
|
for (int i = 0; i < 20; i++)
|
||||||
|
poset.addRelationship(i,i+1);
|
||||||
|
result = "";
|
||||||
|
for (int i : poset.getTopoSort())
|
||||||
|
result += intToString(i) + " ";
|
||||||
|
//std::cout << result << std::endl;
|
||||||
|
assert(result == "20 1000 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0 "); //Note that sets do not have a set order, so this could change
|
||||||
|
//This is why the 1000 is in an odd, yet valid, position
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Poset<int> poset;
|
||||||
|
for (int i = 0; i < 20; i+=2)
|
||||||
|
poset.addRelationship(i,i+1);
|
||||||
|
result = "";
|
||||||
|
for (int i : poset.getTopoSort())
|
||||||
|
result += intToString(i) + " ";
|
||||||
|
//std::cout << result << std::endl;
|
||||||
|
assert(result == "1 3 5 7 9 11 13 15 17 19 0 2 4 6 8 10 12 14 16 18 ");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Poset tests passed" << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
@@ -5,6 +5,8 @@
|
|||||||
#include <queue>
|
#include <queue>
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <utility>
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include "Parser.h"
|
#include "Parser.h"
|
||||||
#include "Symbol.h"
|
#include "Symbol.h"
|
||||||
@@ -16,6 +18,7 @@ class RNGLRParser: public Parser {
|
|||||||
RNGLRParser();
|
RNGLRParser();
|
||||||
~RNGLRParser();
|
~RNGLRParser();
|
||||||
NodeTree<Symbol>* parseInput(std::string inputString);
|
NodeTree<Symbol>* parseInput(std::string inputString);
|
||||||
|
void printReconstructedFrontier(int frontier);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void reducer(int i);
|
void reducer(int i);
|
||||||
|
|||||||
@@ -1,5 +1,8 @@
|
|||||||
#include <fstream>
|
#include <fstream>
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
#include "ParseRule.h"
|
#include "ParseRule.h"
|
||||||
#include "ParseAction.h"
|
#include "ParseAction.h"
|
||||||
@@ -20,7 +23,8 @@ class Table {
|
|||||||
void remove(int stateNum, Symbol tranSymbol);
|
void remove(int stateNum, Symbol tranSymbol);
|
||||||
std::vector<ParseAction*>* get(int state, Symbol token);
|
std::vector<ParseAction*>* get(int state, Symbol token);
|
||||||
ParseAction* getShift(int state, Symbol token);
|
ParseAction* getShift(int state, Symbol token);
|
||||||
std::string toString();
|
std::vector<std::pair<std::string, ParseAction>> stateAsParseActionVector(int state);
|
||||||
|
std::string toString();
|
||||||
private:
|
private:
|
||||||
std::vector< std::vector< std::vector<ParseAction*>* >* > table;
|
std::vector< std::vector< std::vector<ParseAction*>* >* > table;
|
||||||
std::vector<Symbol> symbolIndexVec;
|
std::vector<Symbol> symbolIndexVec;
|
||||||
|
|||||||
31
include/Tester.h
Normal file
31
include/Tester.h
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
#include <iostream>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
#include "util.h"
|
||||||
|
|
||||||
|
#ifndef TESTER_H
|
||||||
|
#define TESTER_H
|
||||||
|
|
||||||
|
class Tester {
|
||||||
|
public:
|
||||||
|
Tester(std::string krakenInvocation, std::string krakenGrammerLocation);
|
||||||
|
~Tester();
|
||||||
|
int ssystem(std::string command);
|
||||||
|
bool run(std::string fileName);
|
||||||
|
bool compareFiles(std::string file1Path, std::string file2Path);
|
||||||
|
void cleanExtras(std::string fileName);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::string krakenInvocation;
|
||||||
|
std::string krakenGrammerLocation;
|
||||||
|
std::string removeCmd;
|
||||||
|
std::string resultsExtention;
|
||||||
|
std::string expectedExtention;
|
||||||
|
std::string krakenExtention;
|
||||||
|
std::string shell;
|
||||||
|
std::string changePermissions;
|
||||||
|
std::string redirect;
|
||||||
|
};
|
||||||
|
#endif
|
||||||
@@ -7,31 +7,43 @@
|
|||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
|
#include <set>
|
||||||
|
|
||||||
//Circular dependency
|
//Circular dependency
|
||||||
class ASTData;
|
class ASTData;
|
||||||
#include "ASTData.h"
|
#include "ASTData.h"
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
|
||||||
enum ValueType {none, void_type, boolean, integer, floating, double_percision, character };
|
enum ValueType {none, template_type, template_type_type, void_type, boolean, integer, floating, double_percision, character };
|
||||||
|
|
||||||
|
|
||||||
class Type {
|
class Type {
|
||||||
public:
|
public:
|
||||||
Type();
|
Type();
|
||||||
Type(ValueType typeIn, int indirectionIn);
|
Type(ValueType typeIn, int indirectionIn = 0);
|
||||||
Type(ValueType typeIn);
|
Type(ValueType typeIn, std::set<std::string> traitsIn); //Mostly for template type type's
|
||||||
Type(NodeTree<ASTData>* typeDefinitionIn);
|
Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn = 0);
|
||||||
Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn);
|
Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn);
|
||||||
Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn);
|
Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn);
|
||||||
|
Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn = std::set<std::string>());
|
||||||
~Type();
|
~Type();
|
||||||
bool const operator==(const Type &other)const;
|
bool const operator==(const Type &other)const;
|
||||||
bool const operator!=(const Type &other)const;
|
bool const operator!=(const Type &other)const;
|
||||||
std::string toString();
|
Type* clone();
|
||||||
ValueType baseType;
|
std::string toString(bool showTraits = true);
|
||||||
|
int getIndirection();
|
||||||
|
void setIndirection(int indirectionIn);
|
||||||
|
void increaseIndirection();
|
||||||
|
void decreaseIndirection();
|
||||||
|
void modifyIndirection(int mod);
|
||||||
|
|
||||||
|
ValueType baseType;
|
||||||
NodeTree<ASTData>* typeDefinition;
|
NodeTree<ASTData>* typeDefinition;
|
||||||
|
NodeTree<Symbol>* templateDefinition;
|
||||||
|
std::map<std::string, Type*> templateTypeReplacement;
|
||||||
|
std::set<std::string> traits;
|
||||||
|
private:
|
||||||
int indirection;
|
int indirection;
|
||||||
private:
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
@@ -9,6 +9,9 @@
|
|||||||
#include <string>
|
#include <string>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <set>
|
||||||
|
#include <fstream>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
std::string intToString(int theInt);
|
std::string intToString(int theInt);
|
||||||
std::string replaceExEscape(std::string first, std::string search, std::string replace);
|
std::string replaceExEscape(std::string first, std::string search, std::string replace);
|
||||||
@@ -16,6 +19,9 @@ std::string strSlice(std::string str, int begin, int end);
|
|||||||
int findPerenEnd(std::string str, int i);
|
int findPerenEnd(std::string str, int i);
|
||||||
std::vector<std::string> split(const std::string &str, char delim);
|
std::vector<std::string> split(const std::string &str, char delim);
|
||||||
std::string join(const std::vector<std::string> &strVec, std::string joinStr);
|
std::string join(const std::vector<std::string> &strVec, std::string joinStr);
|
||||||
|
std::string readFile(std::istream &file);
|
||||||
|
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
bool contains(std::vector<T> vec, T item) {
|
bool contains(std::vector<T> vec, T item) {
|
||||||
for (auto i : vec)
|
for (auto i : vec)
|
||||||
@@ -25,15 +31,32 @@ bool contains(std::vector<T> vec, T item) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
std::vector<T> slice(std::vector<T> vec, int begin, int end) {
|
std::vector<T> slice(std::vector<T> vec, int begin, int end, int step = 1) {
|
||||||
std::vector<T> toReturn;
|
std::vector<T> toReturn;
|
||||||
if (begin < 0)
|
if (begin < 0)
|
||||||
begin += vec.size()+1;
|
begin += vec.size()+1;
|
||||||
if (end < 0)
|
if (end < 0)
|
||||||
end += vec.size()+1;
|
end += vec.size()+1;
|
||||||
for (int i = begin; i < end; i++)
|
for (int i = begin; i < end; i += step)
|
||||||
toReturn.push_back(vec[i]);
|
toReturn.push_back(vec[i]);
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
bool subset(std::set<T> a, std::set<T> b) {
|
||||||
|
for (auto i : a)
|
||||||
|
if (b.find(i) == b.end())
|
||||||
|
return false;
|
||||||
|
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
|
||||||
|
|||||||
@@ -2,10 +2,19 @@ Goal = translation_unit ;
|
|||||||
translation_unit = interpreter_directive WS unorderd_list_part WS ;
|
translation_unit = interpreter_directive WS unorderd_list_part WS ;
|
||||||
unorderd_list_part = import WS unorderd_list_part | function WS unorderd_list_part | type_def WS ";" WS unorderd_list_part | if_comp WS unorderd_list_part | simple_passthrough WS unorderd_list_part | declaration_statement WS ";" WS unorderd_list_part | import | function | type_def WS ";" | if_comp | simple_passthrough | declaration_statement WS ";" ;
|
unorderd_list_part = import WS unorderd_list_part | function WS unorderd_list_part | type_def WS ";" WS unorderd_list_part | if_comp WS unorderd_list_part | simple_passthrough WS unorderd_list_part | declaration_statement WS ";" WS unorderd_list_part | import | function | type_def WS ";" | if_comp | simple_passthrough | declaration_statement WS ";" ;
|
||||||
|
|
||||||
type = type WS "\*" | "void" | "int" | "float" | "double" | "char" | identifier ;
|
type = type WS "\*" | "void" | "int" | "float" | "double" | "char" | identifier | identifier WS template_inst ;
|
||||||
|
dec_type = "\|" WS type WS "\|" ;
|
||||||
|
|
||||||
|
template_inst = "<" WS type_list WS ">" ;
|
||||||
|
type_list = type_list WS "," WS type | type ;
|
||||||
|
|
||||||
|
template_dec = "template" WS "<" WS template_param_list WS ">" ;
|
||||||
|
template_param_list = template_param_list WS "," WS template_param | template_param ;
|
||||||
|
template_param = identifier WS traits | identifier ;
|
||||||
|
|
||||||
import = "import" WS identifier WS ";" ;
|
import = "import" WS identifier WS ";" ;
|
||||||
|
|
||||||
|
|
||||||
interpreter_directive = "#!" WS path | ;
|
interpreter_directive = "#!" WS path | ;
|
||||||
path = path path_part | path_part ;
|
path = path path_part | path_part ;
|
||||||
path_part = forward_slash alphanumeric | back_slash alphanumeric ;
|
path_part = forward_slash alphanumeric | back_slash alphanumeric ;
|
||||||
@@ -29,24 +38,33 @@ triple_quoted_string = "\"\"\"((\"\"(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i
|
|||||||
|
|
||||||
identifier = alpha | alpha alphanumeric ;
|
identifier = alpha | alpha alphanumeric ;
|
||||||
|
|
||||||
overloadable_operator = "\+" | "-" | "\*" | "/" | "%" | "^" | "&" | "\|" | "~" | "\!" | "," | "=" | "\+\+" | "--" | "<<" | ">>" | "==" | "!=" | "&&" | "\|\|" | "\+=" | "-=" | "/=" | "%=" | "^=" | "&=" | "\|=" | "\*=" | "<<=" | ">>=" | "->" ;
|
#Note that to prevent confilct with nested templates (T<A<B>>) it is a nonterminal contructed as follows
|
||||||
|
right_shift = ">" ">" ;
|
||||||
|
overloadable_operator = "\+" | "-" | "\*" | "/" | "%" | "^" | "&" | "\|" | "~" | "!" | "," | "=" | "\+\+" | "--" | "<<" | right_shift | "==" | "!=" | "&&" | "\|\|" | "\+=" | "-=" | "/=" | "%=" | "^=" | "&=" | "\|=" | "\*=" | "<<=" | ">>=" | "->" ;
|
||||||
func_identifier = identifier | identifier overloadable_operator ;
|
func_identifier = identifier | identifier overloadable_operator ;
|
||||||
function = type WS func_identifier WS "\(" WS opt_typed_parameter_list WS "\)" WS code_block ;
|
function = template_dec WS dec_type WS func_identifier WS "\(" WS opt_typed_parameter_list WS "\)" WS code_block | dec_type WS func_identifier WS "\(" WS opt_typed_parameter_list WS "\)" WS code_block ;
|
||||||
|
|
||||||
opt_typed_parameter_list = typed_parameter_list | ;
|
opt_typed_parameter_list = typed_parameter_list | ;
|
||||||
typed_parameter_list = typed_parameter_list WS "," WS typed_parameter | typed_parameter ;
|
typed_parameter_list = typed_parameter_list WS "," WS typed_parameter | typed_parameter ;
|
||||||
typed_parameter = type WS identifier ;
|
typed_parameter = dec_type WS identifier ;
|
||||||
|
|
||||||
opt_parameter_list = parameter_list | ;
|
opt_parameter_list = parameter_list | ;
|
||||||
parameter_list = parameter_list WS "," WS parameter | parameter ;
|
parameter_list = parameter_list WS "," WS parameter | parameter ;
|
||||||
parameter = boolean_expression ;
|
parameter = boolean_expression ;
|
||||||
|
|
||||||
type_def = "typedef" WS identifier WS type | "typedef" WS identifier WS "{" WS class_innerds WS "}" | "typedef" WS identifier WS "{" WS declaration_block WS "}" ;
|
type_def = "typedef" WS identifier WS type | "typedef" WS template_dec WS identifier WS "{" WS declaration_block WS "}" | "typedef" WS identifier WS "{" WS declaration_block WS "}" | "typedef" WS template_dec WS identifier WS traits WS "{" WS declaration_block WS "}" | "typedef" WS identifier WS traits WS "{" WS declaration_block WS "}" ;
|
||||||
class_innerds = visibility_block WS class_innerds | visibility_block ;
|
|
||||||
visibility_block = "public:" WS declaration_block | "protected:" WS declaration_block | "private:" WS declaration_block ;
|
|
||||||
declaration_block = declaration_statement WS ";" WS declaration_block | function WS declaration_block | declaration_statement WS ";" | function ;
|
|
||||||
|
|
||||||
if_statement = "if" WS "\(" WS boolean_expression WS "\)" WS statement ;
|
declaration_block = declaration_statement WS ";" WS declaration_block | function WS declaration_block | declaration_statement WS ";" | function | ;
|
||||||
|
traits = "\(" WS trait_list WS "\)" ;
|
||||||
|
trait_list = trait_list WS "," WS identifier | identifier ;
|
||||||
|
|
||||||
|
#Older rule for stuff with visibility labels - this should be added sometime
|
||||||
|
#type_def = "typedef" WS identifier WS type | "typedef" WS template_dec WS identifier WS "{" WS class_innerds WS "}" | "typedef" WS identifier WS "{" WS class_innerds WS "}" | "typedef" WS template_dec WS identifier WS "{" WS declaration_block WS "}" | "typedef" WS identifier WS "{" WS declaration_block WS "}" ;
|
||||||
|
#class_innerds = visibility_block WS class_innerds | visibility_block ;
|
||||||
|
#visibility_block = "public:" WS declaration_block | "protected:" WS declaration_block | "private:" WS declaration_block ;
|
||||||
|
|
||||||
|
|
||||||
|
if_statement = "if" WS "\(" WS boolean_expression WS "\)" WS statement | "if" WS "\(" WS boolean_expression WS "\)" WS statement WS "else" WS statement ;
|
||||||
|
|
||||||
while_loop = "while" WS boolean_expression WS statement ;
|
while_loop = "while" WS boolean_expression WS statement ;
|
||||||
|
|
||||||
@@ -54,7 +72,7 @@ for_loop = "for" WS "\(" WS statement WS boolean_expression WS ";" WS statement
|
|||||||
|
|
||||||
return_statement = "return" | "return" WS boolean_expression ;
|
return_statement = "return" | "return" WS boolean_expression ;
|
||||||
|
|
||||||
code_block = "{" WS statement_list WS "}" ;
|
code_block = "{" WS statement_list WS "}" | "{" WS "}" ;
|
||||||
|
|
||||||
statement_list = statement_list WS statement | statement ;
|
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 ;
|
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 ;
|
||||||
@@ -62,26 +80,25 @@ function_call = unarad "\(" WS opt_parameter_list WS "\)" ;
|
|||||||
|
|
||||||
boolean_expression = boolean_expression WS "\|\|" WS and_boolean_expression | and_boolean_expression ;
|
boolean_expression = boolean_expression WS "\|\|" WS and_boolean_expression | and_boolean_expression ;
|
||||||
and_boolean_expression = and_boolean_expression "&&" bool_exp | bool_exp ;
|
and_boolean_expression = and_boolean_expression "&&" bool_exp | bool_exp ;
|
||||||
bool_exp = "!" WS bool_exp | expression WS comparator WS expression | bool | expression ;
|
bool_exp = expression WS comparator WS expression | expression ;
|
||||||
comparator = "==" | "<=" | ">=" | "!=" | "<" | ">" ;
|
comparator = "==" | "<=" | ">=" | "!=" | "<" | ">" ;
|
||||||
|
|
||||||
expression = expression WS "<<" WS term | expression WS ">>" WS shiftand | shiftand ;
|
expression = expression WS "<<" WS term | expression WS right_shift WS shiftand | shiftand ;
|
||||||
shiftand = shiftand WS "-" WS term | shiftand WS "\+" WS term | term ;
|
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 ;
|
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 ;
|
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 "\)" | access_operation ;
|
unarad = number | identifier | identifier WS template_inst | function_call | bool | string | character | "\(" WS boolean_expression WS "\)" | access_operation | unarad WS "[" WS expression WS "]" ;
|
||||||
number = integer | float | double ;
|
number = integer | floating_literal ;
|
||||||
access_operation = unarad "." identifier | unarad "->" identifier ;
|
access_operation = unarad "." identifier | unarad "->" identifier ;
|
||||||
|
|
||||||
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 ;
|
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 ;
|
declaration_statement = dec_type WS identifier WS "=" WS boolean_expression | dec_type WS identifier | dec_type WS identifier WS "." WS identifier WS "\(" WS opt_parameter_list WS "\)" ;
|
||||||
|
|
||||||
alphanumeric = alphanumeric numeric | alphanumeric alpha | numeric | alpha ;
|
alphanumeric = alphanumeric numeric | alphanumeric alpha | numeric | alpha ;
|
||||||
hexadecimal = "0x(1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)+" ;
|
hexadecimal = "0x(1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)+" ;
|
||||||
sign = "\+|-" WS | ;
|
sign = "\+|-" WS | ;
|
||||||
integer = sign numeric | sign hexadecimal | "null" ;
|
integer = sign numeric | sign hexadecimal ;
|
||||||
float = sign numeric "." numeric "f" ;
|
floating_literal = sign numeric "." numeric | sign numeric "." numeric alpha ;
|
||||||
double = sign numeric "." numeric | sign numeric "." numeric "d" ;
|
|
||||||
bool = "true" | "false" | "True" | "False" ;
|
bool = "true" | "false" | "True" | "False" ;
|
||||||
character = "'(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'|
|
character = "'(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'|
|
||||||
|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|\"|Z|X|C|V|B|N|M|<|>|\?| )'" ;
|
|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|\"|Z|X|C|V|B|N|M|<|>|\?| )'" ;
|
||||||
|
|||||||
80
main.cpp
80
main.cpp
@@ -14,24 +14,56 @@
|
|||||||
#include "Importer.h"
|
#include "Importer.h"
|
||||||
#include "ASTData.h"
|
#include "ASTData.h"
|
||||||
#include "CGenerator.h"
|
#include "CGenerator.h"
|
||||||
|
#include "Poset.h"
|
||||||
|
|
||||||
#include "util.h"
|
#include "util.h"
|
||||||
|
#include "Tester.h"
|
||||||
|
|
||||||
int main(int argc, char* argv[]) {
|
int main(int argc, char* argv[]) {
|
||||||
if (argc == 2 && std::string(argv[1]) == "--test") {
|
std::vector<std::string> includePaths;
|
||||||
|
includePaths.push_back(""); //Local
|
||||||
|
|
||||||
|
if (argc <= 1) {
|
||||||
|
std::cout << "Kraken invocation: kraken sourceFile.krak grammerFile.kgm outputName" << std::endl;
|
||||||
|
std::cout << "Or for testing do: kraken --test [optional list of names of file (.krak .expected_results) without extentions to run]" << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (argc >= 2 && std::string(argv[1]) == "--test") {
|
||||||
StringReader::test();
|
StringReader::test();
|
||||||
RegEx::test();
|
RegEx::test();
|
||||||
Lexer::test();
|
Lexer::test();
|
||||||
//std::cout << strSlice("123", 0, -1) << std::endl;
|
//std::cout << strSlice("123", 0, -1) << std::endl;
|
||||||
|
Poset<int>::test();
|
||||||
|
|
||||||
|
if (argc >= 3) {
|
||||||
|
std::string testResults, line;
|
||||||
|
int passed = 0, failed = 0;
|
||||||
|
Tester test(argv[0], "../krakenGrammer.kgm");
|
||||||
|
for (int i = 2; i < argc; i++) {
|
||||||
|
bool result = test.run(argv[i]);
|
||||||
|
if (result)
|
||||||
|
line = std::string(argv[i]) + "\t\tpassed!\n", passed++;
|
||||||
|
else
|
||||||
|
line = std::string(argv[i]) + "\t\tFAILED!\n", failed++;
|
||||||
|
std::cout << line << std::endl;
|
||||||
|
testResults += line;
|
||||||
|
}
|
||||||
|
std::cout << "===========Done Testing===========" << std::endl;
|
||||||
|
std::cout << testResults << std::endl;
|
||||||
|
std::cout << "Test results: " << passed << "/" << passed+failed << std::endl;
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
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 programName = argv[1];
|
||||||
std::string grammerFileString = argv[2];
|
std::string grammerFileString = argv[2];
|
||||||
std::string outputName = argv[3];
|
std::string outputName = argv[3];
|
||||||
|
|
||||||
std::ifstream grammerInFile, compiledGrammerInFile;
|
std::ifstream grammerInFile, compiledGrammerInFile;
|
||||||
std::ofstream /*outFileC,*/ compiledGrammerOutFile;
|
std::ofstream compiledGrammerOutFile;
|
||||||
|
|
||||||
grammerInFile.open(grammerFileString);
|
grammerInFile.open(grammerFileString);
|
||||||
if (!grammerInFile.is_open()) {
|
if (!grammerInFile.is_open()) {
|
||||||
@@ -40,17 +72,9 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
compiledGrammerInFile.open(grammerFileString + ".comp", std::ios::binary | std::ios::ate);
|
compiledGrammerInFile.open(grammerFileString + ".comp", std::ios::binary | std::ios::ate);
|
||||||
if (!compiledGrammerInFile.is_open()) {
|
if (!compiledGrammerInFile.is_open())
|
||||||
std::cout << "Problem opening compiledGrammerInFile " << grammerFileString + ".comp" << "\n";
|
std::cout << "Problem opening compiledGrammerInFile " << grammerFileString + ".comp" << "\n";
|
||||||
//return(1);
|
|
||||||
}
|
|
||||||
/*
|
|
||||||
outFileC.open((outputName + ".c").c_str());
|
|
||||||
if (!outFileC.is_open()) {
|
|
||||||
std::cout << "Probelm opening third output file " << outputName + ".c" << "\n";
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
//Read the input file into a string
|
//Read the input file into a string
|
||||||
std::string grammerInputFileString;
|
std::string grammerInputFileString;
|
||||||
std::string line;
|
std::string line;
|
||||||
@@ -63,8 +87,6 @@ int main(int argc, char* argv[]) {
|
|||||||
//LALRParser parser;
|
//LALRParser parser;
|
||||||
RNGLRParser parser;
|
RNGLRParser parser;
|
||||||
parser.loadGrammer(grammerInputFileString);
|
parser.loadGrammer(grammerInputFileString);
|
||||||
//std::cout << "Creating State Set from Main" << std::endl;
|
|
||||||
//std::cout << "\nState Set" << std::endl;
|
|
||||||
|
|
||||||
//Start binary stuff
|
//Start binary stuff
|
||||||
bool compGramGood = false;
|
bool compGramGood = false;
|
||||||
@@ -88,7 +110,6 @@ int main(int argc, char* argv[]) {
|
|||||||
} else {
|
} else {
|
||||||
compGramGood = true;
|
compGramGood = true;
|
||||||
std::cout << "Grammer file is up to date." << std::endl;
|
std::cout << "Grammer file is up to date." << std::endl;
|
||||||
//int tableLength = *((int*)(binaryTablePointer + 4 + sizeof(int) + gramStringLength));
|
|
||||||
parser.importTable(binaryTablePointer + 4 + sizeof(int) + gramStringLength); //Load table starting at the table section
|
parser.importTable(binaryTablePointer + 4 + sizeof(int) + gramStringLength); //Load table starting at the table section
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -118,40 +139,23 @@ int main(int argc, char* argv[]) {
|
|||||||
}
|
}
|
||||||
//End binary stuff
|
//End binary stuff
|
||||||
|
|
||||||
//std::cout << "finished State Set from Main" << std::endl;
|
|
||||||
//std::cout << "Doing stateSetToString from Main" << std::endl;
|
|
||||||
// std::cout << "\n\n\n\n\n\n\n\n\n\nState Set toString" << std::endl;
|
|
||||||
// std::cout << parser.stateSetToString() << std::endl;
|
|
||||||
// std::cout << "finished stateSetToString from Main" << std::endl;
|
|
||||||
// std::cout << "\n\n\n\n\n\n\n\n\n\nTable" << std::endl;
|
|
||||||
// std::cout << parser.tableToString() << std::endl;
|
|
||||||
// std::cout << "\n\n\n\n\n\n\n\n\n\nGrammer Input File" << std::endl;
|
|
||||||
// std::cout << grammerInputFileString << std::endl;
|
|
||||||
// std::cout << "\n\n\n\n\n\n\n\n\n\nGrammer toString" << std::endl;
|
|
||||||
// std::cout << parser.grammerToString() << std::endl;
|
|
||||||
//std::cout << parser.grammerToDOT() << std::endl;
|
|
||||||
|
|
||||||
//outFile << parser.grammerToDOT() << std::endl;
|
|
||||||
std::cout << "\nParsing" << std::endl;
|
std::cout << "\nParsing" << std::endl;
|
||||||
|
|
||||||
Importer importer(&parser);
|
Importer importer(&parser, includePaths);
|
||||||
|
|
||||||
|
for (auto i : includePaths)
|
||||||
|
std::cout << i << std::endl;
|
||||||
|
|
||||||
/*NodeTree<ASTData>* AST =*/
|
|
||||||
importer.import(programName);
|
importer.import(programName);
|
||||||
std::map<std::string, NodeTree<ASTData>*> ASTs = importer.getASTMap();
|
std::map<std::string, NodeTree<ASTData>*> ASTs = importer.getASTMap();
|
||||||
|
|
||||||
//Do optomization, etc. here.
|
//Do optimization, etc. here.
|
||||||
//None at this time, instead going straight to C in this first (more naive) version
|
//None at this time, instead going straight to C in this first (more naive) version
|
||||||
|
|
||||||
//Code generation
|
//Code generation
|
||||||
//For right now, just C
|
//For right now, just C
|
||||||
|
|
||||||
CGenerator().generateCompSet(ASTs, outputName);
|
CGenerator().generateCompSet(ASTs, outputName);
|
||||||
/*
|
|
||||||
std::string c_code = CGenerator().generate(AST);
|
|
||||||
outFileC << c_code << std::endl;
|
|
||||||
outFileC.close();
|
|
||||||
*/
|
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -15,7 +15,8 @@ void CGenerator::generateCompSet(std::map<std::string, NodeTree<ASTData>*> ASTs,
|
|||||||
std::ofstream outputCFile;
|
std::ofstream outputCFile;
|
||||||
outputCFile.open(i->first + ".c");
|
outputCFile.open(i->first + ".c");
|
||||||
if (outputCFile.is_open()) {
|
if (outputCFile.is_open()) {
|
||||||
outputCFile << generate(i->second);
|
// Prequel common to all files
|
||||||
|
outputCFile << "#include <stdbool.h>\n#include <stdlib.h>\n#include <stdio.h>\n" << generate(i->second);
|
||||||
} else {
|
} else {
|
||||||
std::cout << "Cannot open file " << i->first << ".c" << std::endl;
|
std::cout << "Cannot open file " << i->first << ".c" << std::endl;
|
||||||
}
|
}
|
||||||
@@ -35,59 +36,163 @@ std::string CGenerator::tabs() {
|
|||||||
return returnTabs;
|
return returnTabs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string CGenerator::generateClassStruct(NodeTree<ASTData>* from) {
|
||||||
|
auto data = from->getData();
|
||||||
|
auto children = from->getChildren();
|
||||||
|
std::string objectString = "struct __struct_dummy_" + CifyName(data.symbol.getName()) + "__ {\n";
|
||||||
|
tabLevel++;
|
||||||
|
for (int i = 0; i < children.size(); i++) {
|
||||||
|
std::cout << children[i]->getName() << std::endl;
|
||||||
|
if (children[i]->getName() != "function")
|
||||||
|
objectString += tabs() + generate(children[i], nullptr) + "\n";
|
||||||
|
}
|
||||||
|
tabLevel--;
|
||||||
|
objectString += "};";
|
||||||
|
return objectString;
|
||||||
|
}
|
||||||
|
|
||||||
|
// This method recurseivly generates all aliases of some definition
|
||||||
|
std::string CGenerator::generateAliasChains(NodeTree<ASTData>* scopeNode, NodeTree<ASTData>* definition) {
|
||||||
|
auto scope = scopeNode->getDataRef()->scope;
|
||||||
|
std::string output;
|
||||||
|
for (auto i = scope.begin(); i != scope.end(); i++) {
|
||||||
|
for (auto declaration : i->second) {
|
||||||
|
auto declarationData = declaration->getDataRef();
|
||||||
|
if (declarationData->type == type_def
|
||||||
|
&& declarationData->valueType->typeDefinition != declaration
|
||||||
|
&& declarationData->valueType->typeDefinition == definition) {
|
||||||
|
output += "typedef " + CifyName(definition->getDataRef()->symbol.getName()) + " " + CifyName(declarationData->symbol.getName()) + ";\n";
|
||||||
|
// Recursively add the ones that depend on this one
|
||||||
|
output += generateAliasChains(scopeNode, declaration);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
//The enclosing object is for when we're generating the inside of object methods. They allow us to check scope lookups against the object we're in
|
//The enclosing object is for when we're generating the inside of object methods. They allow us to check scope lookups against the object we're in
|
||||||
std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject) {
|
std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject) {
|
||||||
ASTData data = from->getData();
|
ASTData data = from->getData();
|
||||||
std::vector<NodeTree<ASTData>*> children = from->getChildren();
|
std::vector<NodeTree<ASTData>*> children = from->getChildren();
|
||||||
std::string output = "";
|
std::string output;
|
||||||
switch (data.type) {
|
switch (data.type) {
|
||||||
case translation_unit:
|
case translation_unit:
|
||||||
//Do here because we may need the typedefs before the declarations of variables
|
{
|
||||||
for (int i = 0; i < children.size(); i++)
|
// Ok, so we've got to do this in passes to preserve mututally recursive definitions.
|
||||||
if (children[i]->getDataRef()->type == type_def)
|
//
|
||||||
output += generate(children[i], enclosingObject) + "\n";
|
// First Pass: All classes get "struct dummy_thing; typedef struct dummy_thing thing;".
|
||||||
|
// Also, other typedefs follow after their naming.
|
||||||
|
// Second Pass: All top level variable declarations
|
||||||
|
// Third Pass: Define all actual structs of a class, in correct order (done with posets)
|
||||||
|
// Fourth Pass: Declare all function prototypes (as functions may be mutually recursive too).
|
||||||
|
// (this includes object methods)
|
||||||
|
// Fifth Pass: Define all functions (including object methods).
|
||||||
|
|
||||||
|
// However, most of these do not actually have to be done as separate passes. First, second, fourth, and fifth
|
||||||
|
// are done simultanously, but append to different strings that are then concatinated properly, in order.
|
||||||
|
|
||||||
|
std::string plainTypedefs = "/**\n * Plain Typedefs\n */\n\n";
|
||||||
|
std::string variableDeclarations = "/**\n * Variable Declarations \n */\n\n";
|
||||||
|
std::string classStructs = "/**\n * Class Structs\n */\n\n";
|
||||||
|
std::string functionPrototypes = "/**\n * Function Prototypes\n */\n\n";
|
||||||
|
std::string functionDefinitions = "/**\n * Function Definitions\n */\n\n";
|
||||||
|
|
||||||
|
Poset<NodeTree<ASTData>*> typedefPoset;
|
||||||
|
for (int i = 0; i < children.size(); i++) {
|
||||||
|
if (children[i]->getDataRef()->type == type_def) {
|
||||||
|
// If we're an alias type, continue. We handle those differently
|
||||||
|
if (children[i]->getDataRef()->valueType->typeDefinition != children[i])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
typedefPoset.addVertex(children[i]); // We add this definition by itself just in case there are no dependencies.
|
||||||
|
// If it has dependencies, there's no harm in adding it here
|
||||||
|
// Go through every child in the class looking for declaration statements. For each of these that is not a primitive type
|
||||||
|
// we will add a dependency from this definition to that definition in the poset.
|
||||||
|
std::vector<NodeTree<ASTData>*> classChildren = children[i]->getChildren();
|
||||||
|
for (auto j : classChildren) {
|
||||||
|
if (j->getDataRef()->type == declaration_statement) {
|
||||||
|
Type* decType = j->getChildren()[0]->getDataRef()->valueType; // Type of the declaration
|
||||||
|
if (decType->typeDefinition && decType->getIndirection() == 0) // If this is a custom type and not a pointer
|
||||||
|
typedefPoset.addRelationship(children[i], decType->typeDefinition); // Add a dependency
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//Now generate the typedef's in the correct, topological order
|
||||||
|
for (NodeTree<ASTData>* i : typedefPoset.getTopoSort())
|
||||||
|
classStructs += generateClassStruct(i) + "\n";
|
||||||
|
|
||||||
//Declare everything in translation unit scope here. (allows stuff from other files, automatic forward declarations)
|
//Declare everything in translation unit scope here. (allows stuff from other files, automatic forward declarations)
|
||||||
for (auto i = data.scope.begin(); i != data.scope.end(); i++) {
|
for (auto i = data.scope.begin(); i != data.scope.end(); i++) {
|
||||||
for (auto overloadedMembers : i->second) {
|
for (auto declaration : i->second) {
|
||||||
NodeTree<ASTData>* declaration = overloadedMembers;
|
|
||||||
std::vector<NodeTree<ASTData>*> decChildren = declaration->getChildren();
|
std::vector<NodeTree<ASTData>*> decChildren = declaration->getChildren();
|
||||||
ASTData declarationData = declaration->getData();
|
ASTData declarationData = declaration->getData();
|
||||||
switch(declarationData.type) {
|
switch(declarationData.type) {
|
||||||
case identifier:
|
case identifier:
|
||||||
output += ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*identifier*/\n";
|
variableDeclarations += ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*identifier*/\n";
|
||||||
break;
|
break;
|
||||||
case function:
|
case function:
|
||||||
{
|
{
|
||||||
if (decChildren.size() == 0) { //Not a real function, must be a built in passthrough {
|
if (declarationData.valueType->baseType == template_type)
|
||||||
output += "/* built in function: " + declarationData.toString() + " */\n";
|
functionPrototypes += "/* template function " + declarationData.symbol.toString() + " */\n";
|
||||||
break;
|
else if (decChildren.size() == 0) //Not a real function, must be a built in passthrough
|
||||||
|
functionPrototypes += "/* built in function: " + declarationData.symbol.toString() + " */\n";
|
||||||
|
else {
|
||||||
|
functionPrototypes += "\n" + ValueTypeToCType(declarationData.valueType) + " ";
|
||||||
|
std::string nameDecoration, parameters;
|
||||||
|
for (int j = 0; j < decChildren.size()-1; j++) {
|
||||||
|
if (j > 0)
|
||||||
|
parameters += ", ";
|
||||||
|
parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], enclosingObject);
|
||||||
|
nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType);
|
||||||
|
}
|
||||||
|
functionPrototypes += CifyName(declarationData.symbol.getName() + nameDecoration) + "(" + parameters + "); /*func*/\n";
|
||||||
|
// Only generate function if this is the unit it was defined in
|
||||||
|
std::cout << "Generating " << CifyName(declarationData.symbol.getName()) << std::endl;
|
||||||
|
if (contains(children, declaration))
|
||||||
|
functionDefinitions += generate(declaration, enclosingObject);
|
||||||
}
|
}
|
||||||
output += "\n" + ValueTypeToCType(declarationData.valueType) + " ";
|
|
||||||
std::string nameDecoration, parameters;
|
|
||||||
for (int j = 0; j < decChildren.size()-1; j++) {
|
|
||||||
if (j > 0)
|
|
||||||
parameters += ", ";
|
|
||||||
parameters += ValueTypeToCType(decChildren[j]->getData().valueType) + " " + generate(decChildren[j], enclosingObject);
|
|
||||||
nameDecoration += "_" + ValueTypeToCTypeDecoration(decChildren[j]->getData().valueType);
|
|
||||||
}
|
|
||||||
output += CifyFunctionName(declarationData.symbol.getName()) + nameDecoration + "(" + parameters + "); /*func*/\n";
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
case type_def:
|
|
||||||
//type
|
|
||||||
output += "/*typedef " + declarationData.symbol.getName() + " */\n";
|
|
||||||
break;
|
break;
|
||||||
|
case type_def:
|
||||||
|
//type
|
||||||
|
plainTypedefs += "/*typedef " + declarationData.symbol.getName() + " */\n";
|
||||||
|
|
||||||
|
if (declarationData.valueType->baseType == template_type) {
|
||||||
|
plainTypedefs += "/* non instantiated template " + declarationData.symbol.getName() + " */";
|
||||||
|
} else if (declarationData.valueType->typeDefinition != declaration) {
|
||||||
|
if (declarationData.valueType->typeDefinition)
|
||||||
|
continue; // Aliases of objects are done with the thing it alises
|
||||||
|
// Otherwise, we're actually a renaming of a primitive, can generate here
|
||||||
|
plainTypedefs += "typedef " + ValueTypeToCType(declarationData.valueType) + " " + CifyName(declarationData.symbol.getName()) + ";\n";
|
||||||
|
plainTypedefs += generateAliasChains(from, declaration);
|
||||||
|
} else {
|
||||||
|
plainTypedefs += "typedef struct __struct_dummy_" + CifyName(declarationData.symbol.getName()) + "__ " + CifyName(declarationData.symbol.getName()) + ";\n";
|
||||||
|
functionPrototypes += "/* Method Prototypes for " + declarationData.symbol.getName() + " */\n";
|
||||||
|
// We use a seperate string for this because we only include it if this is the file we're defined in
|
||||||
|
std::string objectFunctionDefinitions = "/* Method Definitions for " + declarationData.symbol.getName() + " */\n";
|
||||||
|
for (int j = 0; j < decChildren.size(); j++) {
|
||||||
|
std::cout << decChildren[j]->getName() << std::endl;
|
||||||
|
if (decChildren[j]->getName() == "function") //If object method
|
||||||
|
objectFunctionDefinitions += generateObjectMethod(declaration, decChildren[j], &functionPrototypes) + "\n";
|
||||||
|
}
|
||||||
|
// Add all aliases to the plain typedefs. This will add any alias that aliases to this object, and any alias that aliases to that, and so on
|
||||||
|
plainTypedefs += generateAliasChains(from, declaration);
|
||||||
|
functionPrototypes += "/* Done with " + declarationData.symbol.getName() + " */\n";
|
||||||
|
// If this is the file the object is defined in, include methods
|
||||||
|
if (contains(children, declaration))
|
||||||
|
functionDefinitions += objectFunctionDefinitions + "/* Done with " + declarationData.symbol.getName() + " */\n";
|
||||||
|
}
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
//std::cout << "Declaration? named " << declaration->getName() << " of unknown type " << ASTData::ASTTypeToString(declarationData.type) << " in translation unit scope" << std::endl;
|
//std::cout << "Declaration? named " << declaration->getName() << " of unknown type " << ASTData::ASTTypeToString(declarationData.type) << " in translation unit scope" << std::endl;
|
||||||
output += "/*unknown declaration named " + declaration->getName() + "*/\n";
|
output += "/*unknown declaration named " + declaration->getName() + "*/\n";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Do here because we need the newlines
|
output += plainTypedefs + variableDeclarations + classStructs + functionPrototypes + functionDefinitions;
|
||||||
for (int i = 0; i < children.size(); i++)
|
|
||||||
if (children[i]->getDataRef()->type != type_def)
|
|
||||||
output += generate(children[i], enclosingObject) + "\n";
|
|
||||||
return output;
|
return output;
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case interpreter_directive:
|
case interpreter_directive:
|
||||||
//Do nothing
|
//Do nothing
|
||||||
@@ -97,33 +202,22 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
//return "#include <" + data.symbol.getName() + ">\n";
|
//return "#include <" + data.symbol.getName() + ">\n";
|
||||||
case identifier:
|
case identifier:
|
||||||
{
|
{
|
||||||
//If we're in an object method, and our enclosing scope is that object, we're a member of the object and should use the self reference.
|
//but first, if we're this, we should just emit. (assuming enclosing object) (note that technically this would fall through, but for errors)
|
||||||
|
if (data.symbol.getName() == "this")
|
||||||
|
if (enclosingObject)
|
||||||
|
return "this";
|
||||||
|
else
|
||||||
|
std::cout << "Error: this used in non-object scope" << std::endl;
|
||||||
|
//If we're in an object method, and our enclosing scope is that object, we're a member of the object and should use the this reference.
|
||||||
std::string preName;
|
std::string preName;
|
||||||
if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end())
|
if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end())
|
||||||
preName += "self->";
|
preName += "this->";
|
||||||
if (false)
|
return preName + CifyName(data.symbol.getName()); //Cifying does nothing if not an operator overload
|
||||||
for (int j = 0; j < children.size()-1; j++)
|
|
||||||
preName += ValueTypeToCType(children[j]->getData().valueType) + "_";
|
|
||||||
return preName + CifyFunctionName(data.symbol.getName()); //Cifying does nothing if not an operator overload
|
|
||||||
}
|
}
|
||||||
case type_def:
|
|
||||||
if (children.size() == 0) {
|
|
||||||
return "typedef " + ValueTypeToCType(data.valueType) + " " + data.symbol.getName() + ";";
|
|
||||||
} else {
|
|
||||||
std::string objectString = "typedef struct __struct_dummy_" + data.symbol.getName() + "__ {\n";
|
|
||||||
std::string postString; //The functions have to be outside the struct definition
|
|
||||||
for (int i = 0; i < children.size(); i++) {
|
|
||||||
std::cout << children[i]->getName() << std::endl;
|
|
||||||
if (children[i]->getName() == "function") //If object method
|
|
||||||
postString += generateObjectMethod(from, children[i]) + "\n";
|
|
||||||
else
|
|
||||||
objectString += generate(children[i], enclosingObject) + "\n";
|
|
||||||
}
|
|
||||||
objectString += "} " + data.symbol.getName() + ";";
|
|
||||||
return objectString + postString; //Functions come after the declaration of the struct
|
|
||||||
}
|
|
||||||
case function:
|
case function:
|
||||||
{
|
{
|
||||||
|
if (data.valueType->baseType == template_type)
|
||||||
|
return "/* template function: " + data.symbol.getName() + " */";
|
||||||
output += "\n" + ValueTypeToCType(data.valueType) + " ";
|
output += "\n" + ValueTypeToCType(data.valueType) + " ";
|
||||||
std::string nameDecoration, parameters;
|
std::string nameDecoration, parameters;
|
||||||
for (int j = 0; j < children.size()-1; j++) {
|
for (int j = 0; j < children.size()-1; j++) {
|
||||||
@@ -132,22 +226,39 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
parameters += ValueTypeToCType(children[j]->getData().valueType) + " " + generate(children[j], enclosingObject);
|
parameters += ValueTypeToCType(children[j]->getData().valueType) + " " + generate(children[j], enclosingObject);
|
||||||
nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType);
|
nameDecoration += "_" + ValueTypeToCTypeDecoration(children[j]->getData().valueType);
|
||||||
}
|
}
|
||||||
output += CifyFunctionName(data.symbol.getName()) + nameDecoration + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject);
|
output += CifyName(data.symbol.getName() + nameDecoration) + "(" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject);
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
case code_block:
|
case code_block:
|
||||||
|
{
|
||||||
output += "{\n";
|
output += "{\n";
|
||||||
tabLevel++;
|
std::string destructorString = "";
|
||||||
|
tabLevel++;
|
||||||
for (int i = 0; i < children.size(); i++) {
|
for (int i = 0; i < children.size(); i++) {
|
||||||
//std::cout << "Line " << i << std::endl;
|
//std::cout << "Line " << i << std::endl;
|
||||||
std::string line = generate(children[i], enclosingObject);
|
std::string line = generate(children[i], enclosingObject);
|
||||||
//std::cout << line << std::endl;
|
//std::cout << line << std::endl;
|
||||||
output += line;
|
output += line;
|
||||||
}
|
if (children[i]->getChildren().size() && children[i]->getChildren()[0]->getDataRef()->type == declaration_statement) {
|
||||||
tabLevel--;
|
NodeTree<ASTData> *identifier = children[i]->getChildren()[0]->getChildren()[0];
|
||||||
|
Type* declarationType = identifier->getDataRef()->valueType;
|
||||||
|
if (declarationType->getIndirection())
|
||||||
|
continue;
|
||||||
|
NodeTree<ASTData> *typeDefinition = declarationType->typeDefinition;
|
||||||
|
if (!typeDefinition)
|
||||||
|
continue;
|
||||||
|
if (typeDefinition->getDataRef()->scope.find("destruct") == typeDefinition->getDataRef()->scope.end())
|
||||||
|
continue;
|
||||||
|
destructorString += tabs() + CifyName(typeDefinition->getDataRef()->symbol.getName())
|
||||||
|
+ "__" + "destruct" + "(&" + generate(identifier, enclosingObject) + ");\n";//Call the destructor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output += destructorString;
|
||||||
|
tabLevel--;
|
||||||
output += tabs() + "}";
|
output += tabs() + "}";
|
||||||
return output;
|
return output;
|
||||||
case expression:
|
}
|
||||||
|
case expression:
|
||||||
output += " " + data.symbol.getName() + ", ";
|
output += " " + data.symbol.getName() + ", ";
|
||||||
case boolean_expression:
|
case boolean_expression:
|
||||||
output += " " + data.symbol.getName() + " ";
|
output += " " + data.symbol.getName() + " ";
|
||||||
@@ -175,7 +286,12 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
case declaration_statement:
|
case declaration_statement:
|
||||||
if (children.size() == 1)
|
if (children.size() == 1)
|
||||||
return ValueTypeToCType(children[0]->getData().valueType) + " " + generate(children[0], enclosingObject) + ";";
|
return ValueTypeToCType(children[0]->getData().valueType) + " " + generate(children[0], enclosingObject) + ";";
|
||||||
else
|
else if (children[1]->getChildren().size() && children[1]->getChildren()[0]->getChildren().size() > 1
|
||||||
|
&& children[1]->getChildren()[0]->getChildren()[1] == children[0]) {
|
||||||
|
//That is, if we're a declaration with an init position call (Object a.construct())
|
||||||
|
//We can tell if our function call (children[1])'s access operation([0])'s lhs ([1]) is the thing we just declared (children[0])
|
||||||
|
return ValueTypeToCType(children[0]->getData().valueType) + " " + generate(children[0], enclosingObject) + "; " + generate(children[1]) + "/*Init Position Call*/";
|
||||||
|
} else
|
||||||
return ValueTypeToCType(children[0]->getData().valueType) + " " + generate(children[0], enclosingObject) + " = " + generate(children[1], enclosingObject) + ";";
|
return ValueTypeToCType(children[0]->getData().valueType) + " " + generate(children[0], enclosingObject) + " = " + generate(children[1], enclosingObject) + ";";
|
||||||
case if_comp:
|
case if_comp:
|
||||||
if (generate(children[0], enclosingObject) == generatorString)
|
if (generate(children[0], enclosingObject) == generatorString)
|
||||||
@@ -198,11 +314,13 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
if (funcType == function) {
|
if (funcType == function) {
|
||||||
if (name == "++" || name == "--")
|
if (name == "++" || name == "--")
|
||||||
return generate(children[1], enclosingObject) + name;
|
return generate(children[1], enclosingObject) + name;
|
||||||
if (name == "*" && children.size() == 2) //Is dereference, not multiplication
|
if ( (name == "*" || name == "&" || name == "!" ) && children.size() == 2) //Is dereference, not multiplication, address-of, or other unary operator
|
||||||
return "*(" + generate(children[1], enclosingObject) + ")";
|
return name + "(" + generate(children[1], enclosingObject) + ")";
|
||||||
|
if (name == "[]")
|
||||||
|
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 == "!" )
|
|| name == "&&")
|
||||||
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)
|
||||||
@@ -212,18 +330,24 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
std::string functionName = children[2]->getDataRef()->symbol.getName();
|
std::string functionName = children[2]->getDataRef()->symbol.getName();
|
||||||
NodeTree<ASTData>* possibleObjectType = children[1]->getDataRef()->valueType->typeDefinition;
|
NodeTree<ASTData>* possibleObjectType = children[1]->getDataRef()->valueType->typeDefinition;
|
||||||
//If is an object method, generate it like one. Needs extension/modification for inheritence
|
//If is an object method, generate it like one. Needs extension/modification for inheritence
|
||||||
if (possibleObjectType && possibleObjectType->getDataRef()->scope.find(functionName) != possibleObjectType->getDataRef()->scope.end()) {
|
if (possibleObjectType) {
|
||||||
std::string nameDecoration;
|
NodeTree<ASTData>* unaliasedTypeDef = getMethodsObjectType(possibleObjectType, functionName);
|
||||||
std::vector<NodeTree<ASTData>*> functionDefChildren = children[2]->getChildren(); //The function def is the rhs of the access operation
|
if (unaliasedTypeDef) { //Test to see if the function's a member of this type_def, or if this is an alias, of the original type. Get this original type if it exists.
|
||||||
std::cout << "Decorating (in access-should be object) " << name << " " << functionDefChildren.size() << std::endl;
|
std::string nameDecoration;
|
||||||
for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++)
|
std::vector<NodeTree<ASTData>*> functionDefChildren = children[2]->getChildren(); //The function def is the rhs of the access operation
|
||||||
nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType);
|
std::cout << "Decorating (in access-should be object) " << name << " " << functionDefChildren.size() << std::endl;
|
||||||
/*HERE*/ return possibleObjectType->getDataRef()->symbol.getName() +"__" + CifyFunctionName(functionName) + nameDecoration + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject) + ",";
|
for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++)
|
||||||
//The comma lets the upper function call know we already started the param list
|
nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType);
|
||||||
//Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses
|
/*HERE*/ return CifyName(unaliasedTypeDef->getDataRef()->symbol.getName()) +"__" + CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject) + ",";
|
||||||
} else {
|
//The comma lets the upper function call know we already started the param list
|
||||||
std::cout << "Is not in scope or not type" << std::endl;
|
//Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses
|
||||||
return "((" + generate(children[1], enclosingObject) + ")" + name + functionName + ")";
|
} else {
|
||||||
|
std::cout << "Is not in scope or not type" << std::endl;
|
||||||
|
return "((" + generate(children[1], enclosingObject) + ")" + name + functionName + ")";
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
std::cout << "Is not in scope or not type" << std::endl;
|
||||||
|
return "((" + generate(children[1], enclosingObject) + ")" + name + functionName + ")";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2], enclosingObject) + ")";
|
//return "((" + generate(children[1], enclosingObject) + ")" + name + generate(children[2], enclosingObject) + ")";
|
||||||
@@ -239,10 +363,10 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
//Check to see if we're inside of an object and this is a method call
|
//Check to see if we're inside of an object and this is a method call
|
||||||
bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]);
|
bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]);
|
||||||
if (isSelfObjectMethod)
|
if (isSelfObjectMethod)
|
||||||
output += enclosingObject->getDataRef()->symbol.getName() +"__";
|
output += CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__";
|
||||||
/*HERE*/ output += CifyFunctionName(name) + nameDecoration + "(";
|
/*HERE*/ output += CifyName(name + nameDecoration) + "(";
|
||||||
if (isSelfObjectMethod)
|
if (isSelfObjectMethod)
|
||||||
output += children.size() > 1 ? "self," : "self";
|
output += children.size() > 1 ? "this," : "this";
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
//This part handles cases where our definition isn't the function definition (that is, it is probabally the return from another function)
|
//This part handles cases where our definition isn't the function definition (that is, it is probabally the return from another function)
|
||||||
@@ -272,22 +396,29 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
|||||||
|
|
||||||
return output;
|
return output;
|
||||||
}
|
}
|
||||||
|
NodeTree<ASTData>* CGenerator::getMethodsObjectType(NodeTree<ASTData>* scope, std::string functionName) {
|
||||||
|
//check the thing
|
||||||
|
while (scope != scope->getDataRef()->valueType->typeDefinition) //type is an alias, follow it to the definition
|
||||||
|
scope = scope->getDataRef()->valueType->typeDefinition;
|
||||||
|
return (scope->getDataRef()->scope.find(functionName) != scope->getDataRef()->scope.end()) ? scope : NULL;
|
||||||
|
}
|
||||||
|
|
||||||
std::string CGenerator::generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from) {
|
// Returns the function prototype in the out param and the full definition normally
|
||||||
std::string output;
|
std::string CGenerator::generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype) {
|
||||||
ASTData data = from->getData();
|
ASTData data = from->getData();
|
||||||
Type enclosingObjectType = *(enclosingObject->getDataRef()->valueType); //Copy a new type so we can turn it into a pointer if we need to
|
Type enclosingObjectType = *(enclosingObject->getDataRef()->valueType); //Copy a new type so we can turn it into a pointer if we need to
|
||||||
enclosingObjectType.indirection++;
|
enclosingObjectType.increaseIndirection();
|
||||||
std::vector<NodeTree<ASTData>*> children = from->getChildren();
|
std::vector<NodeTree<ASTData>*> children = from->getChildren();
|
||||||
std::string nameDecoration, parameters;
|
std::string nameDecoration, parameters;
|
||||||
for (int i = 0; i < children.size()-1; i++) {
|
for (int i = 0; i < children.size()-1; i++) {
|
||||||
parameters += ", " + ValueTypeToCType(children[i]->getData().valueType) + " " + generate(children[i]);
|
parameters += ", " + ValueTypeToCType(children[i]->getData().valueType) + " " + generate(children[i]);
|
||||||
nameDecoration += "_" + ValueTypeToCTypeDecoration(children[i]->getData().valueType);
|
nameDecoration += "_" + ValueTypeToCTypeDecoration(children[i]->getData().valueType);
|
||||||
}
|
}
|
||||||
output += "\n" + ValueTypeToCType(data.valueType) + " " + enclosingObject->getDataRef()->symbol.getName() +"__"
|
std::string functionSignature = "\n" + ValueTypeToCType(data.valueType) + " " + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"
|
||||||
+ CifyFunctionName(data.symbol.getName()) + nameDecoration + "(" + ValueTypeToCType(&enclosingObjectType)
|
+ CifyName(data.symbol.getName()) + nameDecoration + "(" + ValueTypeToCType(&enclosingObjectType)
|
||||||
+ " self" + parameters + ")\n" + generate(children[children.size()-1], enclosingObject); //Pass in the object so we can properly handle access to member stuff
|
+ " this" + parameters + ")";
|
||||||
return output;
|
*functionPrototype += functionSignature + ";\n";
|
||||||
|
return functionSignature + "\n" + generate(children[children.size()-1], enclosingObject); //Pass in the object so we can properly handle access to member stuff
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CGenerator::ValueTypeToCType(Type *type) {
|
std::string CGenerator::ValueTypeToCType(Type *type) {
|
||||||
@@ -295,7 +426,7 @@ std::string CGenerator::ValueTypeToCType(Type *type) {
|
|||||||
switch (type->baseType) {
|
switch (type->baseType) {
|
||||||
case none:
|
case none:
|
||||||
if (type->typeDefinition)
|
if (type->typeDefinition)
|
||||||
return_type = type->typeDefinition->getDataRef()->symbol.getName();
|
return_type = CifyName(type->typeDefinition->getDataRef()->symbol.getName());
|
||||||
else
|
else
|
||||||
return_type = "none";
|
return_type = "none";
|
||||||
break;
|
break;
|
||||||
@@ -321,7 +452,7 @@ std::string CGenerator::ValueTypeToCType(Type *type) {
|
|||||||
return_type = "unknown_ValueType";
|
return_type = "unknown_ValueType";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < type->indirection; i++)
|
for (int i = 0; i < type->getIndirection(); i++)
|
||||||
return_type += "*";
|
return_type += "*";
|
||||||
return return_type;
|
return return_type;
|
||||||
}
|
}
|
||||||
@@ -331,7 +462,7 @@ std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) {
|
|||||||
switch (type->baseType) {
|
switch (type->baseType) {
|
||||||
case none:
|
case none:
|
||||||
if (type->typeDefinition)
|
if (type->typeDefinition)
|
||||||
return_type = type->typeDefinition->getDataRef()->symbol.getName();
|
return_type = CifyName(type->typeDefinition->getDataRef()->symbol.getName());
|
||||||
else
|
else
|
||||||
return_type = "none";
|
return_type = "none";
|
||||||
break;
|
break;
|
||||||
@@ -357,12 +488,12 @@ std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) {
|
|||||||
return_type = "unknown_ValueType";
|
return_type = "unknown_ValueType";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
for (int i = 0; i < type->indirection; i++)
|
for (int i = 0; i < type->getIndirection(); i++)
|
||||||
return_type += "_P__";
|
return_type += "_P__";
|
||||||
return return_type;
|
return return_type;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CGenerator::CifyFunctionName(std::string name) {
|
std::string CGenerator::CifyName(std::string name) {
|
||||||
std::string operatorsToReplace[] = { "+", "plus",
|
std::string operatorsToReplace[] = { "+", "plus",
|
||||||
"-", "minus",
|
"-", "minus",
|
||||||
"*", "star",
|
"*", "star",
|
||||||
@@ -392,7 +523,14 @@ std::string CGenerator::CifyFunctionName(std::string name) {
|
|||||||
"|=", "pipeequals",
|
"|=", "pipeequals",
|
||||||
"*=", "starequals",
|
"*=", "starequals",
|
||||||
"<<=", "doublerightequals",
|
"<<=", "doublerightequals",
|
||||||
|
"<", "lessthan",
|
||||||
|
">", "greaterthan",
|
||||||
">>=", "doubleleftequals",
|
">>=", "doubleleftequals",
|
||||||
|
"(", "openparen",
|
||||||
|
")", "closeparen",
|
||||||
|
"[", "openbracket",
|
||||||
|
"]", "closebracket",
|
||||||
|
" ", "space",
|
||||||
"->", "arrow" };
|
"->", "arrow" };
|
||||||
int length = sizeof(operatorsToReplace)/sizeof(std::string);
|
int length = sizeof(operatorsToReplace)/sizeof(std::string);
|
||||||
//std::cout << "Length is " << length << std::endl;
|
//std::cout << "Length is " << length << std::endl;
|
||||||
|
|||||||
@@ -117,6 +117,13 @@ void GraphStructuredStack::addEdge(NodeTree<int>* start, NodeTree<int>* end, Nod
|
|||||||
edges[std::make_pair(start, end)] = edge;
|
edges[std::make_pair(start, end)] = edge;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<int> GraphStructuredStack::getFrontier(int frontier) {
|
||||||
|
std::vector<int> toReturn;
|
||||||
|
for (int i = 0; i < gss[frontier]->size(); i++)
|
||||||
|
toReturn.push_back((*(gss[frontier]))[i]->getData());
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
std::string GraphStructuredStack::toString() {
|
std::string GraphStructuredStack::toString() {
|
||||||
std::string tostring = "";
|
std::string tostring = "";
|
||||||
for (std::vector<std::vector<NodeTree<int>*>*>::size_type i = 0; i < gss.size(); i++) {
|
for (std::vector<std::vector<NodeTree<int>*>*>::size_type i = 0; i < gss.size(); i++) {
|
||||||
|
|||||||
122
src/Importer.cpp
122
src/Importer.cpp
@@ -1,9 +1,12 @@
|
|||||||
#include "Importer.h"
|
#include "Importer.h"
|
||||||
|
|
||||||
Importer::Importer(Parser* parserIn) {
|
Importer::Importer(Parser* parserIn, std::vector<std::string> includePaths) {
|
||||||
//constructor
|
//constructor
|
||||||
parser = parserIn;
|
parser = parserIn;
|
||||||
|
this->includePaths = includePaths;
|
||||||
|
ASTTransformer = new ASTTransformation(this);
|
||||||
|
|
||||||
|
removeSymbols.push_back(Symbol("$NULL$", true));
|
||||||
removeSymbols.push_back(Symbol("WS", false));
|
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));
|
||||||
@@ -13,13 +16,15 @@ Importer::Importer(Parser* parserIn) {
|
|||||||
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("import", true));
|
||||||
removeSymbols.push_back(Symbol("interpreter_directive", false));
|
removeSymbols.push_back(Symbol("interpreter_directive", false));
|
||||||
removeSymbols.push_back(Symbol("if", true));
|
removeSymbols.push_back(Symbol("if", true));
|
||||||
removeSymbols.push_back(Symbol("while", true));
|
removeSymbols.push_back(Symbol("while", true));
|
||||||
removeSymbols.push_back(Symbol("__if_comp__", true));
|
removeSymbols.push_back(Symbol("__if_comp__", true));
|
||||||
removeSymbols.push_back(Symbol("comp_simple_passthrough", true));
|
removeSymbols.push_back(Symbol("comp_simple_passthrough", true));
|
||||||
removeSymbols.push_back(Symbol("typedef", true));
|
removeSymbols.push_back(Symbol("typedef", true));
|
||||||
|
removeSymbols.push_back(Symbol("template", true));
|
||||||
|
removeSymbols.push_back(Symbol("\\|", true));
|
||||||
|
|
||||||
collapseSymbols.push_back(Symbol("opt_typed_parameter_list", false));
|
collapseSymbols.push_back(Symbol("opt_typed_parameter_list", false));
|
||||||
collapseSymbols.push_back(Symbol("opt_parameter_list", false));
|
collapseSymbols.push_back(Symbol("opt_parameter_list", false));
|
||||||
@@ -31,23 +36,102 @@ Importer::Importer(Parser* parserIn) {
|
|||||||
collapseSymbols.push_back(Symbol("unorderd_list_part", false));
|
collapseSymbols.push_back(Symbol("unorderd_list_part", false));
|
||||||
collapseSymbols.push_back(Symbol("if_comp_pred", false));
|
collapseSymbols.push_back(Symbol("if_comp_pred", false));
|
||||||
collapseSymbols.push_back(Symbol("declaration_block", false));
|
collapseSymbols.push_back(Symbol("declaration_block", false));
|
||||||
|
collapseSymbols.push_back(Symbol("type_list", false));
|
||||||
|
collapseSymbols.push_back(Symbol("template_param_list", false));
|
||||||
|
collapseSymbols.push_back(Symbol("trait_list", false));
|
||||||
|
collapseSymbols.push_back(Symbol("dec_type", false));
|
||||||
}
|
}
|
||||||
|
|
||||||
Importer::~Importer() {
|
Importer::~Importer() {
|
||||||
//destructor
|
//destructor
|
||||||
|
delete ASTTransformer;
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeTree<ASTData>* Importer::import(std::string fileName) {
|
void Importer::registerAST(std::string name, NodeTree<ASTData>* ast, NodeTree<Symbol>* syntaxTree) {
|
||||||
|
imported[name] = ast;
|
||||||
|
importedTrips.push_back({name, ast, syntaxTree});
|
||||||
|
std::cout << "REGISTERD " << name << std::endl;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeTree<ASTData>* Importer::getUnit(std::string fileName) {
|
||||||
|
std::cout << "\n\nImporting " << fileName << " ";
|
||||||
//Check to see if we've already done it
|
//Check to see if we've already done it
|
||||||
if (imported.find(fileName) != imported.end())
|
if (imported.find(fileName) != imported.end()) {
|
||||||
|
std::cout << "Already Imported!" << std::endl;
|
||||||
return imported[fileName];
|
return imported[fileName];
|
||||||
|
}
|
||||||
|
std::cout << "Not yet imported" << std::endl;
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeTree<ASTData>* Importer::importFirstPass(std::string fileName) {
|
||||||
|
NodeTree<ASTData>* ast = getUnit(fileName);
|
||||||
|
if (ast == NULL) {
|
||||||
|
NodeTree<Symbol>* parseTree = parseAndTrim(fileName);
|
||||||
|
if (!parseTree)
|
||||||
|
return NULL;
|
||||||
|
//Call with ourself to allow the transformation to call us to import files that it needs
|
||||||
|
ast = ASTTransformer->firstPass(fileName, parseTree); //This firstPass will register itself
|
||||||
|
}
|
||||||
|
return ast;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Importer::import(std::string fileName) {
|
||||||
|
|
||||||
|
//Start the ball rolling by importing and running the first pass on the first file.
|
||||||
|
//This will import, first pass and register all the other files too.
|
||||||
|
|
||||||
|
std::cout << "\n\n =====FIRST PASS===== \n\n" << std::endl;
|
||||||
|
importFirstPass(fileName); //First pass defines all objects
|
||||||
|
|
||||||
|
std::cout << "\n\n =====SECOND PASS===== \n\n" << std::endl;
|
||||||
|
for (importTriplet i : importedTrips) //Second pass defines data inside objects, outside declaration statements,
|
||||||
|
std::cout << "\n\nSecond pass for: " << i.name << std::endl, ASTTransformer->secondPass(i.ast, i.syntaxTree); //function prototypes, and identifiers (as we now have all type defs)
|
||||||
|
|
||||||
|
std::cout << "\n\n =====THIRD PASS===== \n\n" << std::endl;
|
||||||
|
for (importTriplet i : importedTrips) //Third pass redoes all imports to import the new function prototypes and identifiers
|
||||||
|
std::cout << "\n\nThird pass for: " << i.name << std::endl, ASTTransformer->thirdPass(i.ast);
|
||||||
|
|
||||||
|
std::cout << "\n\n =====FOURTH PASS===== \n\n" << std::endl;
|
||||||
|
for (importTriplet i : importedTrips) //Fourth pass finishes up by doing all function bodies
|
||||||
|
std::cout << "\n\nFourth pass for: " << i.name << std::endl, ASTTransformer->fourthPass(i.ast, i.syntaxTree); //With that, we're done
|
||||||
|
|
||||||
|
//Note that class template instantiation can happen in the second or fourth passes and that function template instantion
|
||||||
|
//can happen in the fourth pass.
|
||||||
|
|
||||||
|
std::ofstream outFileAST;
|
||||||
|
for (importTriplet i : importedTrips) {
|
||||||
|
std::string outputName = i.name + "out";
|
||||||
|
outFileAST.open((outputName + ".AST.dot").c_str());
|
||||||
|
if (!outFileAST.is_open()) {
|
||||||
|
std::cout << "Problem opening second output file " << outputName + ".AST.dot" << "\n";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (i.ast) {
|
||||||
|
outFileAST << i.ast->DOTGraphString() << std::endl;
|
||||||
|
} else {
|
||||||
|
std::cout << "Tree returned from ASTTransformation for " << fileName << " is NULL!" << std::endl;
|
||||||
|
}
|
||||||
|
outFileAST.close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NodeTree<Symbol>* Importer::parseAndTrim(std::string fileName) {
|
||||||
|
|
||||||
std::ifstream programInFile;
|
std::ifstream programInFile;
|
||||||
std::ofstream outFile, outFileTransformed, outFileAST;
|
std::ofstream outFile, outFileTransformed;
|
||||||
|
|
||||||
|
|
||||||
std::string outputName = fileName + "out";
|
std::string outputName = fileName + "out";
|
||||||
|
|
||||||
programInFile.open(fileName);
|
for (auto i : includePaths) {
|
||||||
|
programInFile.open(i+fileName);
|
||||||
|
if (programInFile.is_open())
|
||||||
|
break;
|
||||||
|
else
|
||||||
|
std::cout << i+fileName << " is no good" << std::endl;
|
||||||
|
}
|
||||||
if (!programInFile.is_open()) {
|
if (!programInFile.is_open()) {
|
||||||
std::cout << "Problem opening programInFile " << fileName << "\n";
|
std::cout << "Problem opening programInFile " << fileName << "\n";
|
||||||
return NULL;
|
return NULL;
|
||||||
@@ -65,12 +149,6 @@ NodeTree<ASTData>* Importer::import(std::string fileName) {
|
|||||||
return NULL;
|
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string programInputFileString, line;
|
std::string programInputFileString, line;
|
||||||
while(programInFile.good()) {
|
while(programInFile.good()) {
|
||||||
getline(programInFile, line);
|
getline(programInFile, line);
|
||||||
@@ -85,8 +163,10 @@ NodeTree<ASTData>* Importer::import(std::string fileName) {
|
|||||||
//std::cout << parseTree->DOTGraphString() << std::endl;
|
//std::cout << parseTree->DOTGraphString() << std::endl;
|
||||||
outFile << parseTree->DOTGraphString() << std::endl;
|
outFile << parseTree->DOTGraphString() << std::endl;
|
||||||
} else {
|
} else {
|
||||||
std::cout << "ParseTree returned from parser is NULL!" << std::endl;
|
std::cout << "ParseTree returned from parser for " << fileName << " is NULL!" << std::endl;
|
||||||
}
|
outFile.close(); outFileTransformed.close();
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
outFile.close();
|
outFile.close();
|
||||||
|
|
||||||
//Remove Transformations
|
//Remove Transformations
|
||||||
@@ -106,19 +186,7 @@ NodeTree<ASTData>* Importer::import(std::string fileName) {
|
|||||||
}
|
}
|
||||||
outFileTransformed.close();
|
outFileTransformed.close();
|
||||||
|
|
||||||
//Call with ourself to allow the transformation to call us to import files that it needs
|
return parseTree;
|
||||||
NodeTree<ASTData>* 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();
|
|
||||||
|
|
||||||
imported[fileName] = AST;
|
|
||||||
|
|
||||||
return AST;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::map<std::string, NodeTree<ASTData>*> Importer::getASTMap() {
|
std::map<std::string, NodeTree<ASTData>*> Importer::getASTMap() {
|
||||||
|
|||||||
@@ -22,18 +22,33 @@ ParseAction::~ParseAction() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool ParseAction::equalsExceptLookahead(const ParseAction &other) {
|
const bool ParseAction::equalsExceptLookahead(const ParseAction &other) const {
|
||||||
return( action == other.action && ( reduceRule == other.reduceRule || reduceRule->equalsExceptLookahead(*(other.reduceRule)) ) && shiftState == other.shiftState);
|
return( action == other.action && ( reduceRule == other.reduceRule || reduceRule->equalsExceptLookahead(*(other.reduceRule)) ) && shiftState == other.shiftState);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool ParseAction::operator==(const ParseAction &other) {
|
const bool ParseAction::operator==(const ParseAction &other) const {
|
||||||
return( action == other.action && ( reduceRule == other.reduceRule || *reduceRule == *(other.reduceRule) ) && shiftState == other.shiftState);
|
return( action == other.action && ( reduceRule == other.reduceRule || *reduceRule == *(other.reduceRule) ) && shiftState == other.shiftState);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool ParseAction::operator!=(const ParseAction &other) {
|
const bool ParseAction::operator!=(const ParseAction &other) const {
|
||||||
return !(this->operator==(other));
|
return !(this->operator==(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Exists so we can put ParseActions into sets
|
||||||
|
const bool ParseAction::operator<(const ParseAction &other) const {
|
||||||
|
if (action != other.action)
|
||||||
|
return action < other.action;
|
||||||
|
if (reduceRule != other.reduceRule) {
|
||||||
|
if (! (reduceRule && other.reduceRule)) {
|
||||||
|
return reduceRule < other.reduceRule;
|
||||||
|
} else {
|
||||||
|
return *reduceRule < *(other.reduceRule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return shiftState < other.shiftState;
|
||||||
|
}
|
||||||
|
|
||||||
std::string ParseAction::actionToString(ActionType action) {
|
std::string ParseAction::actionToString(ActionType action) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case REDUCE:
|
case REDUCE:
|
||||||
@@ -53,11 +68,11 @@ std::string ParseAction::actionToString(ActionType action) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ParseAction::toString() {
|
std::string ParseAction::toString(bool printRuleLookahead) {
|
||||||
std::string outputString = "";
|
std::string outputString = "";
|
||||||
outputString += actionToString(action);
|
outputString += actionToString(action);
|
||||||
if (reduceRule != NULL)
|
if (reduceRule != NULL)
|
||||||
outputString += " " + reduceRule->toString();
|
outputString += " " + reduceRule->toString(printRuleLookahead);
|
||||||
if (shiftState != -1)
|
if (shiftState != -1)
|
||||||
outputString += " " + intToString(shiftState);
|
outputString += " " + intToString(shiftState);
|
||||||
return(outputString);
|
return(outputString);
|
||||||
|
|||||||
@@ -16,18 +16,34 @@ ParseRule::~ParseRule() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool ParseRule::equalsExceptLookahead(const ParseRule &other) {
|
const bool ParseRule::equalsExceptLookahead(const ParseRule &other) const {
|
||||||
return(leftHandle == other.leftHandle && rightSide == other.rightSide && pointerIndex == other.pointerIndex);
|
return(leftHandle == other.leftHandle && rightSide == other.rightSide && pointerIndex == other.pointerIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool ParseRule::operator==(const ParseRule &other) {
|
const bool ParseRule::operator==(const ParseRule &other) const {
|
||||||
return(equalsExceptLookahead(other) && (lookahead == NULL ? other.lookahead == NULL : (*lookahead) == *(other.lookahead)));
|
return(equalsExceptLookahead(other) && (lookahead == NULL ? other.lookahead == NULL : (*lookahead) == *(other.lookahead)));
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool ParseRule::operator!=(const ParseRule &other) {
|
const bool ParseRule::operator!=(const ParseRule &other) const {
|
||||||
return !(this->operator==(other));
|
return !(this->operator==(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const bool ParseRule::operator<(const ParseRule &other) const {
|
||||||
|
//Used for ordering so we can put ParseRule's in sets, and also so that ParseActions will have an ordering
|
||||||
|
if (leftHandle != other.leftHandle)
|
||||||
|
return leftHandle < other.leftHandle;
|
||||||
|
if (rightSide != other.rightSide)
|
||||||
|
return rightSide < other.rightSide;
|
||||||
|
if (lookahead != other.lookahead) {
|
||||||
|
if (! (lookahead && other.lookahead)) {
|
||||||
|
return lookahead < other.lookahead;
|
||||||
|
} else {
|
||||||
|
return *lookahead < *(other.lookahead);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
ParseRule* ParseRule::clone() {
|
ParseRule* ParseRule::clone() {
|
||||||
std::vector<Symbol>* newLookahead = NULL;
|
std::vector<Symbol>* newLookahead = NULL;
|
||||||
if (lookahead) {
|
if (lookahead) {
|
||||||
@@ -111,7 +127,7 @@ std::vector<Symbol>* ParseRule::getLookahead() {
|
|||||||
return lookahead;
|
return lookahead;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string ParseRule::toString() {
|
std::string ParseRule::toString(bool printLookahead) {
|
||||||
std::string concat = leftHandle.toString() + " -> ";
|
std::string concat = leftHandle.toString() + " -> ";
|
||||||
for (int i = 0; i < rightSide.size(); i++) {
|
for (int i = 0; i < rightSide.size(); i++) {
|
||||||
if (i == pointerIndex)
|
if (i == pointerIndex)
|
||||||
@@ -120,7 +136,7 @@ std::string ParseRule::toString() {
|
|||||||
}
|
}
|
||||||
if (pointerIndex >= rightSide.size())
|
if (pointerIndex >= rightSide.size())
|
||||||
concat += "(*)";
|
concat += "(*)";
|
||||||
if (lookahead != NULL) {
|
if (printLookahead && lookahead != NULL) {
|
||||||
concat += "**";
|
concat += "**";
|
||||||
for (std::vector<Symbol>::size_type i = 0; i < lookahead->size(); i++)
|
for (std::vector<Symbol>::size_type i = 0; i < lookahead->size(); i++)
|
||||||
concat += (*lookahead)[i].toString();
|
concat += (*lookahead)[i].toString();
|
||||||
|
|||||||
114
src/Parser.cpp
114
src/Parser.cpp
@@ -32,10 +32,22 @@ Symbol Parser::getOrAddSymbol(std::string symbolString, bool isTerminal) {
|
|||||||
void Parser::loadGrammer(std::string grammerInputString) {
|
void Parser::loadGrammer(std::string grammerInputString) {
|
||||||
reader.setString(grammerInputString);
|
reader.setString(grammerInputString);
|
||||||
|
|
||||||
std::string currToken = reader.word();
|
std::string currToken = reader.word(false); //Don't truncate so we can find the newline correctly (needed for comments)
|
||||||
|
|
||||||
while(currToken != "") {
|
while(currToken != "") {
|
||||||
//Load the left of the rule
|
//First, if this starts with a '#', skip this
|
||||||
|
if (currToken.front() == '#') {
|
||||||
|
//If this line is more than one token long, eat it
|
||||||
|
std::cout << "Ate: " << currToken << std::endl;
|
||||||
|
if (currToken.back() != '\n')
|
||||||
|
std::cout << "Eating " << reader.line() << " b/c grammer comment" << std::endl;
|
||||||
|
currToken = reader.word(false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (currToken.back() == '\n' || currToken.back() == ' ' || currToken.back() == '\t')
|
||||||
|
currToken.erase(currToken.size()-1);
|
||||||
|
|
||||||
|
//Load the left of the rule
|
||||||
ParseRule* currentRule = new ParseRule();
|
ParseRule* currentRule = new ParseRule();
|
||||||
Symbol leftSide = getOrAddSymbol(currToken, false); //Left handle is never a terminal
|
Symbol leftSide = getOrAddSymbol(currToken, false); //Left handle is never a terminal
|
||||||
currentRule->setLeftHandle(leftSide);
|
currentRule->setLeftHandle(leftSide);
|
||||||
@@ -76,7 +88,7 @@ void Parser::loadGrammer(std::string grammerInputString) {
|
|||||||
|
|
||||||
loadedGrammer.push_back(currentRule);
|
loadedGrammer.push_back(currentRule);
|
||||||
//Get next token
|
//Get next token
|
||||||
currToken = reader.word();
|
currToken = reader.word(false);
|
||||||
}
|
}
|
||||||
//std::cout << "Parsed!\n";
|
//std::cout << "Parsed!\n";
|
||||||
|
|
||||||
@@ -117,59 +129,86 @@ int Parser::stateNum(State* state) {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<Symbol>* Parser::firstSet(Symbol token) {
|
std::vector<Symbol> Parser::firstSet(Symbol token, std::vector<Symbol> avoidList, bool addNewTokens) {
|
||||||
std::vector<Symbol> avoidList;
|
if (tokenFirstSet.find(token) != tokenFirstSet.end())
|
||||||
return firstSet(token, avoidList);
|
return tokenFirstSet[token];
|
||||||
}
|
//If we've already done this token, don't do it again
|
||||||
|
|
||||||
std::vector<Symbol>* Parser::firstSet(Symbol token, std::vector<Symbol> avoidList) {
|
|
||||||
//If we've already done this token, don't do it again
|
|
||||||
for (std::vector<Symbol>::size_type i = 0; i < avoidList.size(); i++)
|
for (std::vector<Symbol>::size_type i = 0; i < avoidList.size(); i++)
|
||||||
if (avoidList[i] == token) {
|
if (avoidList[i] == token)
|
||||||
return new std::vector<Symbol>();
|
return std::vector<Symbol>();
|
||||||
}
|
|
||||||
avoidList.push_back(token);
|
avoidList.push_back(token);
|
||||||
std::vector<Symbol>* first = new std::vector<Symbol>();
|
|
||||||
|
std::vector<Symbol> first;
|
||||||
//First, if the symbol is a terminal, than it's first set is just itself.
|
//First, if the symbol is a terminal, than it's first set is just itself.
|
||||||
if (token.isTerminal()) {
|
if (token.isTerminal()) {
|
||||||
first->push_back(token);
|
first.push_back(token);
|
||||||
return(first);
|
return(first);
|
||||||
}
|
}
|
||||||
//Otherwise....
|
//Otherwise....
|
||||||
//Ok, to make a first set, go through the grammer, if the token it's left side, add it's production's first token's first set.
|
//Ok, to make a first set, go through the grammer, if the token it's left side, add it's production's first token's first set.
|
||||||
//If that one includes mull, do the next one too (if it exists).
|
//If that one includes mull, do the next one too (if it exists).
|
||||||
Symbol rightToken;
|
Symbol rightToken;
|
||||||
std::vector<Symbol>* recursiveFirstSet = NULL;
|
std::vector<Symbol> recursiveFirstSet;
|
||||||
for (std::vector<ParseRule*>::size_type i = 0; i < loadedGrammer.size(); i++) {
|
for (std::vector<ParseRule*>::size_type i = 0; i < loadedGrammer.size(); i++) {
|
||||||
if (token == loadedGrammer[i]->getLeftSide()) {
|
if (token == loadedGrammer[i]->getLeftSide()) {
|
||||||
//Loop through the rule adding first sets for each token if the previous token contained NULL
|
//Loop through the rule adding first sets for each token if the previous token contained NULL
|
||||||
bool recFirstSetHasNull = false;
|
|
||||||
int j = 0;
|
int j = 0;
|
||||||
do {
|
do {
|
||||||
rightToken = loadedGrammer[i]->getRightSide()[j]; //Get token of the right side of this rule
|
rightToken = loadedGrammer[i]->getRightSide()[j]; //Get token of the right side of this rule
|
||||||
if (rightToken.isTerminal()) {
|
if (rightToken.isTerminal()) {
|
||||||
recursiveFirstSet = new std::vector<Symbol>();
|
recursiveFirstSet.push_back(rightToken);
|
||||||
recursiveFirstSet->push_back(rightToken);
|
|
||||||
} else {
|
} else {
|
||||||
//Add the entire set
|
//Add the entire set
|
||||||
recursiveFirstSet = firstSet(rightToken, avoidList);
|
recursiveFirstSet = firstSet(rightToken, avoidList, false);//Don't add children to cache, as early termination may cause them to be incomplete
|
||||||
}
|
}
|
||||||
first->insert(first->end(), recursiveFirstSet->begin(), recursiveFirstSet->end());
|
first.insert(first.end(), recursiveFirstSet.begin(), recursiveFirstSet.end());
|
||||||
//Check to see if the current recursiveFirstSet contains NULL, if so, then go through again with the next token. (if there is one)
|
|
||||||
recFirstSetHasNull = false;
|
|
||||||
for (std::vector<Symbol>::size_type k = 0; k < recursiveFirstSet->size(); k++) {
|
|
||||||
if ((*recursiveFirstSet)[k] == nullSymbol) {
|
|
||||||
recFirstSetHasNull = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
delete recursiveFirstSet;
|
|
||||||
j++;
|
j++;
|
||||||
} while (recFirstSetHasNull && loadedGrammer[i]->getRightSide().size() > j);
|
} while (isNullable(rightToken) && loadedGrammer[i]->getRightSide().size() > j);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (addNewTokens)
|
||||||
|
tokenFirstSet[token] = first;
|
||||||
return(first);
|
return(first);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Parser::isNullable(Symbol token) {
|
||||||
|
if (tokenNullable.find(token) != tokenNullable.end())
|
||||||
|
return tokenNullable[token];
|
||||||
|
bool nullable = isNullableHelper(token, std::set<Symbol>());
|
||||||
|
tokenNullable[token] = nullable;
|
||||||
|
return nullable;
|
||||||
|
}
|
||||||
|
//We use this helper function to recurse because it is possible to wind up with loops, and if so we want
|
||||||
|
//early termination. However, this means that nullable determinations in the middle of the loop are inaccurate
|
||||||
|
//(since we terminated early), so we don't want to save them. Thus, for simplicity, only the main method will
|
||||||
|
//add to the cache. This is somewhat unfortunate for preformance, but the necessary additions to keep track of
|
||||||
|
//invalidated state are more complicated than it's worth.
|
||||||
|
bool Parser::isNullableHelper(Symbol token, std::set<Symbol> done) {
|
||||||
|
if (token.isTerminal())
|
||||||
|
return token == nullSymbol;
|
||||||
|
if (done.find(token) != done.end())
|
||||||
|
return false;
|
||||||
|
done.insert(token);
|
||||||
|
if (tokenNullable.find(token) != tokenNullable.end())
|
||||||
|
return tokenNullable[token];
|
||||||
|
|
||||||
|
for (std::vector<ParseRule*>::size_type i = 0; i < loadedGrammer.size(); i++) {
|
||||||
|
if (token == loadedGrammer[i]->getLeftSide()) {
|
||||||
|
auto rightSide = loadedGrammer[i]->getRightSide();
|
||||||
|
bool ruleNullable = true;
|
||||||
|
for (int j = 0; j < rightSide.size(); j++) {
|
||||||
|
if (!isNullableHelper(rightSide[j], done)) {
|
||||||
|
ruleNullable = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (ruleNullable)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
//Return the correct lookahead. This followSet is built based on the current rule's lookahead if at end, or the next Symbol's first set.
|
//Return the correct lookahead. This followSet is built based on the current rule's lookahead if at end, or the next Symbol's first set.
|
||||||
std::vector<Symbol>* Parser::incrementiveFollowSet(ParseRule* rule) {
|
std::vector<Symbol>* Parser::incrementiveFollowSet(ParseRule* rule) {
|
||||||
//Advance the pointer past the current Symbol (the one we want the followset for) to the next symbol (which might be in our follow set, or might be the end)
|
//Advance the pointer past the current Symbol (the one we want the followset for) to the next symbol (which might be in our follow set, or might be the end)
|
||||||
@@ -178,25 +217,24 @@ std::vector<Symbol>* Parser::incrementiveFollowSet(ParseRule* rule) {
|
|||||||
|
|
||||||
//Get the first set of the next Symbol. If it contains nullSymbol, keep doing for the next one
|
//Get the first set of the next Symbol. If it contains nullSymbol, keep doing for the next one
|
||||||
std::vector<Symbol>* followSet = new std::vector<Symbol>();
|
std::vector<Symbol>* followSet = new std::vector<Symbol>();
|
||||||
std::vector<Symbol>* symbolFirstSet;
|
std::vector<Symbol> symbolFirstSet;
|
||||||
bool symbolFirstSetHasNull = true;
|
bool symbolFirstSetHasNull = true;
|
||||||
while (symbolFirstSetHasNull && !rule->isAtEnd()) {
|
while (symbolFirstSetHasNull && !rule->isAtEnd()) {
|
||||||
symbolFirstSetHasNull = false;
|
symbolFirstSetHasNull = false;
|
||||||
symbolFirstSet = firstSet(rule->getAtNextIndex());
|
symbolFirstSet = firstSet(rule->getAtNextIndex());
|
||||||
for (std::vector<Symbol>::size_type i = 0; i < symbolFirstSet->size(); i++) {
|
for (std::vector<Symbol>::size_type i = 0; i < symbolFirstSet.size(); i++) {
|
||||||
if ((*symbolFirstSet)[i] == nullSymbol) {
|
if (symbolFirstSet[i] == nullSymbol) {
|
||||||
symbolFirstSetHasNull = true;
|
symbolFirstSetHasNull = true;
|
||||||
symbolFirstSet->erase(symbolFirstSet->begin()+i);
|
symbolFirstSet.erase(symbolFirstSet.begin()+i);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
followSet->insert(followSet->end(), symbolFirstSet->begin(), symbolFirstSet->end());
|
followSet->insert(followSet->end(), symbolFirstSet.begin(), symbolFirstSet.end());
|
||||||
delete symbolFirstSet;
|
|
||||||
rule->advancePointer();
|
rule->advancePointer();
|
||||||
}
|
}
|
||||||
if (rule->isAtEnd()) {
|
if (rule->isAtEnd()) {
|
||||||
symbolFirstSet = rule->getLookahead();
|
symbolFirstSet = *(rule->getLookahead());
|
||||||
followSet->insert(followSet->end(), symbolFirstSet->begin(), symbolFirstSet->end());
|
followSet->insert(followSet->end(), symbolFirstSet.begin(), symbolFirstSet.end());
|
||||||
}
|
}
|
||||||
std::vector<Symbol>* followSetReturn = new std::vector<Symbol>();
|
std::vector<Symbol>* followSetReturn = new std::vector<Symbol>();
|
||||||
for (std::vector<Symbol>::size_type i = 0; i < followSet->size(); i++) {
|
for (std::vector<Symbol>::size_type i = 0; i < followSet->size(); i++) {
|
||||||
|
|||||||
@@ -8,6 +8,20 @@ RNGLRParser::~RNGLRParser() {
|
|||||||
//
|
//
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RNGLRParser::printReconstructedFrontier(int frontier) {
|
||||||
|
std::vector<int> lastFrontier = gss.getFrontier(frontier);
|
||||||
|
for (int j = 0; j < lastFrontier.size(); j++) {
|
||||||
|
std::cout << "State: " << lastFrontier[j] << std::endl;
|
||||||
|
std::vector<std::pair<std::string, ParseAction>> stateParseActions = table.stateAsParseActionVector(lastFrontier[j]);
|
||||||
|
std::set<std::pair<std::string, ParseAction>> noRepeats;
|
||||||
|
for (auto k : stateParseActions)
|
||||||
|
noRepeats.insert(k);
|
||||||
|
for (auto k : noRepeats)
|
||||||
|
std::cout << k.first << " " << k.second.toString(false) << std::endl;
|
||||||
|
std::cout << std::endl;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NodeTree<Symbol>* RNGLRParser::parseInput(std::string inputString) {
|
NodeTree<Symbol>* RNGLRParser::parseInput(std::string inputString) {
|
||||||
input.clear();
|
input.clear();
|
||||||
gss.clear();
|
gss.clear();
|
||||||
@@ -74,7 +88,6 @@ NodeTree<Symbol>* RNGLRParser::parseInput(std::string inputString) {
|
|||||||
else if (firstActions[i]->action == ParseAction::REDUCE && fullyReducesToNull(firstActions[i]->reduceRule)) {
|
else if (firstActions[i]->action == ParseAction::REDUCE && fullyReducesToNull(firstActions[i]->reduceRule)) {
|
||||||
Reduction newReduction = {v0, firstActions[i]->reduceRule->getLeftSide(), 0, getNullableParts(firstActions[i]->reduceRule), NULL};
|
Reduction newReduction = {v0, firstActions[i]->reduceRule->getLeftSide(), 0, getNullableParts(firstActions[i]->reduceRule), NULL};
|
||||||
toReduce.push(newReduction);
|
toReduce.push(newReduction);
|
||||||
//toReduce.push(std::make_pair(std::make_pair(v0, firstActions[i]->reduceRule->getLeftSide()), 0));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,14 +102,21 @@ NodeTree<Symbol>* RNGLRParser::parseInput(std::string inputString) {
|
|||||||
std::cout << "Parsing failed on " << input[i].toString() << std::endl;
|
std::cout << "Parsing failed on " << input[i].toString() << std::endl;
|
||||||
std::cout << "Problem is on line: " << findLine(i) << std::endl;
|
std::cout << "Problem is on line: " << findLine(i) << std::endl;
|
||||||
std::cout << "Nearby is:" << std::endl;
|
std::cout << "Nearby is:" << std::endl;
|
||||||
const int range = 10;
|
int range = 10;
|
||||||
for (int j = (i-range >= 0 ? i-range : 0); j < (i+range < input.size() ? i+range : input.size()); j++)
|
for (int j = (i-range >= 0 ? i-range : 0); j < (i+range < input.size() ? i+range : input.size()); j++)
|
||||||
if (j == i)
|
if (j == i)
|
||||||
std::cout << "||*||*||" << input[j].toString() << "||*||*|| ";
|
std::cout << "||*||*||" << input[j].toString() << "||*||*|| ";
|
||||||
else
|
else
|
||||||
std::cout << input[j].toString() << " ";
|
std::cout << input[j].toString() << " ";
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
break;
|
range = 1;
|
||||||
|
/* std::cout << "\n\n\nThe states in the GSS at last frontiers:" << std::endl;
|
||||||
|
for (int j = (i-range >= 0 ? i-range : 0); j < i; j++) {
|
||||||
|
std::cout << "Frontier:" << j << " (would get): " << input[j].toString() << std::endl;
|
||||||
|
printReconstructedFrontier(j);
|
||||||
|
}
|
||||||
|
std::cout << "\n\n\n\n" << std::endl;
|
||||||
|
*/ break;
|
||||||
}
|
}
|
||||||
|
|
||||||
//Clear the vector of SPPF nodes created every step
|
//Clear the vector of SPPF nodes created every step
|
||||||
|
|||||||
@@ -353,6 +353,17 @@ ParseAction* Table::getShift(int state, Symbol token) {
|
|||||||
return shift;
|
return shift;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::vector<std::pair<std::string, ParseAction>> Table::stateAsParseActionVector(int state) {
|
||||||
|
std::vector<std::pair<std::string, ParseAction>> reconstructedState;
|
||||||
|
std::vector<std::vector<ParseAction*>*>* stateVec = table[state];
|
||||||
|
for (int i = 0; i < stateVec->size(); i++)
|
||||||
|
if (std::vector<ParseAction*>* forStateAndSymbol = (*stateVec)[i])
|
||||||
|
for (int j = 0; j < forStateAndSymbol->size(); j++)
|
||||||
|
reconstructedState.push_back(std::make_pair(symbolIndexVec[i].toString(),*((*forStateAndSymbol)[j])));
|
||||||
|
|
||||||
|
return reconstructedState;
|
||||||
|
}
|
||||||
|
|
||||||
std::string Table::toString() {
|
std::string Table::toString() {
|
||||||
std::string concat = "";
|
std::string concat = "";
|
||||||
for (std::vector<Symbol>::size_type i = 0; i < symbolIndexVec.size(); i++)
|
for (std::vector<Symbol>::size_type i = 0; i < symbolIndexVec.size(); i++)
|
||||||
|
|||||||
69
src/Tester.cpp
Normal file
69
src/Tester.cpp
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
#include "Tester.h"
|
||||||
|
|
||||||
|
Tester::Tester(std::string krakenInvocation, std::string krakenGrammerLocation) : krakenInvocation(krakenInvocation), krakenGrammerLocation(krakenGrammerLocation) {
|
||||||
|
//initlization list
|
||||||
|
removeCmd = "rm";
|
||||||
|
resultsExtention = ".results";
|
||||||
|
expectedExtention = ".expected_results";
|
||||||
|
krakenExtention = ".krak";
|
||||||
|
changePermissions = "chmod 755";
|
||||||
|
shell = "sh";
|
||||||
|
redirect = ">";
|
||||||
|
}
|
||||||
|
|
||||||
|
Tester::~Tester() {
|
||||||
|
//Nothing
|
||||||
|
}
|
||||||
|
|
||||||
|
int Tester::ssystem(std::string command) {
|
||||||
|
return system(command.c_str());
|
||||||
|
}
|
||||||
|
|
||||||
|
void Tester::cleanExtras(std::string fileName) {
|
||||||
|
ssystem(removeCmd + " " + fileName);
|
||||||
|
ssystem(removeCmd + " " + fileName + krakenExtention + "out*");
|
||||||
|
ssystem(removeCmd + " " + fileName + krakenExtention + ".c");
|
||||||
|
ssystem(removeCmd + " " + fileName + ".sh");
|
||||||
|
ssystem(removeCmd + " " + fileName + resultsExtention);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tester::run(std::string fileName) {
|
||||||
|
std::cout << "Testing: " << fileName << " with " << krakenInvocation << " and " << krakenGrammerLocation << std::endl;
|
||||||
|
|
||||||
|
cleanExtras(fileName);
|
||||||
|
|
||||||
|
ssystem(changePermissions + " " + fileName);
|
||||||
|
ssystem(krakenInvocation + " " + fileName + krakenExtention + " " + krakenGrammerLocation + " " + fileName);
|
||||||
|
ssystem(shell + " " + fileName + ".sh");
|
||||||
|
ssystem(fileName + " " + redirect + " " + fileName + resultsExtention);
|
||||||
|
|
||||||
|
bool result = compareFiles(fileName + expectedExtention, fileName + resultsExtention);
|
||||||
|
|
||||||
|
//If the test was succesful, we don't need all the extra files
|
||||||
|
if (result)
|
||||||
|
cleanExtras(fileName);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Tester::compareFiles(std::string file1Path, std::string file2Path) {
|
||||||
|
std::ifstream file1, file2;
|
||||||
|
file1.open(file1Path);
|
||||||
|
if (!file1.is_open()) {
|
||||||
|
std::cout << file1Path << " could not be opened!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
file2.open(file2Path);
|
||||||
|
if (!file2.is_open()) {
|
||||||
|
std::cout << file2Path << " could not be opened!" << std::endl;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string file1contents = readFile(file1);
|
||||||
|
std::string file2contents = readFile(file2);
|
||||||
|
|
||||||
|
// std::cout << "file1: " << file1contents << std::endl;
|
||||||
|
// std::cout << "file2: " << file2contents << std::endl;
|
||||||
|
// std::cout << "comp: " << file1contents.compare(file2contents) << std::endl;
|
||||||
|
return file1contents.compare(file2contents) == 0;
|
||||||
|
}
|
||||||
79
src/Type.cpp
79
src/Type.cpp
@@ -4,49 +4,68 @@ Type::Type() {
|
|||||||
indirection = 0;
|
indirection = 0;
|
||||||
baseType = none;
|
baseType = none;
|
||||||
typeDefinition = NULL;
|
typeDefinition = NULL;
|
||||||
}
|
templateDefinition = NULL;
|
||||||
|
|
||||||
Type::Type(ValueType typeIn) {
|
|
||||||
indirection = 0;
|
|
||||||
baseType = typeIn;
|
|
||||||
typeDefinition = NULL;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Type(ValueType typeIn, int indirectionIn) {
|
Type::Type(ValueType typeIn, int indirectionIn) {
|
||||||
indirection = indirectionIn;
|
indirection = indirectionIn;
|
||||||
baseType = typeIn;
|
baseType = typeIn;
|
||||||
typeDefinition = NULL;
|
typeDefinition = NULL;
|
||||||
|
templateDefinition = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Type(NodeTree<ASTData>* typeDefinitionIn) {
|
Type::Type(ValueType typeIn, std::set<std::string> traitsIn) {
|
||||||
indirection = 0;
|
indirection = 0;
|
||||||
baseType = none;
|
baseType = typeIn;
|
||||||
typeDefinition = typeDefinitionIn;
|
traits = traitsIn;
|
||||||
|
typeDefinition = NULL;
|
||||||
|
templateDefinition = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn) {
|
Type::Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn) {
|
||||||
indirection = indirectionIn;
|
indirection = indirectionIn;
|
||||||
baseType = none;
|
baseType = none;
|
||||||
typeDefinition = typeDefinitionIn;
|
typeDefinition = typeDefinitionIn;
|
||||||
|
templateDefinition = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn) {
|
Type::Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn) {
|
||||||
|
indirection = 0;
|
||||||
|
baseType = none;
|
||||||
|
typeDefinition = typeDefinitionIn;
|
||||||
|
traits = traitsIn;
|
||||||
|
templateDefinition = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
Type::Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn, std::set<std::string> traitsIn) {
|
||||||
baseType = typeIn;
|
baseType = typeIn;
|
||||||
indirection = indirectionIn;
|
indirection = indirectionIn;
|
||||||
typeDefinition = typeDefinitionIn;
|
typeDefinition = typeDefinitionIn;
|
||||||
|
traits = traitsIn;
|
||||||
|
templateDefinition = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type::Type(ValueType typeIn, NodeTree<Symbol>* templateDefinitionIn, std::set<std::string> traitsIn) {
|
||||||
|
indirection = 0;
|
||||||
|
baseType = typeIn;
|
||||||
|
typeDefinition = NULL;
|
||||||
|
templateDefinition = templateDefinitionIn;
|
||||||
|
traits = traitsIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
Type::~Type() {
|
Type::~Type() {
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool Type::operator==(const Type &other) const {
|
const bool Type::operator==(const Type &other) const {
|
||||||
return( baseType == other.baseType && indirection == other.indirection && typeDefinition == other.typeDefinition);
|
return( baseType == other.baseType && indirection == other.indirection && typeDefinition == other.typeDefinition && templateDefinition == other.templateDefinition && other.traits == traits);
|
||||||
}
|
}
|
||||||
|
|
||||||
const bool Type::operator!=(const Type &other) const {
|
const bool Type::operator!=(const Type &other) const {
|
||||||
return(!this->operator==(other));
|
return(!this->operator==(other));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string Type::toString() {
|
std::string Type::toString(bool showTraits) {
|
||||||
std::string typeString;
|
std::string typeString;
|
||||||
switch (baseType) {
|
switch (baseType) {
|
||||||
case none:
|
case none:
|
||||||
@@ -55,6 +74,12 @@ std::string Type::toString() {
|
|||||||
else
|
else
|
||||||
typeString = "none";
|
typeString = "none";
|
||||||
break;
|
break;
|
||||||
|
case template_type:
|
||||||
|
typeString = "template: " + templateDefinition->getDataRef()->toString();
|
||||||
|
break;
|
||||||
|
case template_type_type:
|
||||||
|
typeString = "template_type_type";
|
||||||
|
break;
|
||||||
case void_type:
|
case void_type:
|
||||||
typeString = "void";
|
typeString = "void";
|
||||||
break;
|
break;
|
||||||
@@ -81,5 +106,35 @@ std::string Type::toString() {
|
|||||||
}
|
}
|
||||||
for (int i = 0; i < indirection; i++)
|
for (int i = 0; i < indirection; i++)
|
||||||
typeString += "*";
|
typeString += "*";
|
||||||
|
if (traits.size() && showTraits) {
|
||||||
|
typeString += "[ ";
|
||||||
|
for (auto i : traits)
|
||||||
|
typeString += i + " ";
|
||||||
|
typeString += "]";
|
||||||
|
}
|
||||||
|
//std::cout << "Extra components of " << typeString << " are " << indirection << " " << typeDefinition << " " << templateDefinition << std::endl;
|
||||||
return typeString;
|
return typeString;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Type* Type::clone() {
|
||||||
|
return new Type(baseType, typeDefinition, indirection, traits);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Type::getIndirection() {
|
||||||
|
return indirection;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Type::setIndirection(int indirectionIn) {
|
||||||
|
indirection = indirectionIn;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Type::increaseIndirection() {
|
||||||
|
setIndirection(indirection+1);
|
||||||
|
}
|
||||||
|
void Type::decreaseIndirection() {
|
||||||
|
setIndirection(indirection-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Type::modifyIndirection(int mod) {
|
||||||
|
setIndirection(indirection + mod);
|
||||||
|
}
|
||||||
|
|||||||
@@ -71,4 +71,13 @@ std::string join(const std::vector<std::string> &strVec, std::string joinStr) {
|
|||||||
return joinedStr;
|
return joinedStr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string readFile(std::istream &file) {
|
||||||
|
std::string line, contents;
|
||||||
|
while(file.good()) {
|
||||||
|
getline(file, line);
|
||||||
|
contents.append(line+"\n");
|
||||||
|
}
|
||||||
|
return contents;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
59
stdlib/io.krak
Normal file
59
stdlib/io.krak
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
__if_comp__ __C__ __simple_passthrough__ """
|
||||||
|
#include <stdio.h>
|
||||||
|
"""
|
||||||
|
|
||||||
|
|void| println() {
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|void| print(|char*| toPrint) {
|
||||||
|
__if_comp__ __C__ {
|
||||||
|
__simple_passthrough__ """
|
||||||
|
printf(toPrint);
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|void| println(|char*| toPrint) {
|
||||||
|
print(toPrint);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
|
|void| print(|int| toPrint) {
|
||||||
|
__if_comp__ __C__ {
|
||||||
|
__simple_passthrough__ """
|
||||||
|
printf("%d", toPrint);
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|void| println(|int| toPrint) {
|
||||||
|
print(toPrint);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
|
|void| print(|float| toPrint) {
|
||||||
|
__if_comp__ __C__ {
|
||||||
|
__simple_passthrough__ """
|
||||||
|
printf("%f", toPrint);
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|void| print(|double| toPrint) {
|
||||||
|
__if_comp__ __C__ {
|
||||||
|
__simple_passthrough__ """
|
||||||
|
printf("%f", toPrint);
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|void| println(|float| toPrint) {
|
||||||
|
print(toPrint);
|
||||||
|
println();
|
||||||
|
}
|
||||||
|
|
||||||
9
stdlib/math.krak
Normal file
9
stdlib/math.krak
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
|int| NotPi = 3;
|
||||||
|
|float| Pi = 3.141592654;
|
||||||
|
|
||||||
|
|int| fibanacci(|int| num) {
|
||||||
|
if (num < 2)
|
||||||
|
return 1;
|
||||||
|
return fibanacci(num-1) + fibanacci(num-2);
|
||||||
|
}
|
||||||
64
stdlib/mem.krak
Normal file
64
stdlib/mem.krak
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
__if_comp__ __C__ __simple_passthrough__ """
|
||||||
|
#include <stdlib.h>
|
||||||
|
"""
|
||||||
|
|
||||||
|
/* we have a template versions so we don't have to cast (because we don't have that yet) */
|
||||||
|
|
||||||
|
template <T> |T*| malloc(|int| size) {
|
||||||
|
|T*| memPtr = 0;
|
||||||
|
__if_comp__ __C__ {
|
||||||
|
__simple_passthrough__ """
|
||||||
|
memPtr = malloc(size);
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
return memPtr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <T> |void| free(|T*| memPtr) {
|
||||||
|
__if_comp__ __C__ {
|
||||||
|
__simple_passthrough__ """
|
||||||
|
free(memPtr);
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <T> |int| sizeof() {
|
||||||
|
|int| result = 0;
|
||||||
|
|T| testObj;
|
||||||
|
__if_comp__ __C__ {
|
||||||
|
__simple_passthrough__ """
|
||||||
|
result = sizeof(testObj);
|
||||||
|
"""
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <T> |T*| new(|int| count) {
|
||||||
|
return malloc<T>( sizeof<T>() * count );
|
||||||
|
}
|
||||||
|
|
||||||
|
template <T> |T*| new() {
|
||||||
|
return new<T>(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We specilize on the trait Destructable to decide on whether or not the destructor should be called */
|
||||||
|
template <T> |void| delete(|T*| toDelete, |int| itemCount) {
|
||||||
|
delete<T>(toDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Calling this with itemCount = 0 allows you to delete destructable objects without calling their destructors. */
|
||||||
|
template <T(Destructable)> |void| delete(|T*| toDelete, |int| itemCount) {
|
||||||
|
for (|int| i = 0; i < itemCount; i++;)
|
||||||
|
toDelete[i].destruct();
|
||||||
|
delete<T>(toDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* We specilize on the trait Destructable to decide on whether or not the destructor should be called */
|
||||||
|
template <T> |void| delete(|T*| toDelete) {
|
||||||
|
free(toDelete);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <T(Destructable)> |void| delete(|T*| toDelete) {
|
||||||
|
toDelete->destruct();
|
||||||
|
free(toDelete);
|
||||||
|
}
|
||||||
9
stdlib/trivial_container.krak
Normal file
9
stdlib/trivial_container.krak
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
typedef template <T> trivialContainer {
|
||||||
|
|T| data;
|
||||||
|
|void| print() {
|
||||||
|
print(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
12
stdlib/util.krak
Normal file
12
stdlib/util.krak
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
|
||||||
|
template<T> |T| greater(|T| a, |T| b) {
|
||||||
|
if (a > b)
|
||||||
|
return a;
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<T> |T| lesser(|T| a, |T| b) {
|
||||||
|
if (a > b)
|
||||||
|
return b;
|
||||||
|
return a;
|
||||||
|
}
|
||||||
55
stdlib/vector.krak
Normal file
55
stdlib/vector.krak
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
import mem;
|
||||||
|
import util;
|
||||||
|
import io;
|
||||||
|
|
||||||
|
typedef template<T> vector (Destructable) {
|
||||||
|
|T*| data;
|
||||||
|
|int| size;
|
||||||
|
|int| available;
|
||||||
|
|
||||||
|
|vector<T>*| construct() {
|
||||||
|
size = 0;
|
||||||
|
available = 8;
|
||||||
|
data = new<T>(8);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
|void| destruct() {
|
||||||
|
delete<T>(data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|bool| resize(|int| newSize) {
|
||||||
|
|T*| newData = new<T>(newSize);
|
||||||
|
if (!newData)
|
||||||
|
return false;
|
||||||
|
for (|int| i = 0; i < lesser<int>(size, newSize); i++;)
|
||||||
|
newData[i] = data[i];
|
||||||
|
delete<T>(data, 0);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|T| at(|int| index) {
|
||||||
|
return get(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
|T| get(|int| index) {
|
||||||
|
if (index < 0 || index >= size) {
|
||||||
|
println("Vector access out of bounds! Retuning 0th element as sanest option");
|
||||||
|
return data[0];
|
||||||
|
}
|
||||||
|
return data[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
|void| set(|int| index, |T| dataIn) {
|
||||||
|
if (index < 0 || index >= size)
|
||||||
|
return;
|
||||||
|
data[index] = dataIn;
|
||||||
|
}
|
||||||
|
|void| addEnd(|T| dataIn) {
|
||||||
|
if (size < available)
|
||||||
|
size++;
|
||||||
|
else
|
||||||
|
resize(size*2);
|
||||||
|
data[size-1] = dataIn;
|
||||||
|
}
|
||||||
|
};
|
||||||
5
tests/OperatorOverloadTest.expected_results
Normal file
5
tests/OperatorOverloadTest.expected_results
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
3 9
|
||||||
|
6 18
|
||||||
|
Subtraction
|
||||||
|
3 9
|
||||||
|
-97 -61
|
||||||
64
tests/OperatorOverloadTest.krak
Normal file
64
tests/OperatorOverloadTest.krak
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
typedef Vec2 {
|
||||||
|
|int| x;
|
||||||
|
|int| y;
|
||||||
|
|
||||||
|
|void| print() {
|
||||||
|
print(x);
|
||||||
|
print(" ");
|
||||||
|
print(y);
|
||||||
|
}
|
||||||
|
|
||||||
|
|Vec2| add(|Vec2| other) {
|
||||||
|
|Vec2| toReturn;
|
||||||
|
toReturn.x = x + other.x;
|
||||||
|
toReturn.y = y + other.y;
|
||||||
|
print();
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|Vec2| subtract(|Vec2| other) {
|
||||||
|
|Vec2| toReturn;
|
||||||
|
toReturn.x = x - other.x;
|
||||||
|
toReturn.y = y - other.y;
|
||||||
|
print();
|
||||||
|
return toReturn;
|
||||||
|
}
|
||||||
|
|
||||||
|
|Vec2| operator+(|Vec2| other) {
|
||||||
|
return add(other);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
|Vec2| operator-(|Vec2| lhs, |Vec2| rhs) {
|
||||||
|
return lhs.subtract(rhs);
|
||||||
|
}
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|Vec2| vector1;
|
||||||
|
|Vec2| vector2;
|
||||||
|
vector1.x = 3;
|
||||||
|
vector1.y = 9;
|
||||||
|
vector2 = vector1;
|
||||||
|
/* NOTE COMMENT
|
||||||
|
|Vec2| vector3;
|
||||||
|
vector3.x = vector1.x + vector2.x;
|
||||||
|
vector3.y = vector1.y + vector2.y;
|
||||||
|
vector2.print();
|
||||||
|
*/
|
||||||
|
|Vec2| addition = vector1 + vector2;
|
||||||
|
print("\n");
|
||||||
|
addition.print();
|
||||||
|
print("\nSubtraction\n");
|
||||||
|
vector2.x = 100;
|
||||||
|
vector2.y = 70;
|
||||||
|
|Vec2| subtraction = vector1 - vector2;
|
||||||
|
print("\n");
|
||||||
|
print(subtraction.x); print(" "); print(subtraction.y);
|
||||||
|
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
tests/RecursiveTest.expected_results
Normal file
1
tests/RecursiveTest.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
5
|
||||||
14
tests/RecursiveTest.krak
Normal file
14
tests/RecursiveTest.krak
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
|int| fibanacci(|int| num) {
|
||||||
|
if (num < 2)
|
||||||
|
return 1;
|
||||||
|
return fibanacci(num-1) + fibanacci(num-2);
|
||||||
|
}
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
print(fibanacci(4));
|
||||||
|
print("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
1
tests/commentFirstTest.expected_results
Normal file
1
tests/commentFirstTest.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1337
|
||||||
7
tests/commentFirstTest.krak
Normal file
7
tests/commentFirstTest.krak
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
/* Comment first! */
|
||||||
|
import io;
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
println(1337);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
3
tests/declarationsTest.expected_results
Normal file
3
tests/declarationsTest.expected_results
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
4
|
||||||
|
8
|
||||||
|
11
|
||||||
26
tests/declarationsTest.krak
Normal file
26
tests/declarationsTest.krak
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
import io;
|
||||||
|
import mem;
|
||||||
|
|
||||||
|
typedef ClassWithConstructor {
|
||||||
|
|int| data;
|
||||||
|
|ClassWithConstructor*| construct(|int| inData) {
|
||||||
|
data = inData;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|void| printData() {
|
||||||
|
println(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|ClassWithConstructor| object.construct(4);
|
||||||
|
//ClassWithConstructor object;
|
||||||
|
//object.construct(4);
|
||||||
|
object.printData();
|
||||||
|
|int| a = 8;
|
||||||
|
println(a);
|
||||||
|
|ClassWithConstructor*| objPtr = new<ClassWithConstructor>()->construct(11);
|
||||||
|
objPtr->printData();
|
||||||
|
delete<ClassWithConstructor>(objPtr);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
tests/destructorTest.expected_results
Normal file
1
tests/destructorTest.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
Hello Destructors!
|
||||||
28
tests/destructorTest.krak
Normal file
28
tests/destructorTest.krak
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
typedef DestructorPrint {
|
||||||
|
|char*| myStr;
|
||||||
|
|DestructorPrint*| construct(|char*| str) {
|
||||||
|
myStr = str;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|void| destruct() {
|
||||||
|
println(myStr);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef NoDistruction {
|
||||||
|
|int| a;
|
||||||
|
|void| dummyFunc() {}
|
||||||
|
};
|
||||||
|
|
||||||
|
|void| indirPrint() {
|
||||||
|
|DestructorPrint| testObj.construct("Hello Destructors!");
|
||||||
|
|NoDistruction| dummy;
|
||||||
|
}
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
indirPrint();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
1
tests/emptyBracesFunction.expected_results
Normal file
1
tests/emptyBracesFunction.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
It was nothing
|
||||||
9
tests/emptyBracesFunction.krak
Normal file
9
tests/emptyBracesFunction.krak
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
|void| nothing() {}
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
nothing();
|
||||||
|
println("It was nothing");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
tests/functionMultipleTemplateTest.expected_results
Normal file
1
tests/functionMultipleTemplateTest.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
22.141590
|
||||||
13
tests/functionMultipleTemplateTest.krak
Normal file
13
tests/functionMultipleTemplateTest.krak
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
template <T,J> |void| addAndPrint(|T| a, |J| b) {
|
||||||
|
print(a+b);
|
||||||
|
}
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|
||||||
|
addAndPrint<int,double>(10,12.14159);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
tests/functionOrderingTest.expected_results
Normal file
1
tests/functionOrderingTest.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
12
|
||||||
17
tests/functionOrderingTest.krak
Normal file
17
tests/functionOrderingTest.krak
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
|int| ret1() {
|
||||||
|
return ret2() / 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
print(ret1());
|
||||||
|
print(ret2());
|
||||||
|
print("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|int| ret2() {
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
1
tests/functionTemplateTest.expected_results
Normal file
1
tests/functionTemplateTest.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
22
|
||||||
13
tests/functionTemplateTest.krak
Normal file
13
tests/functionTemplateTest.krak
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
template <T> |T| addAndPrint(|T| a, |T| b) {
|
||||||
|
print(a+b);
|
||||||
|
return a+b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
addAndPrint<int>(10,12);
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
3
tests/memTest.expected_results
Normal file
3
tests/memTest.expected_results
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
11
|
||||||
|
Hello decent memory! Quite a nice feeling
|
||||||
|
|
||||||
27
tests/memTest.krak
Normal file
27
tests/memTest.krak
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import mem;
|
||||||
|
import io;
|
||||||
|
|
||||||
|
typedef AnObject {
|
||||||
|
|int| a;
|
||||||
|
|int| b;
|
||||||
|
|char*| c;
|
||||||
|
|
||||||
|
|void| print() {
|
||||||
|
print(a+b);
|
||||||
|
print("\n");
|
||||||
|
print(c);
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|AnObject*| ptr = new<AnObject>();
|
||||||
|
ptr->a = 4;
|
||||||
|
ptr->b = 7;
|
||||||
|
ptr->c = "Hello decent memory! Quite a nice feeling\n";
|
||||||
|
ptr->print();
|
||||||
|
delete<AnObject>(ptr);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
2
tests/moreComplexObjectTest.expected_results
Normal file
2
tests/moreComplexObjectTest.expected_results
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
742
|
||||||
|
1337
|
||||||
29
tests/moreComplexObjectTest.krak
Normal file
29
tests/moreComplexObjectTest.krak
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
typedef firstObject {
|
||||||
|
|int| objectNum;
|
||||||
|
|int| other;
|
||||||
|
|void| print() {
|
||||||
|
print(other);
|
||||||
|
}
|
||||||
|
|void| printInd() {
|
||||||
|
print();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef Int int;
|
||||||
|
|
||||||
|
|Int| aliasNum;
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|firstObject| wooObject;
|
||||||
|
wooObject.objectNum = 7;
|
||||||
|
print(wooObject.objectNum);
|
||||||
|
|firstObject*| objPtr = &wooObject;
|
||||||
|
objPtr->objectNum = 42;
|
||||||
|
print(objPtr->objectNum);
|
||||||
|
print("\n");
|
||||||
|
objPtr->other = 1337;
|
||||||
|
objPtr->printInd();
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
1
tests/moreObjectTemplateTest.expected_results
Normal file
1
tests/moreObjectTemplateTest.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
45Hello!Hello!Hello!
|
||||||
37
tests/moreObjectTemplateTest.krak
Normal file
37
tests/moreObjectTemplateTest.krak
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import io;
|
||||||
|
import trivial_container;
|
||||||
|
|
||||||
|
typedef RegularObject {
|
||||||
|
|int| num;
|
||||||
|
|trivialContainer<char*>| innerContainer;
|
||||||
|
|void| set(|char*| message, |int| number) {
|
||||||
|
innerContainer.data = message;
|
||||||
|
num = number;
|
||||||
|
}
|
||||||
|
|char*| get() {
|
||||||
|
return innerContainer.data;
|
||||||
|
}
|
||||||
|
|void| print() {
|
||||||
|
print(num);
|
||||||
|
innerContainer.print();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef MyIntContainer trivialContainer<int>;
|
||||||
|
|MyIntContainer| roundabout;
|
||||||
|
|RegularObject| outsideDec;
|
||||||
|
|
||||||
|
|void| print(|trivialContainer<char*>| toPrint) {
|
||||||
|
print(toPrint.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
roundabout.data = 4;
|
||||||
|
outsideDec.set("Hello!", 5);
|
||||||
|
roundabout.print();
|
||||||
|
outsideDec.print();
|
||||||
|
print(outsideDec.get());
|
||||||
|
print(outsideDec.innerContainer);
|
||||||
|
print("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
tests/objectOrderingTest.expected_results
Normal file
1
tests/objectOrderingTest.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
12
|
||||||
27
tests/objectOrderingTest.krak
Normal file
27
tests/objectOrderingTest.krak
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
typedef objectA {
|
||||||
|
|int| a;
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef BigObject {
|
||||||
|
|objectA| a;
|
||||||
|
|objectB| b;
|
||||||
|
|int| add() {
|
||||||
|
return a.a + b.b;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef objectB {
|
||||||
|
|int| b;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|BigObject| c;
|
||||||
|
c.a.a = 4;
|
||||||
|
c.b.b = 8;
|
||||||
|
print(c.add());
|
||||||
|
print("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
14
tests/runTests.sh
Executable file
14
tests/runTests.sh
Executable file
@@ -0,0 +1,14 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
krakenPath="../build/kraken"
|
||||||
|
testDir=${1:-"../tests"}
|
||||||
|
ext=${2:-"krak"}
|
||||||
|
|
||||||
|
fileList=""
|
||||||
|
for dir in `find ${testDir} -type f -name "*.${ext}"`; do
|
||||||
|
filename=$(basename ${dir})
|
||||||
|
filename="${filename%.*}"
|
||||||
|
fileList+=\ $testDir\/$filename
|
||||||
|
done
|
||||||
|
|
||||||
|
${krakenPath} "--test" ${fileList}
|
||||||
1
tests/simpleFunctionTest.expected_results
Normal file
1
tests/simpleFunctionTest.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
1919
|
||||||
14
tests/simpleFunctionTest.krak
Normal file
14
tests/simpleFunctionTest.krak
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
|int| addAndPrintInt(|int| a, |int| b) {
|
||||||
|
print(a+b);
|
||||||
|
return a+b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|
||||||
|
print(addAndPrintInt(7,12));
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
4
tests/simpleObjectMultipleTemplateTest.expected_results
Normal file
4
tests/simpleObjectMultipleTemplateTest.expected_results
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
a: 24
|
||||||
|
b: Hello World
|
||||||
|
a: Pi incoming
|
||||||
|
b: 3.14159 - Fooled you! txt pi. C is being weird with floats. Not a Kraken problem. Ahh Well.
|
||||||
30
tests/simpleObjectMultipleTemplateTest.krak
Normal file
30
tests/simpleObjectMultipleTemplateTest.krak
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
|
||||||
|
typedef template <T,J> TemplateTest {
|
||||||
|
|T| a;
|
||||||
|
|J| b;
|
||||||
|
|void| print() {
|
||||||
|
print("a: ");
|
||||||
|
print(a);
|
||||||
|
print("\n");
|
||||||
|
print("b: ");
|
||||||
|
print(b);
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|
||||||
|
|TemplateTest<int, char*>| test;
|
||||||
|
|TemplateTest<char*, char*>| test2;
|
||||||
|
test.a = 24;
|
||||||
|
test.b = "Hello World";
|
||||||
|
test2.a = "Pi incoming";
|
||||||
|
test2.b = "3.14159 - Fooled you! txt pi. C is being weird with floats. Not a Kraken problem. Ahh Well.";
|
||||||
|
|
||||||
|
test.print();
|
||||||
|
test2.print();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
4
tests/simpleObjectTemplateTest.expected_results
Normal file
4
tests/simpleObjectTemplateTest.expected_results
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
a: 5
|
||||||
|
b: 7
|
||||||
|
a: 9
|
||||||
|
b: Hello Templates!
|
||||||
30
tests/simpleObjectTemplateTest.krak
Normal file
30
tests/simpleObjectTemplateTest.krak
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
|
||||||
|
typedef template <T> TemplateTest {
|
||||||
|
|int| a;
|
||||||
|
|T| b;
|
||||||
|
|void| print() {
|
||||||
|
print("a: ");
|
||||||
|
print(a);
|
||||||
|
print("\n");
|
||||||
|
print("b: ");
|
||||||
|
print(b);
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|
||||||
|
|TemplateTest<int>| test;
|
||||||
|
|TemplateTest<char*>| test2;
|
||||||
|
test.a = 5;
|
||||||
|
test.b = 7;
|
||||||
|
test2.a = 9;
|
||||||
|
test2.b = "Hello Templates!";
|
||||||
|
|
||||||
|
test.print();
|
||||||
|
test2.print();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
tests/simpleObjectTest.expected_results
Normal file
1
tests/simpleObjectTest.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
57
|
||||||
18
tests/simpleObjectTest.krak
Normal file
18
tests/simpleObjectTest.krak
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
|
||||||
|
import io;
|
||||||
|
|
||||||
|
typedef FirstObject {
|
||||||
|
|int| objectNum;
|
||||||
|
|void| PrintSelf(|int| a) {
|
||||||
|
print(objectNum);
|
||||||
|
print(a);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|FirstObject| wooObject;
|
||||||
|
wooObject.objectNum = 5;
|
||||||
|
wooObject.PrintSelf(7);
|
||||||
|
print("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
8
tests/templateTest.expected_results
Normal file
8
tests/templateTest.expected_results
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
a: 5
|
||||||
|
b: 7
|
||||||
|
1337
|
||||||
|
a: 9
|
||||||
|
b: Hello Templates!
|
||||||
|
Woooo nesting!
|
||||||
|
From another file! Whoh!
|
||||||
|
1919
|
||||||
52
tests/templateTest.krak
Normal file
52
tests/templateTest.krak
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import io;
|
||||||
|
import trivial_container;
|
||||||
|
|
||||||
|
typedef template <T> TemplateTest {
|
||||||
|
|int| a;
|
||||||
|
|T| b;
|
||||||
|
|trivialContainer<T>| c;
|
||||||
|
|void| print() {
|
||||||
|
print("a: ");
|
||||||
|
print(a);
|
||||||
|
print("\n");
|
||||||
|
print("b: ");
|
||||||
|
print(b);
|
||||||
|
print("\n");
|
||||||
|
c.print();
|
||||||
|
print("\n");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef MyInt int;
|
||||||
|
|
||||||
|
|MyInt| c;
|
||||||
|
|
||||||
|
|
||||||
|
template <T> |T| addAndPrint(|T| a, |T| b) {
|
||||||
|
print(a+b);
|
||||||
|
return a+b;
|
||||||
|
}
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|TemplateTest<int>| test;
|
||||||
|
|TemplateTest<char*>| test2;
|
||||||
|
test.a = 5;
|
||||||
|
test.b = 7;
|
||||||
|
test.c.data = 1337;
|
||||||
|
test2.a = 9;
|
||||||
|
test2.b = "Hello Templates!";
|
||||||
|
test2.c.data = "Woooo nesting!";
|
||||||
|
|
||||||
|
test.print();
|
||||||
|
test2.print();
|
||||||
|
|
||||||
|
|trivialContainer<char*>| testImport;
|
||||||
|
testImport.data = "From another file! Whoh!";
|
||||||
|
testImport.print();
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
print(addAndPrint<int>(7,12));
|
||||||
|
print("\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
1
tests/testArrayNotation.expected_results
Normal file
1
tests/testArrayNotation.expected_results
Normal file
@@ -0,0 +1 @@
|
|||||||
|
777
|
||||||
13
tests/testArrayNotation.krak
Normal file
13
tests/testArrayNotation.krak
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
import io;
|
||||||
|
import mem;
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|int| b;
|
||||||
|
|int*| a = &b;
|
||||||
|
a [ 0 ] = 7;
|
||||||
|
print(a [ 0 ] );
|
||||||
|
print(*a);
|
||||||
|
print(b);
|
||||||
|
print("\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
9
tests/traitsTest.expected_results
Normal file
9
tests/traitsTest.expected_results
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
No Traits
|
||||||
|
First Trait
|
||||||
|
Second Trait
|
||||||
|
Both Traits
|
||||||
|
|
||||||
|
First Trait
|
||||||
|
Second Trait
|
||||||
|
Both Traits
|
||||||
|
No Traits
|
||||||
75
tests/traitsTest.krak
Normal file
75
tests/traitsTest.krak
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
typedef NoTraits {};
|
||||||
|
|
||||||
|
typedef Trait1 (FirstTrait) {};
|
||||||
|
typedef Trait2 (SecondTrait) {};
|
||||||
|
typedef TwoTrait (FirstTrait, SecondTrait) {};
|
||||||
|
typedef AlreadySpecilized (FirstTrait, SecondTrait) {};
|
||||||
|
|
||||||
|
template <T> |void| OneTwoFunc(|T| obj) {
|
||||||
|
println("No Traits");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <T(FirstTrait)> |void| OneTwoFunc(|T| obj) {
|
||||||
|
println("First Trait");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <T(SecondTrait)> |void| OneTwoFunc(|T| obj) {
|
||||||
|
println("Second Trait");
|
||||||
|
}
|
||||||
|
|
||||||
|
template <T(FirstTrait, SecondTrait)> |void| OneTwoFunc(|T| obj) {
|
||||||
|
println("Both Traits");
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
template <AlreadySpecilized> |void| OneTwoFunc(|AlreadySpecilized| obj) {
|
||||||
|
println("Already Specilized");
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//This should work for objects too!
|
||||||
|
//To test, we cycle the mapping of traits
|
||||||
|
|
||||||
|
typedef template<T> OneTwoObj (FirstTrait) {};
|
||||||
|
typedef template<T(FirstTrait)> OneTwoObj (SecondTrait) {};
|
||||||
|
typedef template<T(SecondTrait)> OneTwoObj (FirstTrait, SecondTrait) {};
|
||||||
|
typedef template<T(FirstTrait, SecondTrait)> OneTwoObj {};
|
||||||
|
/*
|
||||||
|
*typedef template<AlreadySpecilized> OneTwoObj {
|
||||||
|
* void proveSpecilized() {
|
||||||
|
* println("I'm specilized!");
|
||||||
|
* }
|
||||||
|
*};
|
||||||
|
*/
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|NoTraits| a;
|
||||||
|
|Trait1| b;
|
||||||
|
|Trait2| c;
|
||||||
|
|TwoTrait| d;
|
||||||
|
|AlreadySpecilized| e;
|
||||||
|
|
||||||
|
OneTwoFunc<NoTraits>(a);
|
||||||
|
OneTwoFunc<Trait1>(b);
|
||||||
|
OneTwoFunc<Trait2>(c);
|
||||||
|
OneTwoFunc<TwoTrait>(d);
|
||||||
|
// OneTwoFunc<AlreadySpecilized>(e);
|
||||||
|
|
||||||
|
println();
|
||||||
|
|
||||||
|
|OneTwoObj<NoTraits>| alpha;
|
||||||
|
|OneTwoObj<Trait1>| beta;
|
||||||
|
|OneTwoObj<Trait2>| gamma;
|
||||||
|
|OneTwoObj<TwoTrait>| delta;
|
||||||
|
// |OneTwoObj<AlreadySpecilized>| epsilon;
|
||||||
|
|
||||||
|
OneTwoFunc<OneTwoObj<NoTraits>>(alpha);
|
||||||
|
OneTwoFunc<OneTwoObj<Trait1>>(beta);
|
||||||
|
OneTwoFunc<OneTwoObj<Trait2>>(gamma);
|
||||||
|
OneTwoFunc<OneTwoObj<TwoTrait>>(delta);
|
||||||
|
|
||||||
|
//We can't pass along our inner part, so let's just make sure that it is the right object.
|
||||||
|
//epsilon.proveSpecilized();
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
2
tests/typeExpr.expected_results
Normal file
2
tests/typeExpr.expected_results
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
4
|
||||||
|
8
|
||||||
20
tests/typeExpr.krak
Normal file
20
tests/typeExpr.krak
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import io;
|
||||||
|
|
||||||
|
typedef ClassWithConstructor {
|
||||||
|
|int| data;
|
||||||
|
|ClassWithConstructor*| construct(|int| inData) {
|
||||||
|
data = inData;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|void| printData() {
|
||||||
|
println(data);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|ClassWithConstructor| object.construct(4);
|
||||||
|
object.printData();
|
||||||
|
|int| a = 8;
|
||||||
|
println(a);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
2
tests/vectorTest.expected_results
Normal file
2
tests/vectorTest.expected_results
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
1337
|
||||||
|
Destroyed!
|
||||||
28
tests/vectorTest.krak
Normal file
28
tests/vectorTest.krak
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import io;
|
||||||
|
import mem;
|
||||||
|
import vector;
|
||||||
|
|
||||||
|
typedef AbleToBeDestroyed (Destructable) {
|
||||||
|
|void| destruct() {
|
||||||
|
println("Destroyed!");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|int| main() {
|
||||||
|
|vector<int>| intVec.construct();
|
||||||
|
intVec.addEnd(1);
|
||||||
|
intVec.addEnd(3);
|
||||||
|
intVec.addEnd(3);
|
||||||
|
intVec.addEnd(7);
|
||||||
|
for (|int| i = 0; i < intVec.size; i++;)
|
||||||
|
print(intVec.at(i));
|
||||||
|
|
||||||
|
println();
|
||||||
|
|
||||||
|
|vector<AbleToBeDestroyed>*| desVec = new<vector<AbleToBeDestroyed>>()->construct();
|
||||||
|
|AbleToBeDestroyed| testDestruct;
|
||||||
|
desVec->addEnd(testDestruct);
|
||||||
|
delete<vector<AbleToBeDestroyed>>(desVec);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
This is the true regex for triple quoted strings, but it segfaults my regex code....
|
|
||||||
|
|
||||||
triple_quoted_string = "\"\"\"((\"\"(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'|
|
|
||||||
|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|Z|X|C|V|B|N|M|<|>|\?| )+)|(\"(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'|
|
|
||||||
|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|Z|X|C|V|B|N|M|<|>|\?| )+))*(`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'|
|
|
||||||
|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|Z|X|C|V|B|N|M|<|>|\?| )*(((`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'|
|
|
||||||
|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|Z|X|C|V|B|N|M|<|>|\?| )+\")|((`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'|
|
|
||||||
|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|Z|X|C|V|B|N|M|<|>|\?| )+\"\")|((`|1|2|3|4|5|6|7|8|9|0|-|=| |q|w|e|r|t|y|u|i|o|p|[|]|\\|a|s|d|f|g|h|j|k|l|;|'|
|
|
||||||
|z|x|c|v|b|n|m|,|.|/|~|!|@|#|$|%|^|&|\*|\(|\)|_|\+|Q|W|E|R|T|Y|U|I|O|P|{|}|\||A|S|D|F|G|H|J|K|L|:|Z|X|C|V|B|N|M|<|>|\?| )+))*\"\"\"" ;
|
|
||||||
Reference in New Issue
Block a user