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)
|
||||
|
||||
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11")
|
||||
|
||||
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} )
|
||||
|
||||
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 <map>
|
||||
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
#include "Type.h"
|
||||
#include "ASTData.h"
|
||||
#include "NodeTransformation.h"
|
||||
@@ -15,17 +18,46 @@ class ASTTransformation: public NodeTransformation<Symbol,ASTData> {
|
||||
public:
|
||||
ASTTransformation(Importer* importerIn);
|
||||
~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);
|
||||
NodeTree<ASTData>* transform(NodeTree<Symbol>* from, NodeTree<ASTData>* scope, std::vector<Type> types = std::vector<Type>());
|
||||
std::vector<NodeTree<ASTData>*> transformChildren(std::vector<NodeTree<Symbol>*> children, std::set<int> skipChildren, NodeTree<ASTData>* scope, std::vector<Type> types);
|
||||
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::map<std::string, Type*> templateTypeReplacements);
|
||||
std::vector<Type> mapNodesToTypes(std::vector<NodeTree<ASTData>*> nodes);
|
||||
std::string concatSymbolTree(NodeTree<Symbol>* root);
|
||||
NodeTree<ASTData>* scopeLookup(NodeTree<ASTData>* scope, std::string lookup, std::vector<NodeTree<ASTData>*> nodes);
|
||||
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>* doFunction(NodeTree<ASTData>* scope, std::string lookup, std::vector<NodeTree<ASTData>*> nodes, std::map<std::string, Type*> templateTypeReplacements);
|
||||
|
||||
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:
|
||||
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
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "Type.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "Poset.h"
|
||||
|
||||
|
||||
class CGenerator {
|
||||
@@ -17,12 +18,14 @@ class CGenerator {
|
||||
CGenerator();
|
||||
~CGenerator();
|
||||
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 generateAliasChains(NodeTree<ASTData>* scopeNode, NodeTree<ASTData>* definition);
|
||||
static std::string ValueTypeToCType(Type *type);
|
||||
static std::string ValueTypeToCTypeDecoration(Type *type);
|
||||
static std::string CifyFunctionName(std::string name);
|
||||
std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from);
|
||||
|
||||
static std::string CifyName(std::string name);
|
||||
std::string generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype);
|
||||
NodeTree<ASTData>* getMethodsObjectType(NodeTree<ASTData>* scope, std::string functionName);
|
||||
std::string generatorString;
|
||||
private:
|
||||
std::string tabs();
|
||||
|
||||
@@ -27,6 +27,7 @@ class GraphStructuredStack {
|
||||
void addEdge(NodeTree<int>* start, NodeTree<int>* end, NodeTree<Symbol>* edge);
|
||||
void clear();
|
||||
|
||||
std::vector<int> getFrontier(int frontier);
|
||||
std::string toString();
|
||||
private:
|
||||
std::vector<std::vector<NodeTree<int>*>*> gss;
|
||||
|
||||
@@ -14,13 +14,27 @@
|
||||
#include "CollapseTransformation.h"
|
||||
#include "ASTTransformation.h"
|
||||
|
||||
class ASTTransformation;
|
||||
|
||||
class Importer {
|
||||
public:
|
||||
Importer(Parser* parserIn);
|
||||
Importer(Parser* parserIn, std::vector<std::string> includePaths);
|
||||
~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();
|
||||
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;
|
||||
std::vector<Symbol> removeSymbols;
|
||||
std::vector<Symbol> collapseSymbols;
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
|
||||
class ParseAction {
|
||||
public:
|
||||
enum ActionType { INVALID, REDUCE, SHIFT, ACCEPT, REJECT };
|
||||
@@ -18,10 +19,11 @@ class ParseAction {
|
||||
ParseAction(ActionType action, ParseRule* reduceRule);
|
||||
ParseAction(ActionType action, int shiftState);
|
||||
~ParseAction();
|
||||
bool const equalsExceptLookahead(const ParseAction &other);
|
||||
bool const operator==(const ParseAction &other);
|
||||
bool const operator!=(const ParseAction &other);
|
||||
std::string toString();
|
||||
bool const equalsExceptLookahead(const ParseAction &other) const;
|
||||
bool const operator==(const ParseAction &other) const;
|
||||
bool const operator!=(const ParseAction &other) const;
|
||||
bool const operator<(const ParseAction &other) const;
|
||||
std::string toString(bool printRuleLookahead = true);
|
||||
static std::string actionToString(ActionType action);
|
||||
|
||||
ActionType action;
|
||||
|
||||
@@ -16,10 +16,10 @@ class ParseRule {
|
||||
ParseRule();
|
||||
ParseRule(Symbol leftHandle, int pointerIndex, std::vector<Symbol> &rightSide, std::vector<Symbol>* lookahead);
|
||||
~ParseRule();
|
||||
const bool equalsExceptLookahead(const ParseRule &other);
|
||||
bool const operator==(const ParseRule &other);
|
||||
bool const operator!=(const ParseRule &other);
|
||||
|
||||
const bool equalsExceptLookahead(const ParseRule &other) const;
|
||||
bool const operator==(const ParseRule &other) const;
|
||||
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();
|
||||
|
||||
void setLeftHandle(Symbol leftHandle);
|
||||
@@ -40,7 +40,7 @@ class ParseRule {
|
||||
void addLookahead(std::vector<Symbol>* lookahead);
|
||||
std::vector<Symbol>* getLookahead();
|
||||
|
||||
std::string toString();
|
||||
std::string toString(bool printLookahead = true);
|
||||
std::string toDOT();
|
||||
|
||||
private:
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
#include "Table.h"
|
||||
|
||||
#include <queue>
|
||||
#include <set>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
@@ -36,8 +37,13 @@ class Parser {
|
||||
void importTable(char* tableData);
|
||||
|
||||
protected:
|
||||
std::vector<Symbol>* firstSet(Symbol token);
|
||||
std::vector<Symbol>* firstSet(Symbol token, std::vector<Symbol> avoidList);
|
||||
std::vector<Symbol> firstSet(Symbol token, std::vector<Symbol> avoidList = std::vector<Symbol>(), bool addNewTokens = true);
|
||||
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);
|
||||
virtual void closure(State* state);
|
||||
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 <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <utility>
|
||||
#include <algorithm>
|
||||
#include "Parser.h"
|
||||
#include "Symbol.h"
|
||||
@@ -16,6 +18,7 @@ class RNGLRParser: public Parser {
|
||||
RNGLRParser();
|
||||
~RNGLRParser();
|
||||
NodeTree<Symbol>* parseInput(std::string inputString);
|
||||
void printReconstructedFrontier(int frontier);
|
||||
|
||||
private:
|
||||
void reducer(int i);
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
#include <fstream>
|
||||
|
||||
#include <string>
|
||||
#include <utility>
|
||||
|
||||
#include "util.h"
|
||||
#include "ParseRule.h"
|
||||
#include "ParseAction.h"
|
||||
@@ -20,7 +23,8 @@ class Table {
|
||||
void remove(int stateNum, Symbol tranSymbol);
|
||||
std::vector<ParseAction*>* get(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:
|
||||
std::vector< std::vector< std::vector<ParseAction*>* >* > table;
|
||||
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 <iostream>
|
||||
#include <set>
|
||||
|
||||
//Circular dependency
|
||||
class ASTData;
|
||||
#include "ASTData.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 {
|
||||
public:
|
||||
Type();
|
||||
Type(ValueType typeIn, int indirectionIn);
|
||||
Type(ValueType typeIn);
|
||||
Type(NodeTree<ASTData>* typeDefinitionIn);
|
||||
Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn);
|
||||
Type(ValueType typeIn, NodeTree<ASTData>* typeDefinitionIn, int indirectionIn);
|
||||
Type(ValueType typeIn, int indirectionIn = 0);
|
||||
Type(ValueType typeIn, std::set<std::string> traitsIn); //Mostly for template type type's
|
||||
Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn = 0);
|
||||
Type(NodeTree<ASTData>* typeDefinitionIn, std::set<std::string> traitsIn);
|
||||
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();
|
||||
bool const operator==(const Type &other)const;
|
||||
bool const operator!=(const Type &other)const;
|
||||
std::string toString();
|
||||
ValueType baseType;
|
||||
Type* clone();
|
||||
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<Symbol>* templateDefinition;
|
||||
std::map<std::string, Type*> templateTypeReplacement;
|
||||
std::set<std::string> traits;
|
||||
private:
|
||||
int indirection;
|
||||
private:
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -9,6 +9,9 @@
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
|
||||
std::string intToString(int theInt);
|
||||
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);
|
||||
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 readFile(std::istream &file);
|
||||
|
||||
|
||||
template <typename T>
|
||||
bool contains(std::vector<T> vec, T item) {
|
||||
for (auto i : vec)
|
||||
@@ -25,15 +31,32 @@ bool contains(std::vector<T> vec, T item) {
|
||||
}
|
||||
|
||||
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;
|
||||
if (begin < 0)
|
||||
begin += vec.size()+1;
|
||||
if (end < 0)
|
||||
end += vec.size()+1;
|
||||
for (int i = begin; i < end; i++)
|
||||
for (int i = begin; i < end; i += step)
|
||||
toReturn.push_back(vec[i]);
|
||||
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
|
||||
|
||||
@@ -2,10 +2,19 @@ Goal = translation_unit ;
|
||||
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 ";" ;
|
||||
|
||||
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 ";" ;
|
||||
|
||||
|
||||
interpreter_directive = "#!" WS path | ;
|
||||
path = path path_part | path_part ;
|
||||
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 ;
|
||||
|
||||
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 ;
|
||||
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 | ;
|
||||
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 | ;
|
||||
parameter_list = parameter_list WS "," WS parameter | parameter ;
|
||||
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 "}" ;
|
||||
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 ;
|
||||
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 "}" ;
|
||||
|
||||
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 ;
|
||||
|
||||
@@ -54,7 +72,7 @@ for_loop = "for" WS "\(" WS statement WS boolean_expression WS ";" WS statement
|
||||
|
||||
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 = 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 ;
|
||||
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 = "==" | "<=" | ">=" | "!=" | "<" | ">" ;
|
||||
|
||||
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 ;
|
||||
term = term WS forward_slash WS factor | term WS "\*" WS factor | term WS "%" WS factor | factor ;
|
||||
factor = "\+\+" WS unarad | unarad WS "\+\+" | "--" WS unarad | unarad WS "--" | "\+" WS unarad | "-" WS unarad | "!" WS unarad | "~" WS unarad | "\(" WS type WS "\)" WS unarad | "\*" WS unarad | "&" WS unarad | unarad ;
|
||||
unarad = number | identifier | function_call | bool | string | character | "\(" WS boolean_expression WS "\)" | access_operation ;
|
||||
number = integer | float | double ;
|
||||
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 | floating_literal ;
|
||||
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 ;
|
||||
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 ;
|
||||
hexadecimal = "0x(1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)+" ;
|
||||
sign = "\+|-" WS | ;
|
||||
integer = sign numeric | sign hexadecimal | "null" ;
|
||||
float = sign numeric "." numeric "f" ;
|
||||
double = sign numeric "." numeric | sign numeric "." numeric "d" ;
|
||||
integer = sign numeric | sign hexadecimal ;
|
||||
floating_literal = sign numeric "." numeric | sign numeric "." numeric alpha ;
|
||||
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|;|'|
|
||||
|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 "ASTData.h"
|
||||
#include "CGenerator.h"
|
||||
#include "Poset.h"
|
||||
|
||||
#include "util.h"
|
||||
#include "Tester.h"
|
||||
|
||||
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();
|
||||
RegEx::test();
|
||||
Lexer::test();
|
||||
//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;
|
||||
}
|
||||
|
||||
std::string krakenDir = argv[0];
|
||||
krakenDir = strSlice(krakenDir, 0, -(std::string("kraken").length()+1));
|
||||
includePaths.push_back(krakenDir + "stdlib/"); //Add the stdlib directory that exists in the same directory as the kraken executable to the path
|
||||
std::string programName = argv[1];
|
||||
std::string grammerFileString = argv[2];
|
||||
std::string outputName = argv[3];
|
||||
|
||||
std::ifstream grammerInFile, compiledGrammerInFile;
|
||||
std::ofstream /*outFileC,*/ compiledGrammerOutFile;
|
||||
std::ofstream compiledGrammerOutFile;
|
||||
|
||||
grammerInFile.open(grammerFileString);
|
||||
if (!grammerInFile.is_open()) {
|
||||
@@ -40,17 +72,9 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
|
||||
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";
|
||||
//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
|
||||
std::string grammerInputFileString;
|
||||
std::string line;
|
||||
@@ -63,8 +87,6 @@ int main(int argc, char* argv[]) {
|
||||
//LALRParser parser;
|
||||
RNGLRParser parser;
|
||||
parser.loadGrammer(grammerInputFileString);
|
||||
//std::cout << "Creating State Set from Main" << std::endl;
|
||||
//std::cout << "\nState Set" << std::endl;
|
||||
|
||||
//Start binary stuff
|
||||
bool compGramGood = false;
|
||||
@@ -88,7 +110,6 @@ int main(int argc, char* argv[]) {
|
||||
} else {
|
||||
compGramGood = true;
|
||||
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
|
||||
}
|
||||
} else {
|
||||
@@ -118,40 +139,23 @@ int main(int argc, char* argv[]) {
|
||||
}
|
||||
//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;
|
||||
|
||||
Importer importer(&parser);
|
||||
Importer importer(&parser, includePaths);
|
||||
|
||||
for (auto i : includePaths)
|
||||
std::cout << i << std::endl;
|
||||
|
||||
/*NodeTree<ASTData>* AST =*/
|
||||
importer.import(programName);
|
||||
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
|
||||
|
||||
//Code generation
|
||||
//For right now, just C
|
||||
|
||||
CGenerator().generateCompSet(ASTs, outputName);
|
||||
/*
|
||||
std::string c_code = CGenerator().generate(AST);
|
||||
outFileC << c_code << std::endl;
|
||||
outFileC.close();
|
||||
*/
|
||||
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;
|
||||
outputCFile.open(i->first + ".c");
|
||||
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 {
|
||||
std::cout << "Cannot open file " << i->first << ".c" << std::endl;
|
||||
}
|
||||
@@ -35,59 +36,163 @@ std::string CGenerator::tabs() {
|
||||
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
|
||||
std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enclosingObject) {
|
||||
ASTData data = from->getData();
|
||||
std::vector<NodeTree<ASTData>*> children = from->getChildren();
|
||||
std::string output = "";
|
||||
std::string output;
|
||||
switch (data.type) {
|
||||
case translation_unit:
|
||||
//Do here because we may need the typedefs before the declarations of variables
|
||||
for (int i = 0; i < children.size(); i++)
|
||||
if (children[i]->getDataRef()->type == type_def)
|
||||
output += generate(children[i], enclosingObject) + "\n";
|
||||
{
|
||||
// Ok, so we've got to do this in passes to preserve mututally recursive definitions.
|
||||
//
|
||||
// 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)
|
||||
for (auto i = data.scope.begin(); i != data.scope.end(); i++) {
|
||||
for (auto overloadedMembers : i->second) {
|
||||
NodeTree<ASTData>* declaration = overloadedMembers;
|
||||
for (auto declaration : i->second) {
|
||||
std::vector<NodeTree<ASTData>*> decChildren = declaration->getChildren();
|
||||
ASTData declarationData = declaration->getData();
|
||||
switch(declarationData.type) {
|
||||
case identifier:
|
||||
output += ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*identifier*/\n";
|
||||
variableDeclarations += ValueTypeToCType(declarationData.valueType) + " " + declarationData.symbol.getName() + "; /*identifier*/\n";
|
||||
break;
|
||||
case function:
|
||||
{
|
||||
if (decChildren.size() == 0) { //Not a real function, must be a built in passthrough {
|
||||
output += "/* built in function: " + declarationData.toString() + " */\n";
|
||||
break;
|
||||
if (declarationData.valueType->baseType == template_type)
|
||||
functionPrototypes += "/* template function " + declarationData.symbol.toString() + " */\n";
|
||||
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;
|
||||
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:
|
||||
//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";
|
||||
}
|
||||
}
|
||||
}
|
||||
//Do here because we need the newlines
|
||||
for (int i = 0; i < children.size(); i++)
|
||||
if (children[i]->getDataRef()->type != type_def)
|
||||
output += generate(children[i], enclosingObject) + "\n";
|
||||
output += plainTypedefs + variableDeclarations + classStructs + functionPrototypes + functionDefinitions;
|
||||
return output;
|
||||
}
|
||||
break;
|
||||
case interpreter_directive:
|
||||
//Do nothing
|
||||
@@ -97,33 +202,22 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
||||
//return "#include <" + data.symbol.getName() + ">\n";
|
||||
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;
|
||||
if (enclosingObject && enclosingObject->getDataRef()->scope.find(data.symbol.getName()) != enclosingObject->getDataRef()->scope.end())
|
||||
preName += "self->";
|
||||
if (false)
|
||||
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
|
||||
preName += "this->";
|
||||
return preName + CifyName(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:
|
||||
{
|
||||
if (data.valueType->baseType == template_type)
|
||||
return "/* template function: " + data.symbol.getName() + " */";
|
||||
output += "\n" + ValueTypeToCType(data.valueType) + " ";
|
||||
std::string nameDecoration, parameters;
|
||||
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);
|
||||
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;
|
||||
}
|
||||
case code_block:
|
||||
{
|
||||
output += "{\n";
|
||||
tabLevel++;
|
||||
std::string destructorString = "";
|
||||
tabLevel++;
|
||||
for (int i = 0; i < children.size(); i++) {
|
||||
//std::cout << "Line " << i << std::endl;
|
||||
std::string line = generate(children[i], enclosingObject);
|
||||
//std::cout << line << std::endl;
|
||||
output += line;
|
||||
}
|
||||
tabLevel--;
|
||||
if (children[i]->getChildren().size() && children[i]->getChildren()[0]->getDataRef()->type == declaration_statement) {
|
||||
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() + "}";
|
||||
return output;
|
||||
case expression:
|
||||
}
|
||||
case expression:
|
||||
output += " " + data.symbol.getName() + ", ";
|
||||
case boolean_expression:
|
||||
output += " " + data.symbol.getName() + " ";
|
||||
@@ -175,7 +286,12 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
||||
case declaration_statement:
|
||||
if (children.size() == 1)
|
||||
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) + ";";
|
||||
case if_comp:
|
||||
if (generate(children[0], enclosingObject) == generatorString)
|
||||
@@ -198,11 +314,13 @@ std::string CGenerator::generate(NodeTree<ASTData>* from, NodeTree<ASTData>* enc
|
||||
if (funcType == function) {
|
||||
if (name == "++" || name == "--")
|
||||
return generate(children[1], enclosingObject) + name;
|
||||
if (name == "*" && children.size() == 2) //Is dereference, not multiplication
|
||||
return "*(" + generate(children[1], enclosingObject) + ")";
|
||||
if ( (name == "*" || name == "&" || name == "!" ) && children.size() == 2) //Is dereference, not multiplication, address-of, or other unary operator
|
||||
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 == "!="
|
||||
|| name == "<" || name == ">" || name == "%" || name == "+=" || name == "-=" || name == "*=" || name == "/=" || name == "||"
|
||||
|| name == "&&" || name == "!" )
|
||||
|| name == "&&")
|
||||
return "((" + generate(children[1], enclosingObject) + ")" + name + "(" + generate(children[2], enclosingObject) + "))";
|
||||
else if (name == "." || name == "->") {
|
||||
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();
|
||||
NodeTree<ASTData>* possibleObjectType = children[1]->getDataRef()->valueType->typeDefinition;
|
||||
//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()) {
|
||||
std::string nameDecoration;
|
||||
std::vector<NodeTree<ASTData>*> functionDefChildren = children[2]->getChildren(); //The function def is the rhs of the access operation
|
||||
std::cout << "Decorating (in access-should be object) " << name << " " << functionDefChildren.size() << std::endl;
|
||||
for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++)
|
||||
nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType);
|
||||
/*HERE*/ return possibleObjectType->getDataRef()->symbol.getName() +"__" + CifyFunctionName(functionName) + nameDecoration + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject) + ",";
|
||||
//The comma lets the upper function call know we already started the param list
|
||||
//Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses
|
||||
} else {
|
||||
std::cout << "Is not in scope or not type" << std::endl;
|
||||
return "((" + generate(children[1], enclosingObject) + ")" + name + functionName + ")";
|
||||
if (possibleObjectType) {
|
||||
NodeTree<ASTData>* unaliasedTypeDef = getMethodsObjectType(possibleObjectType, functionName);
|
||||
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::string nameDecoration;
|
||||
std::vector<NodeTree<ASTData>*> functionDefChildren = children[2]->getChildren(); //The function def is the rhs of the access operation
|
||||
std::cout << "Decorating (in access-should be object) " << name << " " << functionDefChildren.size() << std::endl;
|
||||
for (int i = 0; i < (functionDefChildren.size() > 0 ? functionDefChildren.size()-1 : 0); i++)
|
||||
nameDecoration += "_" + ValueTypeToCTypeDecoration(functionDefChildren[i]->getData().valueType);
|
||||
/*HERE*/ return CifyName(unaliasedTypeDef->getDataRef()->symbol.getName()) +"__" + CifyName(functionName + nameDecoration) + "(" + (name == "." ? "&" : "") + generate(children[1], enclosingObject) + ",";
|
||||
//The comma lets the upper function call know we already started the param list
|
||||
//Note that we got here from a function call. We just pass up this special case and let them finish with the perentheses
|
||||
} 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 {
|
||||
//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
|
||||
bool isSelfObjectMethod = enclosingObject && contains(enclosingObject->getChildren(), children[0]);
|
||||
if (isSelfObjectMethod)
|
||||
output += enclosingObject->getDataRef()->symbol.getName() +"__";
|
||||
/*HERE*/ output += CifyFunctionName(name) + nameDecoration + "(";
|
||||
output += CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__";
|
||||
/*HERE*/ output += CifyName(name + nameDecoration) + "(";
|
||||
if (isSelfObjectMethod)
|
||||
output += children.size() > 1 ? "self," : "self";
|
||||
output += children.size() > 1 ? "this," : "this";
|
||||
}
|
||||
} else {
|
||||
//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;
|
||||
}
|
||||
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) {
|
||||
std::string output;
|
||||
// Returns the function prototype in the out param and the full definition normally
|
||||
std::string CGenerator::generateObjectMethod(NodeTree<ASTData>* enclosingObject, NodeTree<ASTData>* from, std::string *functionPrototype) {
|
||||
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
|
||||
enclosingObjectType.indirection++;
|
||||
enclosingObjectType.increaseIndirection();
|
||||
std::vector<NodeTree<ASTData>*> children = from->getChildren();
|
||||
std::string nameDecoration, parameters;
|
||||
for (int i = 0; i < children.size()-1; i++) {
|
||||
parameters += ", " + ValueTypeToCType(children[i]->getData().valueType) + " " + generate(children[i]);
|
||||
nameDecoration += "_" + ValueTypeToCTypeDecoration(children[i]->getData().valueType);
|
||||
}
|
||||
output += "\n" + ValueTypeToCType(data.valueType) + " " + enclosingObject->getDataRef()->symbol.getName() +"__"
|
||||
+ CifyFunctionName(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
|
||||
return output;
|
||||
std::string functionSignature = "\n" + ValueTypeToCType(data.valueType) + " " + CifyName(enclosingObject->getDataRef()->symbol.getName()) +"__"
|
||||
+ CifyName(data.symbol.getName()) + nameDecoration + "(" + ValueTypeToCType(&enclosingObjectType)
|
||||
+ " this" + parameters + ")";
|
||||
*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) {
|
||||
@@ -295,7 +426,7 @@ std::string CGenerator::ValueTypeToCType(Type *type) {
|
||||
switch (type->baseType) {
|
||||
case none:
|
||||
if (type->typeDefinition)
|
||||
return_type = type->typeDefinition->getDataRef()->symbol.getName();
|
||||
return_type = CifyName(type->typeDefinition->getDataRef()->symbol.getName());
|
||||
else
|
||||
return_type = "none";
|
||||
break;
|
||||
@@ -321,7 +452,7 @@ std::string CGenerator::ValueTypeToCType(Type *type) {
|
||||
return_type = "unknown_ValueType";
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < type->indirection; i++)
|
||||
for (int i = 0; i < type->getIndirection(); i++)
|
||||
return_type += "*";
|
||||
return return_type;
|
||||
}
|
||||
@@ -331,7 +462,7 @@ std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) {
|
||||
switch (type->baseType) {
|
||||
case none:
|
||||
if (type->typeDefinition)
|
||||
return_type = type->typeDefinition->getDataRef()->symbol.getName();
|
||||
return_type = CifyName(type->typeDefinition->getDataRef()->symbol.getName());
|
||||
else
|
||||
return_type = "none";
|
||||
break;
|
||||
@@ -357,12 +488,12 @@ std::string CGenerator::ValueTypeToCTypeDecoration(Type *type) {
|
||||
return_type = "unknown_ValueType";
|
||||
break;
|
||||
}
|
||||
for (int i = 0; i < type->indirection; i++)
|
||||
for (int i = 0; i < type->getIndirection(); i++)
|
||||
return_type += "_P__";
|
||||
return return_type;
|
||||
}
|
||||
|
||||
std::string CGenerator::CifyFunctionName(std::string name) {
|
||||
std::string CGenerator::CifyName(std::string name) {
|
||||
std::string operatorsToReplace[] = { "+", "plus",
|
||||
"-", "minus",
|
||||
"*", "star",
|
||||
@@ -392,7 +523,14 @@ std::string CGenerator::CifyFunctionName(std::string name) {
|
||||
"|=", "pipeequals",
|
||||
"*=", "starequals",
|
||||
"<<=", "doublerightequals",
|
||||
"<", "lessthan",
|
||||
">", "greaterthan",
|
||||
">>=", "doubleleftequals",
|
||||
"(", "openparen",
|
||||
")", "closeparen",
|
||||
"[", "openbracket",
|
||||
"]", "closebracket",
|
||||
" ", "space",
|
||||
"->", "arrow" };
|
||||
int length = sizeof(operatorsToReplace)/sizeof(std::string);
|
||||
//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;
|
||||
}
|
||||
|
||||
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 tostring = "";
|
||||
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"
|
||||
|
||||
Importer::Importer(Parser* parserIn) {
|
||||
Importer::Importer(Parser* parserIn, std::vector<std::string> includePaths) {
|
||||
//constructor
|
||||
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("\\(", 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("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("if", true));
|
||||
removeSymbols.push_back(Symbol("while", true));
|
||||
removeSymbols.push_back(Symbol("__if_comp__", true));
|
||||
removeSymbols.push_back(Symbol("comp_simple_passthrough", 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_parameter_list", false));
|
||||
@@ -31,23 +36,102 @@ Importer::Importer(Parser* parserIn) {
|
||||
collapseSymbols.push_back(Symbol("unorderd_list_part", false));
|
||||
collapseSymbols.push_back(Symbol("if_comp_pred", 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() {
|
||||
//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
|
||||
if (imported.find(fileName) != imported.end())
|
||||
if (imported.find(fileName) != imported.end()) {
|
||||
std::cout << "Already Imported!" << std::endl;
|
||||
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::ofstream outFile, outFileTransformed, outFileAST;
|
||||
std::ofstream outFile, outFileTransformed;
|
||||
|
||||
|
||||
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()) {
|
||||
std::cout << "Problem opening programInFile " << fileName << "\n";
|
||||
return NULL;
|
||||
@@ -65,12 +149,6 @@ NodeTree<ASTData>* Importer::import(std::string fileName) {
|
||||
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;
|
||||
while(programInFile.good()) {
|
||||
getline(programInFile, line);
|
||||
@@ -85,8 +163,10 @@ NodeTree<ASTData>* Importer::import(std::string fileName) {
|
||||
//std::cout << parseTree->DOTGraphString() << std::endl;
|
||||
outFile << parseTree->DOTGraphString() << std::endl;
|
||||
} 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();
|
||||
|
||||
//Remove Transformations
|
||||
@@ -106,19 +186,7 @@ NodeTree<ASTData>* Importer::import(std::string fileName) {
|
||||
}
|
||||
outFileTransformed.close();
|
||||
|
||||
//Call with ourself to allow the transformation to call us to import files that it needs
|
||||
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;
|
||||
return parseTree;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
const bool ParseAction::operator!=(const ParseAction &other) {
|
||||
const bool ParseAction::operator!=(const ParseAction &other) const {
|
||||
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) {
|
||||
switch (action) {
|
||||
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 = "";
|
||||
outputString += actionToString(action);
|
||||
if (reduceRule != NULL)
|
||||
outputString += " " + reduceRule->toString();
|
||||
outputString += " " + reduceRule->toString(printRuleLookahead);
|
||||
if (shiftState != -1)
|
||||
outputString += " " + intToString(shiftState);
|
||||
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);
|
||||
}
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
const bool ParseRule::operator!=(const ParseRule &other) {
|
||||
const bool ParseRule::operator!=(const ParseRule &other) const {
|
||||
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() {
|
||||
std::vector<Symbol>* newLookahead = NULL;
|
||||
if (lookahead) {
|
||||
@@ -111,7 +127,7 @@ std::vector<Symbol>* ParseRule::getLookahead() {
|
||||
return lookahead;
|
||||
}
|
||||
|
||||
std::string ParseRule::toString() {
|
||||
std::string ParseRule::toString(bool printLookahead) {
|
||||
std::string concat = leftHandle.toString() + " -> ";
|
||||
for (int i = 0; i < rightSide.size(); i++) {
|
||||
if (i == pointerIndex)
|
||||
@@ -120,7 +136,7 @@ std::string ParseRule::toString() {
|
||||
}
|
||||
if (pointerIndex >= rightSide.size())
|
||||
concat += "(*)";
|
||||
if (lookahead != NULL) {
|
||||
if (printLookahead && lookahead != NULL) {
|
||||
concat += "**";
|
||||
for (std::vector<Symbol>::size_type i = 0; i < lookahead->size(); i++)
|
||||
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) {
|
||||
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 != "") {
|
||||
//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();
|
||||
Symbol leftSide = getOrAddSymbol(currToken, false); //Left handle is never a terminal
|
||||
currentRule->setLeftHandle(leftSide);
|
||||
@@ -76,7 +88,7 @@ void Parser::loadGrammer(std::string grammerInputString) {
|
||||
|
||||
loadedGrammer.push_back(currentRule);
|
||||
//Get next token
|
||||
currToken = reader.word();
|
||||
currToken = reader.word(false);
|
||||
}
|
||||
//std::cout << "Parsed!\n";
|
||||
|
||||
@@ -117,59 +129,86 @@ int Parser::stateNum(State* state) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::vector<Symbol>* Parser::firstSet(Symbol token) {
|
||||
std::vector<Symbol> avoidList;
|
||||
return firstSet(token, avoidList);
|
||||
}
|
||||
|
||||
std::vector<Symbol>* Parser::firstSet(Symbol token, std::vector<Symbol> avoidList) {
|
||||
//If we've already done this token, don't do it again
|
||||
std::vector<Symbol> Parser::firstSet(Symbol token, std::vector<Symbol> avoidList, bool addNewTokens) {
|
||||
if (tokenFirstSet.find(token) != tokenFirstSet.end())
|
||||
return tokenFirstSet[token];
|
||||
//If we've already done this token, don't do it again
|
||||
for (std::vector<Symbol>::size_type i = 0; i < avoidList.size(); i++)
|
||||
if (avoidList[i] == token) {
|
||||
return new std::vector<Symbol>();
|
||||
}
|
||||
if (avoidList[i] == token)
|
||||
return std::vector<Symbol>();
|
||||
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.
|
||||
if (token.isTerminal()) {
|
||||
first->push_back(token);
|
||||
first.push_back(token);
|
||||
return(first);
|
||||
}
|
||||
//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.
|
||||
//If that one includes mull, do the next one too (if it exists).
|
||||
Symbol rightToken;
|
||||
std::vector<Symbol>* recursiveFirstSet = NULL;
|
||||
std::vector<Symbol> recursiveFirstSet;
|
||||
for (std::vector<ParseRule*>::size_type i = 0; i < loadedGrammer.size(); i++) {
|
||||
if (token == loadedGrammer[i]->getLeftSide()) {
|
||||
//Loop through the rule adding first sets for each token if the previous token contained NULL
|
||||
bool recFirstSetHasNull = false;
|
||||
int j = 0;
|
||||
do {
|
||||
rightToken = loadedGrammer[i]->getRightSide()[j]; //Get token of the right side of this rule
|
||||
if (rightToken.isTerminal()) {
|
||||
recursiveFirstSet = new std::vector<Symbol>();
|
||||
recursiveFirstSet->push_back(rightToken);
|
||||
recursiveFirstSet.push_back(rightToken);
|
||||
} else {
|
||||
//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());
|
||||
//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;
|
||||
first.insert(first.end(), recursiveFirstSet.begin(), recursiveFirstSet.end());
|
||||
j++;
|
||||
} while (recFirstSetHasNull && loadedGrammer[i]->getRightSide().size() > j);
|
||||
} while (isNullable(rightToken) && loadedGrammer[i]->getRightSide().size() > j);
|
||||
}
|
||||
}
|
||||
if (addNewTokens)
|
||||
tokenFirstSet[token] = 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.
|
||||
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)
|
||||
@@ -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
|
||||
std::vector<Symbol>* followSet = new std::vector<Symbol>();
|
||||
std::vector<Symbol>* symbolFirstSet;
|
||||
std::vector<Symbol> symbolFirstSet;
|
||||
bool symbolFirstSetHasNull = true;
|
||||
while (symbolFirstSetHasNull && !rule->isAtEnd()) {
|
||||
symbolFirstSetHasNull = false;
|
||||
symbolFirstSet = firstSet(rule->getAtNextIndex());
|
||||
for (std::vector<Symbol>::size_type i = 0; i < symbolFirstSet->size(); i++) {
|
||||
if ((*symbolFirstSet)[i] == nullSymbol) {
|
||||
for (std::vector<Symbol>::size_type i = 0; i < symbolFirstSet.size(); i++) {
|
||||
if (symbolFirstSet[i] == nullSymbol) {
|
||||
symbolFirstSetHasNull = true;
|
||||
symbolFirstSet->erase(symbolFirstSet->begin()+i);
|
||||
symbolFirstSet.erase(symbolFirstSet.begin()+i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
followSet->insert(followSet->end(), symbolFirstSet->begin(), symbolFirstSet->end());
|
||||
delete symbolFirstSet;
|
||||
followSet->insert(followSet->end(), symbolFirstSet.begin(), symbolFirstSet.end());
|
||||
rule->advancePointer();
|
||||
}
|
||||
if (rule->isAtEnd()) {
|
||||
symbolFirstSet = rule->getLookahead();
|
||||
followSet->insert(followSet->end(), symbolFirstSet->begin(), symbolFirstSet->end());
|
||||
symbolFirstSet = *(rule->getLookahead());
|
||||
followSet->insert(followSet->end(), symbolFirstSet.begin(), symbolFirstSet.end());
|
||||
}
|
||||
std::vector<Symbol>* followSetReturn = new std::vector<Symbol>();
|
||||
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) {
|
||||
input.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)) {
|
||||
Reduction newReduction = {v0, firstActions[i]->reduceRule->getLeftSide(), 0, getNullableParts(firstActions[i]->reduceRule), NULL};
|
||||
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 << "Problem is on line: " << findLine(i) << 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++)
|
||||
if (j == i)
|
||||
std::cout << "||*||*||" << input[j].toString() << "||*||*|| ";
|
||||
else
|
||||
std::cout << input[j].toString() << " ";
|
||||
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
|
||||
|
||||
@@ -353,6 +353,17 @@ ParseAction* Table::getShift(int state, Symbol token) {
|
||||
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 concat = "";
|
||||
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;
|
||||
baseType = none;
|
||||
typeDefinition = NULL;
|
||||
}
|
||||
|
||||
Type::Type(ValueType typeIn) {
|
||||
indirection = 0;
|
||||
baseType = typeIn;
|
||||
typeDefinition = NULL;
|
||||
templateDefinition = NULL;
|
||||
}
|
||||
|
||||
Type::Type(ValueType typeIn, int indirectionIn) {
|
||||
indirection = indirectionIn;
|
||||
baseType = typeIn;
|
||||
typeDefinition = NULL;
|
||||
templateDefinition = NULL;
|
||||
}
|
||||
|
||||
Type::Type(NodeTree<ASTData>* typeDefinitionIn) {
|
||||
Type::Type(ValueType typeIn, std::set<std::string> traitsIn) {
|
||||
indirection = 0;
|
||||
baseType = none;
|
||||
typeDefinition = typeDefinitionIn;
|
||||
baseType = typeIn;
|
||||
traits = traitsIn;
|
||||
typeDefinition = NULL;
|
||||
templateDefinition = NULL;
|
||||
}
|
||||
|
||||
Type::Type(NodeTree<ASTData>* typeDefinitionIn, int indirectionIn) {
|
||||
indirection = indirectionIn;
|
||||
baseType = none;
|
||||
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;
|
||||
indirection = indirectionIn;
|
||||
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() {
|
||||
}
|
||||
|
||||
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 {
|
||||
return(!this->operator==(other));
|
||||
}
|
||||
|
||||
std::string Type::toString() {
|
||||
std::string Type::toString(bool showTraits) {
|
||||
std::string typeString;
|
||||
switch (baseType) {
|
||||
case none:
|
||||
@@ -55,6 +74,12 @@ std::string Type::toString() {
|
||||
else
|
||||
typeString = "none";
|
||||
break;
|
||||
case template_type:
|
||||
typeString = "template: " + templateDefinition->getDataRef()->toString();
|
||||
break;
|
||||
case template_type_type:
|
||||
typeString = "template_type_type";
|
||||
break;
|
||||
case void_type:
|
||||
typeString = "void";
|
||||
break;
|
||||
@@ -81,5 +106,35 @@ std::string Type::toString() {
|
||||
}
|
||||
for (int i = 0; i < indirection; i++)
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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