Ver código fonte

changes towards the same style as the Java version

Kajetan Johannes Hammerle 5 anos atrás
pai
commit
3ec6b417c0
100 arquivos alterados com 2430 adições e 1818 exclusões
  1. 3 1
      .gitignore
  2. 0 29
      Exception.cpp
  3. 0 21
      Exception.h
  4. 0 44
      File.cpp
  5. 0 22
      File.h
  6. 2 25
      Main.cpp
  7. 35 5
      Makefile
  8. 0 22
      Utils.cpp
  9. 0 10
      Utils.h
  10. 0 31
      code/BoolData.cpp
  11. 0 20
      code/BoolData.h
  12. 0 55
      code/Data.cpp
  13. 0 33
      code/Data.h
  14. 0 25
      code/FloatData.cpp
  15. 0 21
      code/FloatData.h
  16. 0 1
      code/Function.c
  17. 0 18
      code/Function.h
  18. 0 15
      code/Instruction.cpp
  19. 0 22
      code/Instruction.h
  20. 0 34
      code/Script.cpp
  21. 0 27
      code/Script.h
  22. 0 93
      compiler/Compiler.cpp
  23. 0 27
      compiler/Compiler.h
  24. 0 83
      compiler/Token.cpp
  25. 0 35
      compiler/Token.h
  26. 0 43
      compiler/TokenList.cpp
  27. 0 24
      compiler/TokenList.h
  28. 0 101
      compiler/TokenType.cpp
  29. 0 100
      compiler/TokenType.h
  30. 0 262
      compiler/Tokenizer.cpp
  31. 0 31
      compiler/Tokenizer.h
  32. 0 107
      data/ArrayList.h
  33. 0 340
      data/HashMap.h
  34. 0 91
      data/Stack.h
  35. 22 0
      snuviscript/code/ISnuviLogger.h
  36. 14 0
      snuviscript/code/Script.cpp
  37. 15 0
      snuviscript/code/Script.h
  38. 11 0
      snuviscript/exceptions/PreScriptException.cpp
  39. 22 0
      snuviscript/exceptions/PreScriptException.h
  40. 159 0
      snuviscript/test/Test.cpp
  41. 26 0
      snuviscript/test/Test.h
  42. 72 0
      snuviscript/test/TestLogger.cpp
  43. 32 0
      snuviscript/test/TestLogger.h
  44. 28 0
      snuviscript/tokenizer/DoubleToken.cpp
  45. 20 0
      snuviscript/tokenizer/DoubleToken.h
  46. 19 0
      snuviscript/tokenizer/StringToken.cpp
  47. 20 0
      snuviscript/tokenizer/StringToken.h
  48. 46 0
      snuviscript/tokenizer/Token.cpp
  49. 26 0
      snuviscript/tokenizer/Token.h
  50. 137 0
      snuviscript/tokenizer/TokenType.cpp
  51. 46 0
      snuviscript/tokenizer/TokenType.h
  52. 349 0
      snuviscript/tokenizer/Tokenizer.cpp
  53. 48 0
      snuviscript/tokenizer/Tokenizer.h
  54. 10 0
      test/arrays/array_dim1
  55. 37 0
      test/arrays/array_dim1.cout
  56. 3 0
      test/arrays/array_dim1.out
  57. 59 0
      test/arrays/array_dim1.tout
  58. 15 0
      test/arrays/array_dim2
  59. 72 0
      test/arrays/array_dim2.cout
  60. 6 0
      test/arrays/array_dim2.out
  61. 111 0
      test/arrays/array_dim2.tout
  62. 21 0
      test/arrays/array_dim3
  63. 111 0
      test/arrays/array_dim3.cout
  64. 24 0
      test/arrays/array_dim3.out
  65. 169 0
      test/arrays/array_dim3.tout
  66. 8 0
      test/basic/gosub
  67. 10 0
      test/basic/gosub.cout
  68. 3 0
      test/basic/gosub.out
  69. 28 0
      test/basic/gosub.tout
  70. 21 0
      test/basic/goto
  71. 25 0
      test/basic/goto.cout
  72. 4 0
      test/basic/goto.out
  73. 66 0
      test/basic/goto.tout
  74. 7 0
      test/basic/local
  75. 9 0
      test/basic/local.cout
  76. 1 0
      test/basic/local.out
  77. 21 0
      test/basic/local.tout
  78. 2 0
      test/basic/print
  79. 4 0
      test/basic/print.cout
  80. 2 0
      test/basic/print.out
  81. 11 0
      test/basic/print.tout
  82. 4 0
      test/basic/unicode
  83. 8 0
      test/basic/unicode.cout
  84. 4 0
      test/basic/unicode.out
  85. 21 0
      test/basic/unicode.tout
  86. 15 0
      test/calc/base
  87. 58 0
      test/calc/base.cout
  88. 12 0
      test/calc/base.out
  89. 95 0
      test/calc/base.tout
  90. 1 0
      test/calc/comma
  91. 8 0
      test/calc/comma.cout
  92. 1 0
      test/calc/comma.out
  93. 12 0
      test/calc/comma.tout
  94. 8 0
      test/calc/mixed
  95. 60 0
      test/calc/mixed.cout
  96. 8 0
      test/calc/mixed.out
  97. 97 0
      test/calc/mixed.tout
  98. 1 0
      test/calc/mod
  99. 4 0
      test/calc/mod.cout
  100. 1 0
      test/calc/mod.out

+ 3 - 1
.gitignore

@@ -1,2 +1,4 @@
 /nbproject
-LonelyTiger
+lonely_tiger
+*.java
+*.o

+ 0 - 29
Exception.cpp

@@ -1,29 +0,0 @@
-#include "Exception.h"
-
-#include <iostream>
-
-using namespace std;
-
-Exception::Exception(string message)
-{
-    this->message = message;
-    this->line = -1;
-}
-
-Exception::Exception(string message, int line)
-{
-    this->message = message;
-    this->line = line;
-}
-
-void Exception::print() const
-{
-    cout << message;
-    if(line != -1)
-    {
-        cout << "(" << line << ")";
-    }
-    cout << endl;
-}
-
-

+ 0 - 21
Exception.h

@@ -1,21 +0,0 @@
-#ifndef EXCEPTION_H
-#define EXCEPTION_H
-
-#include <string>
-
-using namespace std;
-
-class Exception
-{
-public:
-    Exception(string message);
-    Exception(string message, int line);
-    
-    void print() const;
-private:
-    string message;
-    int line;
-};
-
-#endif
-

+ 0 - 44
File.cpp

@@ -1,44 +0,0 @@
-#include "File.h"
-#include <iostream>
-#include <fstream>
-#include <sstream>
-
-File::File(string path)
-{
-    this->path = path;
-}
-
-File::File(const File& orig)
-{
-}
-
-File::~File()
-{
-}
-
-bool File::exists()
-{
-    ifstream fileStream(path);
-    return fileStream.good();
-}
-
-string File::read()
-{
-    ifstream fileStream(path);
-    if(!fileStream.good())
-    {
-        return "";
-    }
-
-    stringstream stream;
-    string s;
-    while(!fileStream.eof())
-    {
-        getline(fileStream, s);
-        stream << s;
-        stream << '\n';
-    }
-
-    return stream.str();
-}
-

+ 0 - 22
File.h

@@ -1,22 +0,0 @@
-#ifndef FILE_H
-#define FILE_H
-
-#include <string>
-
-using namespace std;
-
-class File 
-{
-public:
-    File(string path);
-    File(const File& orig);
-    virtual ~File();
-    
-    bool exists();
-    string read();
-private:
-    string path;
-};
-
-#endif
-

+ 2 - 25
Main.cpp

@@ -1,31 +1,8 @@
-#include <iostream>
-#include "File.h"
-#include "compiler/Tokenizer.h"
-#include "Exception.h"
-#include "data/Stack.h"
-#include "code/Script.h"
-#include "compiler/Compiler.h"
-#include "code/FloatData.h"
-#include "code/BoolData.h"
-#include "code/Instruction.h"
-
-using namespace std;
+#include "snuviscript/test/Test.h"
 
 int main(int argc, char** argv) 
 {        
-    File f("tests/vars.snuvi");
-    if(f.exists())
-    {
-        Compiler c(f.read());
-        Script sc;
-        c.compile(sc);
-        sc.execute();
-    }
-    else
-    {
-        cout << "no" << endl;
-    }
-
+    Test::test();
     return 0;
 }
 

+ 35 - 5
Makefile

@@ -1,8 +1,38 @@
-run: all
-	./LonelyTiger
+VERSION = -Wall -std=c++14
 
-all: *.cpp *.h compiler/*.cpp compiler/*.h code/*.cpp code/*.h
-	g++ -Wall -std=c++14 *.cpp compiler/*.cpp code/*.cpp -o LonelyTiger
+run: lonely_tiger
+	./lonely_tiger
+	
+lonely_tiger: Main.cpp Test.o Token.o DoubleToken.o StringToken.o TokenType.o Tokenizer.o TestLogger.o PreScriptException.o
+	g++ $(VERSION) -o $@ Main.cpp *.o
 	
 clean:
-	rm LonelyTiger
+	rm lonely_tiger *.o
+	
+	
+PreScriptException.o: snuviscript/exceptions/PreScriptException.cpp snuviscript/exceptions/PreScriptException.h
+	g++ $(VERSION) -c snuviscript/exceptions/PreScriptException.cpp -o $@	
+
+Test.o: snuviscript/test/Test.cpp snuviscript/test/Test.h
+	g++ $(VERSION) -c snuviscript/test/Test.cpp -o $@
+	
+TestLogger.o: snuviscript/test/TestLogger.cpp snuviscript/test/TestLogger.h
+	g++ $(VERSION) -c snuviscript/test/TestLogger.cpp -o $@
+	
+StringObject.o: snuviscript/base/StringObject.cpp snuviscript/base/StringObject.h
+	g++ $(VERSION) -c snuviscript/base/StringObject.cpp -o $@
+	
+Token.o: snuviscript/tokenizer/Token.cpp snuviscript/tokenizer/Token.h
+	g++ $(VERSION) -c snuviscript/tokenizer/Token.cpp -o $@
+	
+DoubleToken.o: snuviscript/tokenizer/DoubleToken.cpp snuviscript/tokenizer/DoubleToken.h
+	g++ $(VERSION) -c snuviscript/tokenizer/DoubleToken.cpp -o $@
+	
+StringToken.o: snuviscript/tokenizer/StringToken.cpp snuviscript/tokenizer/StringToken.h
+	g++ $(VERSION) -c snuviscript/tokenizer/StringToken.cpp -o $@
+	
+TokenType.o: snuviscript/tokenizer/TokenType.cpp snuviscript/tokenizer/TokenType.h
+	g++ $(VERSION) -c snuviscript/tokenizer/TokenType.cpp -o $@
+	
+Tokenizer.o: snuviscript/tokenizer/Tokenizer.cpp snuviscript/tokenizer/Tokenizer.h
+	g++ $(VERSION) -c snuviscript/tokenizer/Tokenizer.cpp -o $@

+ 0 - 22
Utils.cpp

@@ -1,22 +0,0 @@
-#include "Utils.h"
-
-bool isLetter(char c)
-{
-    return ('a' <= c && 'z' >= c) || ('A' <= c && 'Z' >= c);
-}
-
-bool isDigit(char c)
-{
-    return '0' <= c && '9' >= c;
-}
-
-bool isLetterOrDigit(char c)
-{
-    return isLetter(c) || isDigit(c);
-}
-
-bool isAllowedInName(char c)
-{
-    return isLetter(c) || isDigit(c) || c == '.' || c == '_';
-}
-

+ 0 - 10
Utils.h

@@ -1,10 +0,0 @@
-#ifndef UTILS_H
-#define UTILS_H
-
-bool isLetter(char c);
-bool isDigit(char c);
-bool isLetterOrDigit(char c);
-bool isAllowedInName(char c);
-
-#endif
-

+ 0 - 31
code/BoolData.cpp

@@ -1,31 +0,0 @@
-#include "BoolData.h"
-
-BoolData::BoolData(bool b) : b(b)
-{
-}
-
-BoolData::BoolData(const BoolData& orig)
-{
-}
-
-BoolData::~BoolData()
-{
-}
-
-bool BoolData::getBool() const
-{
-    return b;
-}
-
-void BoolData::print(std::ostream& os) const
-{
-    if(b)
-    {
-        os << "cbool(true)";
-    } 
-    else
-    { 
-        os << "cbool(false)";
-    }
-}
-

+ 0 - 20
code/BoolData.h

@@ -1,20 +0,0 @@
-#ifndef BOOLDATA_H
-#define BOOLDATA_H
-
-#include "Data.h"
-
-class BoolData : public Data
-{
-public:
-    BoolData(bool b);
-    BoolData(const BoolData& orig);
-    virtual ~BoolData();
-   
-    virtual bool getBool() const;
-    virtual void print(std::ostream& os) const;
-private:
-    bool b;
-};
-
-#endif
-

+ 0 - 55
code/Data.cpp

@@ -1,55 +0,0 @@
-#include "Data.h"
-
-Data::Data()
-{
-}
-
-Data::Data(const Data& orig)
-{
-}
-
-Data::~Data()
-{
-}
-
-float Data::getFloat() const
-{
-    throw Exception("get float not possible");
-}
-
-void Data::setFloat(float f)
-{
-    throw Exception("set float not possible");
-}
-
-bool Data::getBool() const
-{
-    throw Exception("get bool not possible");
-}
-
-void Data::setBool(bool b)
-{
-    throw Exception("set bool not possible");
-}
-
-string Data::getString() const
-{
-    throw Exception("get string not possible");
-}
-
-void Data::setString(string s)
-{
-    throw Exception("set string not possible");
-}
-
-std::ostream& operator<<(std::ostream& os, const Data& d)
-{
-    d.print(os);
-    return os;
-}
-
-void Data::print(std::ostream& os) const
-{
-    os << "_no_print_";
-}
-

+ 0 - 33
code/Data.h

@@ -1,33 +0,0 @@
-#ifndef DATA_H
-#define DATA_H
-
-#include <string>
-#include <iostream>
-#include "../Exception.h"
-
-using namespace std;
-
-class Data
-{
-public:
-    Data();
-    Data(const Data& orig);
-    virtual ~Data();
-
-    virtual float getFloat() const;
-    virtual void setFloat(float f);
-    
-    virtual bool getBool() const;
-    virtual void setBool(bool b);
-    
-    virtual string getString() const;
-    virtual void setString(string s);
-    
-    virtual void print(std::ostream& os) const;
-private:
-};
-
-std::ostream& operator<<(std::ostream& os, const Data& d);
-
-#endif
-

+ 0 - 25
code/FloatData.cpp

@@ -1,25 +0,0 @@
-#include "FloatData.h"
-
-FloatData::FloatData(float f) : f(f)
-{
-}
-
-FloatData::FloatData(const FloatData& orig)
-{
-}
-
-FloatData::~FloatData()
-{
-}
-
-float FloatData::getFloat() const
-{
-    return f;
-}
-
-void FloatData::print(std::ostream& os) const
-{
-    os << "cfloat(";
-    os << f;
-    os << ")";
-}

+ 0 - 21
code/FloatData.h

@@ -1,21 +0,0 @@
-#ifndef FLOATDATA_H
-#define FLOATDATA_H
-
-#include "Data.h"
-#include <iostream>
-
-class FloatData : public Data
-{
-public:
-    FloatData(float f);
-    FloatData(const FloatData& orig);
-    virtual ~FloatData();
-    
-    virtual float getFloat() const;
-    virtual void print(std::ostream& os) const;
-private:
-    float f;
-};
-
-#endif
-

+ 0 - 1
code/Function.c

@@ -1 +0,0 @@
-

+ 0 - 18
code/Function.h

@@ -1,18 +0,0 @@
-#ifndef FUNCTION_H
-#define FUNCTION_H
-
-#include "FloatData.h"
-#include <memory>
-
-void push(int args, Stack<shared_ptr<Data>>& st, shared_ptr<Data> data)
-{
-    st.push(data);
-}
-
-void add(int args, Stack<shared_ptr<Data>>& st, shared_ptr<Data> data)
-{
-    st.push(shared_ptr<FloatData>(new FloatData(st.pop()->getFloat() + st.pop()->getFloat())));
-}
-
-#endif
-

+ 0 - 15
code/Instruction.cpp

@@ -1,15 +0,0 @@
-#include "Instruction.h"
-
-Instruction::Instruction(int args, void (*f) (int, Stack<shared_ptr<Data>>&, shared_ptr<Data>), shared_ptr<Data> data) : args(args), function(f), data(data)
-{
-}
-
-Instruction::~Instruction()
-{
-}
-
-void Instruction::execute(Stack< shared_ptr<Data> >& st) const
-{
-    function(args, st, data);
-}
-

+ 0 - 22
code/Instruction.h

@@ -1,22 +0,0 @@
-#ifndef INSTRUCTION_H
-#define INSTRUCTION_H
-
-#include "../data/Stack.h"
-#include "Data.h"
-#include <memory>
-
-class Instruction
-{
-public:
-    Instruction(int args, void (*f) (int, Stack<shared_ptr<Data>>&, shared_ptr<Data>), shared_ptr<Data> data);
-    virtual ~Instruction();
-    
-    void execute(Stack< shared_ptr<Data> >& st) const;
-private:
-    int args;
-    void (*function) (int, Stack<shared_ptr<Data>>&, shared_ptr<Data>);
-    shared_ptr<Data> data;
-};
-
-#endif
-

+ 0 - 34
code/Script.cpp

@@ -1,34 +0,0 @@
-#include "Script.h"
-#include <iostream>
-
-Script::Script()
-{
-}
-
-Script::~Script()
-{
-    for(int i = 0; i < instructions.getSize(); i++)
-    {
-        delete instructions.get(i);
-    }
-}
-
-void Script::execute()
-{
-    for(int i = 0; i < instructions.getSize(); i++)
-    {
-        cout << i << endl;
-        instructions.get(i)->execute(dataStack);
-    }
-    
-    if(!dataStack.isEmpty())
-    {
-        cout << "RESULT: " << *dataStack.pop() << endl;
-    }
-}
-
-ArrayList<Instruction*>& Script::getInstructions()
-{
-    return instructions;
-}
-

+ 0 - 27
code/Script.h

@@ -1,27 +0,0 @@
-#ifndef SCRIPT_H
-#define SCRIPT_H
-
-#include "../data/ArrayList.h"
-#include "../data/Stack.h"
-#include "Data.h"
-#include "Instruction.h"
-#include <memory>
-
-using namespace std;
-
-class Script
-{
-public:
-    Script();
-    virtual ~Script();
-    
-    void execute();
-    
-    ArrayList<Instruction*>& getInstructions();
-private:
-    ArrayList<Instruction*> instructions;
-    Stack<shared_ptr<Data>> dataStack;
-};
-
-#endif
-

+ 0 - 93
compiler/Compiler.cpp

@@ -1,93 +0,0 @@
-#include "Compiler.h"
-#include "../Exception.h"
-#include "../data/Stack.h"
-#include "../code/Function.h"
-#include "../code/FloatData.h"
-
-Compiler::Compiler(string s) : tokenizer(s)
-{
-}
-
-Compiler::~Compiler()
-{
-}
-
-void Compiler::compile(Script& sc)
-{
-    TokenList tokens;
-    try
-    {
-        tokenizer.tokenize(tokens);
-        compile(sc, tokens);
-    }
-    catch(Exception ex)
-    {
-        ex.print();
-    }
-}
-
-void Compiler::addInstruction(ArrayList<Instruction*>& code, Stack<Token*>& st, Token* t)
-{
-    if(t->getType() == Tokens::FLOAT)
-    {
-        code.add(new Instruction(0, push, shared_ptr<Data>(new FloatData(t->getFloat()))));
-    }
-    else if(t->getType() == Tokens::ADD)
-    {
-        code.add(new Instruction(2, add, nullptr));
-    }
-    cout << *t << endl;
-}
-
-void Compiler::compile(Script& sc, TokenList& tokens)
-{
-    ArrayList<Instruction*>& code = sc.getInstructions();
-    Stack<Token*> st;
-    for(int i = 0; i < tokens.getSize(); i++)
-    {
-        Token* t = tokens.get(i);
-        if(t->getType() == Tokens::END_OF_FILE || t->getType() == Tokens::SEMICOLON)
-        {
-            while(!st.isEmpty())
-            {
-                addInstruction(code, st, st.pop());
-            }
-            continue;
-        }
-        else if(t->getType() == Tokens::OPEN_BRACKET)
-        {
-            st.push(t);
-            continue;
-        }
-        else if(t->getType() == Tokens::CLOSE_BRACKET)
-        {
-            while(!st.isEmpty())
-            {
-                Token* t = st.pop();
-                if(t->getType() == Tokens::OPEN_BRACKET)
-                {
-                    break;
-                }
-                else
-                {
-                    addInstruction(code, st, t);
-                }
-            }
-            continue;
-        }
-        else if(t->getType() == Tokens::SUB && (st.isEmpty() || st.peek()->getType().getLevel() >= Tokens::UNARY_SUB.getLevel()))
-        {
-            t->setType(Tokens::UNARY_SUB);
-        }
-        else if(t->getType() == Tokens::ADD && (st.isEmpty() || st.peek()->getType().getLevel() >= Tokens::UNARY_ADD.getLevel()))
-        {
-            t->setType(Tokens::UNARY_ADD);
-        }
-        
-        while(!st.isEmpty() && st.peek()->getType().getLevel() <= t->getType().getLevel())
-        {
-            addInstruction(code, st, st.pop());
-        }
-        st.push(t);
-    }
-}

+ 0 - 27
compiler/Compiler.h

@@ -1,27 +0,0 @@
-#ifndef COMPILER_H
-#define COMPILER_H
-
-#include <string>
-#include "../data/ArrayList.h"
-#include "Token.h"
-#include "Tokenizer.h"
-#include "../code/Script.h"
-
-using namespace std;
-
-class Compiler
-{
-public:
-    Compiler(string s);
-    virtual ~Compiler();
-
-    void compile(Script& sc);
-private:
-    Tokenizer tokenizer;
-    
-    void compile(Script& sc, TokenList& tokens);
-    void addInstruction(ArrayList<Instruction*>& code, Stack<Token*>& st, Token* t);
-};
-
-#endif
-

+ 0 - 83
compiler/Token.cpp

@@ -1,83 +0,0 @@
-#include "Token.h"
-#include "../Exception.h"
-#include <iostream>
-#include "TokenType.h"
-
-Token::Token(TokenType type, int line) : type(&type)
-{
-    this->line = line;
-    f = 0.0f;
-    s = "";
-}
-
-Token::~Token() 
-{
-}
-
-void Token::setFloat(float f)
-{
-    if((*type) != Tokens::FLOAT)
-    {
-        throw Exception("token contains no float");
-    }
-    this->f = f;
-}
-
-void Token::setString(string s)
-{
-    if(*type != Tokens::TEXT && *type != Tokens::LABEL && *type != Tokens::VAR)
-    {
-        throw Exception("token contains no string");
-    }
-    this->s.assign(s);
-}
-
-float Token::getFloat() const
-{
-    return f;
-}
-
-bool Token::getBool() const
-{
-    if(*type == Tokens::TRUE)
-    {
-        return true;
-    }
-    return false;
-}
-
-string Token::getString() const
-{
-    return s;
-}
-
-int Token::getLine() const
-{
-    return line;
-}
-
-void Token::setType(TokenType type)
-{
-    this->type = &type;
-}
-
-TokenType Token::getType() const
-{
-    return *type;
-}
-
-std::ostream& operator<<(std::ostream& stream, const Token& t)
-{
-    stream << t.getLine() << " ";
-    stream << t.getType();
-    string s = t.getString();
-    if(s.size() != 0)
-    {
-        stream << "(\"" << s << "\")"; 
-    }
-    if(t.getType() == Tokens::FLOAT)
-    {
-        stream << '(' << t.getFloat() << ')'; 
-    }
-    return stream;
-}

+ 0 - 35
compiler/Token.h

@@ -1,35 +0,0 @@
-#ifndef TOKEN_H
-#define TOKEN_H
-
-#include "TokenType.h"
-#include <string>
-
-using namespace std;
-
-class Token
-{
-public:
-    Token(TokenType type, int line);
-    virtual ~Token();
-    
-    void setFloat(float f);
-    void setBool(bool b);
-    void setString(string s);
-    
-    float getFloat() const;
-    bool getBool() const;
-    string getString() const;
-    int getLine() const;
-    void setType(TokenType type);
-    TokenType getType() const;
-private:
-    const TokenTypeClass* type;
-    float f;
-    string s;
-    int line;
-};
-
-std::ostream& operator<< (std::ostream& stream, const Token& t);
-
-#endif
-

+ 0 - 43
compiler/TokenList.cpp

@@ -1,43 +0,0 @@
-#include "TokenList.h"
-
-TokenList::TokenList()
-{
-}
-
-TokenList::TokenList(const TokenList& orig)
-{
-}
-
-TokenList::~TokenList()
-{
-    list.forEach([](Token* t) 
-    {
-        delete t;
-    });
-}
-
-void TokenList::add(Token* t)
-{
-    list.add(t);
-}
-
-void TokenList::remove(int index)
-{
-    list.remove(index);
-}
-
-void TokenList::forEach(void (*f) (Token*))
-{
-    list.forEach(f);
-}
-
-int TokenList::getSize()
-{
-    return list.getSize();
-}
-
-Token* TokenList::get(int index)
-{
-    return list.get(index);
-}
-

+ 0 - 24
compiler/TokenList.h

@@ -1,24 +0,0 @@
-#ifndef TOKENLIST_H
-#define TOKENLIST_H
-
-#include "Token.h"
-#include "../data/ArrayList.h"
-
-class TokenList
-{
-public:
-    TokenList();
-    TokenList(const TokenList& orig);
-    virtual ~TokenList();
-    
-    void add(Token* t);
-    void remove(int index);
-    int getSize();
-    Token* get(int index);
-    void forEach(void (*f) (Token*));
-private:
-    ArrayList<Token*> list;
-};
-
-#endif
-

+ 0 - 101
compiler/TokenType.cpp

@@ -1,101 +0,0 @@
-#include "TokenType.h"
-
-#include <iostream>
-
-TokenTypeClass::~TokenTypeClass()
-{
-}
-
-string TokenTypeClass::getName() const
-{
-    return typeName;
-}
-
-int TokenTypeClass::getLevel() const
-{
-    return level;
-}
-
-bool TokenTypeClass::operator==(const TokenTypeClass& t) const
-{
-    return this == &t;
-}
-
-bool TokenTypeClass::operator!=(const TokenTypeClass& t) const
-{
-    return this != &t;
-}
-
-std::ostream& operator<<(std::ostream& os, const TokenType& c)
-{
-    return os << c.getName();
-}
-
-namespace Tokens
-{
-    const TokenTypeClass FLOAT("float");
-    const TokenTypeClass TRUE("bool(true)");
-    const TokenTypeClass FALSE("bool(false)");
-    const TokenTypeClass TNULL("null");
-    const TokenTypeClass TEXT("String");
-    const TokenTypeClass LABEL("Label");
-    const TokenTypeClass VAR("var");
-    const TokenTypeClass GLOBAL("$");
-    
-    const TokenTypeClass INC("++", 2);
-    const TokenTypeClass DEC("--", 2);
-    const TokenTypeClass INVERT("!", 2);
-    const TokenTypeClass BIT_INVERT("~", 2);
-    const TokenTypeClass MUL("*", 3);
-    const TokenTypeClass DIV("/", 3);
-    const TokenTypeClass MOD("%", 3);
-    const TokenTypeClass UNARY_ADD("u+", 2);
-    const TokenTypeClass UNARY_SUB("u-", 2);
-    const TokenTypeClass ADD("+", 4);
-    const TokenTypeClass SUB("-", 4);
-    const TokenTypeClass LEFT_SHIFT("<<", 5);
-    const TokenTypeClass RIGHT_SHIFT(">>", 5);
-    const TokenTypeClass LESS("<", 6);
-    const TokenTypeClass LESS_EQUAL("<=", 6);
-    const TokenTypeClass GREATER(">", 6);
-    const TokenTypeClass GREATER_EQUAL(">=", 6);
-    const TokenTypeClass EQUAL("==", 7);
-    const TokenTypeClass NOT_EQUAL("!=", 7);
-    const TokenTypeClass BIT_AND("&", 8);
-    const TokenTypeClass BIT_XOR("^", 9);
-    const TokenTypeClass BIT_OR("|", 10);
-    const TokenTypeClass AND("&&", 11);
-    const TokenTypeClass OR("||", 12);
-    const TokenTypeClass SET("=", 14);
-    const TokenTypeClass ADD_SET("+=", 14);
-    const TokenTypeClass SUB_SET("-=", 14);
-    const TokenTypeClass MUL_SET("*=", 14);
-    const TokenTypeClass DIV_SET("/=", 14);
-    const TokenTypeClass MOD_SET("%=", 14);
-    const TokenTypeClass LEFT_SHIFT_SET("<<=", 14);
-    const TokenTypeClass RIGHT_SHIFT_SET(">>=", 14);
-    const TokenTypeClass BIT_AND_SET("&=", 14);
-    const TokenTypeClass BIT_XOR_SET("^=", 14);
-    const TokenTypeClass BIT_OR_SET("|=", 14);
-    const TokenTypeClass COMMA(",", 15);
-    const TokenTypeClass OPEN_BRACKET("(", 50);
-    const TokenTypeClass CLOSE_BRACKET(")", 50);
-    const TokenTypeClass OPEN_SQUARE_BRACKET("[", 1);
-    const TokenTypeClass CLOSE_SQUARE_BRACKET("]", 1);
-    const TokenTypeClass OPEN_CURVED_BRACKET("{");
-    const TokenTypeClass CLOSE_CURVED_BRACKET("}");
-    const TokenTypeClass SEMICOLON(";");
-    
-    const TokenTypeClass IF("if");
-    const TokenTypeClass ELSE_IF("else if");
-    const TokenTypeClass ELSE("else");
-    const TokenTypeClass FOR("for");
-    const TokenTypeClass WHILE("while");
-    const TokenTypeClass FUNCTION("function");
-    const TokenTypeClass BREAK("break");
-    const TokenTypeClass CONTINUE("continue");
-    const TokenTypeClass RETURN("return");
-    const TokenTypeClass TRY("try");
-    const TokenTypeClass CATCH("catch");
-    const TokenTypeClass END_OF_FILE("end_of_file");  
-};

+ 0 - 100
compiler/TokenType.h

@@ -1,100 +0,0 @@
-#ifndef TOKENTYPE_H
-#define TOKENTYPE_H
-
-#include <iostream>
-#include <string>
-
-using namespace std;
-
-class TokenTypeClass
-{
-public:
-    TokenTypeClass(string name, int level) : typeName(name), level(level) {};
-    TokenTypeClass(string name) : typeName(name), level(-1) {};
-    virtual ~TokenTypeClass();
-
-    string getName() const;
-    int getLevel() const;
-    
-    bool operator==(const TokenTypeClass& t) const;
-    bool operator!=(const TokenTypeClass& t) const;
-private:
-    string typeName;
-    int level;
-};
-
-typedef const TokenTypeClass& TokenType;
-
-std::ostream& operator<<(std::ostream& os, const TokenType& c);
-
-namespace Tokens
-{
-    extern const TokenTypeClass FLOAT;
-    extern const TokenTypeClass TRUE;
-    extern const TokenTypeClass FALSE;
-    extern const TokenTypeClass TNULL;
-    extern const TokenTypeClass TEXT;
-    extern const TokenTypeClass LABEL;
-    extern const TokenTypeClass VAR;
-    extern const TokenTypeClass GLOBAL;
-    
-    extern const TokenTypeClass INC;
-    extern const TokenTypeClass DEC;
-    extern const TokenTypeClass INVERT;
-    extern const TokenTypeClass BIT_INVERT;
-    extern const TokenTypeClass MUL;
-    extern const TokenTypeClass DIV;
-    extern const TokenTypeClass MOD;
-    extern const TokenTypeClass UNARY_ADD;
-    extern const TokenTypeClass UNARY_SUB;
-    extern const TokenTypeClass ADD;
-    extern const TokenTypeClass SUB;
-    extern const TokenTypeClass LEFT_SHIFT;
-    extern const TokenTypeClass RIGHT_SHIFT;
-    extern const TokenTypeClass LESS;
-    extern const TokenTypeClass LESS_EQUAL;
-    extern const TokenTypeClass GREATER;
-    extern const TokenTypeClass GREATER_EQUAL;
-    extern const TokenTypeClass EQUAL;
-    extern const TokenTypeClass NOT_EQUAL;
-    extern const TokenTypeClass BIT_AND;
-    extern const TokenTypeClass BIT_XOR;
-    extern const TokenTypeClass BIT_OR;
-    extern const TokenTypeClass AND;
-    extern const TokenTypeClass OR;
-    extern const TokenTypeClass SET;
-    extern const TokenTypeClass ADD_SET;
-    extern const TokenTypeClass SUB_SET;
-    extern const TokenTypeClass MUL_SET;
-    extern const TokenTypeClass DIV_SET;
-    extern const TokenTypeClass MOD_SET;
-    extern const TokenTypeClass LEFT_SHIFT_SET;
-    extern const TokenTypeClass RIGHT_SHIFT_SET;
-    extern const TokenTypeClass BIT_AND_SET;
-    extern const TokenTypeClass BIT_XOR_SET;
-    extern const TokenTypeClass BIT_OR_SET;
-    extern const TokenTypeClass COMMA;
-    extern const TokenTypeClass OPEN_BRACKET;
-    extern const TokenTypeClass CLOSE_BRACKET;
-    extern const TokenTypeClass OPEN_SQUARE_BRACKET;
-    extern const TokenTypeClass CLOSE_SQUARE_BRACKET;
-    extern const TokenTypeClass OPEN_CURVED_BRACKET;
-    extern const TokenTypeClass CLOSE_CURVED_BRACKET;
-    extern const TokenTypeClass SEMICOLON;
-    
-    extern const TokenTypeClass IF;
-    extern const TokenTypeClass ELSE_IF;
-    extern const TokenTypeClass ELSE;
-    extern const TokenTypeClass FOR;
-    extern const TokenTypeClass WHILE;
-    extern const TokenTypeClass FUNCTION;
-    extern const TokenTypeClass BREAK;
-    extern const TokenTypeClass CONTINUE;
-    extern const TokenTypeClass RETURN;
-    extern const TokenTypeClass TRY;
-    extern const TokenTypeClass CATCH;
-    extern const TokenTypeClass END_OF_FILE;
-};
-
-#endif
-

+ 0 - 262
compiler/Tokenizer.cpp

@@ -1,262 +0,0 @@
-#include "Tokenizer.h"
-#include "../Utils.h"
-#include "../Exception.h"
-
-Tokenizer::Tokenizer(string s) 
-{
-    data = s;
-    line = 0;
-    pos = 0;
-    length = 0;
-}
-
-Tokenizer::Tokenizer(const Tokenizer& orig) 
-{
-}
-
-Tokenizer::~Tokenizer() 
-{
-}
-
-void Tokenizer::tokenize(TokenList& tokens, char c, TokenType type1, TokenType type2)
-{
-    if(pos + 1 < length && data[pos + 1] == c)
-    {
-        tokens.add(new Token(type1, line));
-        pos++;
-    }
-    else
-    {
-        tokens.add(new Token(type2, line));
-    }
-}
-
-void Tokenizer::tokenize(TokenList& tokens, TokenType type1, char c2, TokenType type2, char c3, TokenType type3)
-{
-    if(pos + 1 >= length)
-    {
-        tokens.add(new Token(type1, line));
-    }
-    else if(data[pos + 1] == c2)
-    {
-        tokens.add(new Token(type2, line));
-        pos++;
-    }
-    else if(data[pos + 1] == c3)
-    {
-        tokens.add(new Token(type3, line));
-        pos++;
-    }
-    else
-    {
-        tokens.add(new Token(type1, line));
-    }
-}
-
-void Tokenizer::tokenize(TokenList& tokens, TokenType type1, char c2, char c3, TokenType type2, TokenType type3, char c4, TokenType type4)
-{
-    if(pos + 1 >= length)
-    {
-        tokens.add(new Token(type1, line));
-    }
-    else if(data[pos + 1] == c2)
-    {
-        if(pos + 2 < length && data[pos + 2] == c3)
-        {
-            tokens.add(new Token(type2, line));
-            pos += 2;
-        }
-        else
-        {
-            tokens.add(new Token(type3, line));
-            pos++;
-        }
-    }
-    else if(data[pos + 1] == c4)
-    {
-        tokens.add(new Token(type4, line));
-        pos++;
-    }
-    else
-    {
-        tokens.add(new Token(type1, line));
-    }
-}
-
-void Tokenizer::tokenize(TokenList& tokens)
-{
-    line = 1;
-    pos = 0;
-    length = data.size();
-    
-    while(pos < length)
-    {
-        if(isLetter(data[pos]))
-        {
-            int old = pos;
-            pos++;
-            while(pos < length && isAllowedInName(data[pos]))
-            {
-                pos++;
-            }
-            string s = data.substr(old, pos - old);
-            if(s == "if") {tokens.add(new Token(Tokens::IF, line));}
-            else if(s == "elseif") {tokens.add(new Token(Tokens::ELSE_IF, line));}
-            else if(s == "else") {tokens.add(new Token(Tokens::ELSE, line));}
-            else if(s == "for") {tokens.add(new Token(Tokens::FOR, line));}
-            else if(s == "while") {tokens.add(new Token(Tokens::WHILE, line));}
-            else if(s == "function") {tokens.add(new Token(Tokens::FUNCTION, line));}
-            else if(s == "break") {tokens.add(new Token(Tokens::BREAK, line));}
-            else if(s == "continue") {tokens.add(new Token(Tokens::CONTINUE, line));}
-            else if(s == "return") {tokens.add(new Token(Tokens::RETURN, line));}
-            else if(s == "try") {tokens.add(new Token(Tokens::TRY, line));}
-            else if(s == "catch") {tokens.add(new Token(Tokens::CATCH, line));}
-            else if(s == "true") {tokens.add(new Token(Tokens::TRUE, line));}
-            else if(s == "false") {tokens.add(new Token(Tokens::FALSE, line));}
-            else if(s == "null") {tokens.add(new Token(Tokens::TNULL, line));}
-            else
-            {
-                Token* t = new Token(Tokens::VAR, line);
-                t->setString(s);
-                tokens.add(t);
-            }
-            pos--;
-        }
-        else if(isDigit(data[pos]))
-        {
-            int old = pos;
-            pos++;
-            while(pos < length && isDigit(data[pos]))
-            {
-                pos++;
-            }
-            if(pos < length && data[pos] == '.')
-            {
-                pos++;
-                while(pos < length && isDigit(data[pos]))
-                {
-                    pos++;
-                }
-            }
-            string s = data.substr(old, pos - old);
-            try
-            {
-                float f = stof(s);
-                
-                Token* t = new Token(Tokens::FLOAT, line);
-                t->setFloat(f);
-                tokens.add(t);
-            }
-            catch(std::out_of_range ex)
-            {
-                throw Exception("invalid float", line);
-            }
-            catch(std::invalid_argument ex)
-            {
-                throw Exception("invalid float", line);
-            }
-            pos--;
-        }
-        else
-        {
-            switch(data[pos])
-            {
-                case '@':
-                {
-                    int old = pos;
-                    pos++;
-                    while(pos < length && isAllowedInName(data[pos]))
-                    {
-                        pos++;
-                    }
-                    string s = data.substr(old, pos - old);
-                    Token* t = new Token(Tokens::LABEL, line);
-                    t->setString(s);
-                    tokens.add(t);
-                    pos--;
-                    break;
-                }
-                case '"':
-                {
-                    pos++;
-                    int old = pos;
-                    while(pos < length && data[pos] != '"')
-                    {
-                        pos++;
-                    }
-                    string s = data.substr(old, pos - old);
-                    Token* t = new Token(Tokens::TEXT, line);
-                    t->setString(s);
-                    tokens.add(t);
-                    break;
-                }
-                case '/':
-                {
-                    if(pos + 1 >= length)
-                    {
-                        tokens.add(new Token(Tokens::DIV, line));
-                    }
-                    else
-                    {
-                        switch(data[pos + 1])
-                        {
-                            case '/':
-                                pos += 2;
-                                while(pos < length && data[pos] != '\n')
-                                {
-                                    pos++;
-                                }
-                                pos--;
-                                break;
-                            case '*':
-                                pos += 2;
-                                while(pos + 1 < length && (data[pos] != '*' || data[pos + 1] != '/'))
-                                {
-                                    if(data[pos] == '\n')
-                                    {
-                                        line++;
-                                    }
-                                    pos++;
-                                }
-                                pos++;
-                                break;
-                            case '=':
-                                tokens.add(new Token(Tokens::DIV_SET, line));
-                                pos++;
-                                break;
-                            default:
-                                tokens.add(new Token(Tokens::DIV, line));
-                        }
-                    }
-                    break;
-                }
-                case '<': tokenize(tokens, Tokens::LESS, '<', '=', Tokens::LEFT_SHIFT_SET, Tokens::LEFT_SHIFT, '=', Tokens::LESS_EQUAL); break;
-                case '>': tokenize(tokens, Tokens::GREATER, '>', '=', Tokens::RIGHT_SHIFT_SET, Tokens::RIGHT_SHIFT, '=', Tokens::GREATER_EQUAL); break;
-                case '&': tokenize(tokens, Tokens::BIT_AND, '&', Tokens::AND, '=', Tokens::BIT_AND_SET); break;
-                case '|': tokenize(tokens, Tokens::BIT_OR, '|', Tokens::OR, '=', Tokens::BIT_OR_SET); break;
-                case '+': tokenize(tokens, Tokens::ADD, '+', Tokens::INC, '=', Tokens::ADD_SET); break;
-                case '-': tokenize(tokens, Tokens::SUB, '-', Tokens::DEC, '=', Tokens::SUB_SET); break;
-                case '*': tokenize(tokens, '=', Tokens::MUL_SET, Tokens::MUL); break;
-                case '\n': line++; break;
-                case '!': tokenize(tokens, '=', Tokens::NOT_EQUAL, Tokens::INVERT); break;
-                case '%': tokenize(tokens, '=', Tokens::MOD_SET, Tokens::MOD); break;
-                case '=': tokenize(tokens, '=', Tokens::EQUAL, Tokens::SET); break;
-                case '^': tokenize(tokens, '=', Tokens::BIT_XOR_SET, Tokens::BIT_XOR); break;
-                case '~': tokens.add(new Token(Tokens::BIT_INVERT, line)); break;
-                case ',': tokens.add(new Token(Tokens::COMMA, line)); break;
-                case '(': tokens.add(new Token(Tokens::OPEN_BRACKET, line)); break;
-                case ')': tokens.add(new Token(Tokens::CLOSE_BRACKET, line)); break;
-                case '[': tokens.add(new Token(Tokens::OPEN_SQUARE_BRACKET, line)); break;
-                case ']': tokens.add(new Token(Tokens::CLOSE_SQUARE_BRACKET, line)); break;
-                case '{': tokens.add(new Token(Tokens::OPEN_CURVED_BRACKET, line)); break;
-                case '}': tokens.add(new Token(Tokens::CLOSE_CURVED_BRACKET, line)); break;
-                case ';': tokens.add(new Token(Tokens::SEMICOLON, line)); break;
-                case '$': tokens.add(new Token(Tokens::GLOBAL, line)); break;
-                case ' ': break;
-                default: throw Exception(string("invalid token ") + data[pos], line);
-            }
-        } 
-        pos++;
-    }
-    tokens.add(new Token(Tokens::END_OF_FILE, line));
-}

+ 0 - 31
compiler/Tokenizer.h

@@ -1,31 +0,0 @@
-#ifndef TOKENIZER_H
-#define TOKENIZER_H
-
-#include <string>
-#include "../data/ArrayList.h"
-#include "Token.h"
-#include "TokenList.h"
-
-using namespace std;
-
-class Tokenizer 
-{
-public:
-    Tokenizer(string s);
-    Tokenizer(const Tokenizer& orig);
-    virtual ~Tokenizer();
-    
-    void tokenize(TokenList& tokens);
-private:
-    string data;
-    int pos;
-    int line;
-    int length;
-    
-    void tokenize(TokenList& tokens, char c, TokenType type1, TokenType type2);
-    void tokenize(TokenList& tokens, TokenType type1, char c2, TokenType, char c3, TokenType type3);
-    void tokenize(TokenList& tokens, TokenType type1, char c2, char c3, TokenType type2, TokenType type3, char c4, TokenType type4);
-};
-
-#endif
-

+ 0 - 107
data/ArrayList.h

@@ -1,107 +0,0 @@
-#ifndef ARRAYLIST_H
-#define ARRAYLIST_H
-
-#include <cstring>
-#include <iostream>
-#include "../Exception.h"
-
-template<class T>
-class ArrayList
-{
-public:
-    ArrayList()
-    {
-        pos = 0;
-        capacity = 4;
-        data = new T[capacity];
-    }
-    
-    ArrayList(const ArrayList& orig)
-    {
-        pos = orig.pos;
-        capacity = orig.capacity;
-        data = new T[capacity];
-        memcpy(data, orig.data, capacity * sizeof(T));
-    }
-    
-    ArrayList& operator=(const ArrayList& orig)
-    {
-        delete[] data;
-        
-        pos = orig.pos;
-        capacity = orig.capacity;
-        data = new T[capacity];
-        memcpy(data, orig.data, capacity * sizeof(T));
-        
-        return *this;
-    }
-    
-    virtual ~ArrayList()
-    {
-        delete[] data;
-    }
-    
-    int getSize()
-    {
-        return pos;
-    }
-    
-    void clear()
-    {
-        memset(data, 0, sizeof(T) * pos);
-        pos = 0;
-    }
-    
-    void add(T t)
-    {
-        if(pos >= capacity)
-        {
-            int newCapacity = capacity * 2;
-            T* t = new T[newCapacity];
-            memcpy(t, data, capacity * sizeof(T));
-            delete[] data;
-            data = t;
-            capacity = newCapacity;
-        }
-        data[pos] = t;
-        pos++;
-    }
-    
-    void remove(int index)
-    {
-        if(index < 0 || index >= pos)
-        {
-            return;
-        }
-        for(int i = index; i < pos - 1; i++)
-        {
-            data[i] = data[i + 1];
-        }
-        memset(data + pos - 1, 0, sizeof(T));
-        pos--;
-    }
-    
-    T get(int index)
-    {
-        if(index < 0 || index >= pos)
-        {
-            throw Exception("out of bounds");
-        }
-        return data[index];
-    }
-    
-    void forEach(void (*f) (T))
-    {
-        for(int i = 0; i < pos; i++)
-        {
-            f(data[i]);
-        }
-    }
-private:
-    int capacity;
-    int pos;
-    T* data;
-};
-
-#endif
-

+ 0 - 340
data/HashMap.h

@@ -1,340 +0,0 @@
-#ifndef HASHMAP_H
-#define HASHMAP_H
-
-const static int PRIMES[26] = 
-{
-    17, 37, 79, 163, 331, 673, 1361, 2729, 5471, 10949, 21911, 43853, 87719, 
-    175447, 350899, 701819, 1403641, 2807303, 5614657, 11229331, 22458671,
-    44917381, 89834777, 179669557, 359339171, 718678369
-};
-
-template<class K, class V> 
-class HashMap
-{
-    class Node
-    {
-    public:
-        Node* next;
-        K k;
-        V v;
-        
-        Node(K k, V v)
-        {
-            next = nullptr;
-            this->k = k;
-            this->v = v;
-        }
-    };
-    
-private:
-    // hasher, key comparison
-    int (*hasher)(K); 
-    bool (*equal)(K, K);
-    
-    // size specs
-    int primeIndex;
-    int capacity;
-    int resizeCap;
-    
-    // entries
-    Node** data;
-    int entries;
-    
-    // found node
-    K lastKey;
-    Node* found;
-    int lastIndex;
-    
-    int getHigherPrimeIndex(int lower) const
-    {
-        int low = 0;
-        int high = 25;
-        int mid;
-        while(true)
-        {
-            if(low == high)
-            {
-                return low;
-            }
-            mid = (high + low) >> 1;
-            if(PRIMES[mid] >= lower)
-            {
-                high = mid;
-            }
-            else
-            {
-                low = mid + 1;
-            }
-        }
-    }
-    
-    int getHash(K k) const
-    {
-        int hash = ((*hasher)(k)) % capacity;
-        return hash < 0 ? hash + capacity : hash;
-    }
-    
-    void ensureCapacity()
-    {
-        if(entries < resizeCap)
-        {
-            return;
-        }
-        
-        primeIndex++;
-        if(primeIndex >= 26)
-        {
-            resizeCap = 2147483647;
-            return;
-        }
-        
-        int oldCapacity = capacity;
-        capacity = PRIMES[primeIndex];
-        
-        resizeCap = (capacity >> 2) * 3;
-        
-        Node** newData = new Node*[capacity];
-        Node* n;
-        Node* m;
-        
-        int hash;
-        for(int i = 0; i < oldCapacity; i++)
-        {
-            Node* old = data[i];
-            if(old != nullptr)
-            {
-                hash = getHash(old->k);
-                n = newData[hash];
-                if(n == nullptr)
-                {
-                    newData[hash] = old;
-                }
-                else
-                {
-                    while(n->next != nullptr)
-                    {
-                        n = n->next;
-                    }
-                    n->next = old;
-                }
-                
-                while(old->next != nullptr)
-                {
-                    n = old->next;
-                    old->next = nullptr;
-                    
-                    hash = getHash(n->k);
-                    m = newData[hash];
-                    if(m == nullptr)
-                    {
-                        newData[hash] = n;
-                    }
-                    else
-                    {
-                        while(m->next != nullptr)
-                        {
-                            m = m->next;
-                        }
-                        m->next = n;
-                    }
-                    
-                    old = n;
-                }
-            }
-        }
-        
-        delete[] data;
-        data = newData;
-    }
-
-public:
-    HashMap(int initialLoad, int (*hasher)(K), bool (*equal)(K, K))
-    {
-        this->hasher = hasher;
-        this->equal = equal;
-        this->hasher = hasher;
-        
-        primeIndex = getHigherPrimeIndex(initialLoad);
-        capacity = PRIMES[primeIndex];
-        resizeCap = (capacity >> 2) * 3;
-        
-        data = new Node*[capacity];
-        for(int i = 0; i < capacity; i++)
-        {
-            data[i] = nullptr;
-        }
-        entries = 0;
-        
-        found = nullptr;
-        lastIndex = -1;
-    }
-    
-    virtual ~HashMap()
-    {
-        for(int i = 0; i < capacity; i++)
-        {
-            Node* n = data[i];
-            while(n != nullptr)
-            {
-                Node* next = n->next;
-                delete n;
-                n = next;
-            }
-        }
-        delete[] data;
-    }
-    
-    void search(K k)
-    {
-        lastKey = k;
-        int hash = getHash(k);
-        Node* n = data[hash];
-        if(n == nullptr) // free slot, nothing found
-        {
-            found = nullptr;
-            // mark index for inserting
-            lastIndex = hash;
-        }
-        else
-        {
-            while(true)
-            {
-                if((*equal)(k, n->k)) // key was found
-                {
-                    // mark existing node for overwrite / deleting
-                    found = n;
-                    lastIndex = hash;
-                    return;
-                }
-                if(n->next == nullptr)
-                {
-                    break;
-                }
-                n = n->next;
-            }
-            // nothing found, mark last node for adding
-            found = n;
-            lastIndex = -1;
-        }
-    }
-    
-    void print() const
-    {
-        for(int i = 0; i < capacity; i++)
-        {
-            Node* n = data[i];
-            if(n != nullptr)
-            {
-                std::cout << n->k << " - " << n->v;
-                while(n->next != nullptr)
-                {
-                    n = n->next;
-                    std::cout << ", " << n->k << " - " << n->v;
-                }
-                std::cout << "\n";
-            }
-        }
-    }
-    
-    void insert(K k, V v)
-    {
-        search(k);
-        insert(v);
-    }
-    
-    void insert(V v)
-    {
-        if(found == nullptr)
-        {
-            if(lastIndex != -1)
-            {
-                // inserting into empty slot
-                data[lastIndex] = new Node(lastKey, v);
-                entries++;
-                lastIndex = -1;
-                ensureCapacity();
-            }
-        }
-        else
-        {
-            if(lastIndex != -1)
-            {
-                // overwriting old value
-                found->v = v;
-            }
-            else
-            {
-                // adding new node to list
-                found->next = new Node(lastKey, v);
-                entries++;
-                ensureCapacity();
-            }
-            found = nullptr;
-        }
-    }
-    
-    void remove()
-    {
-        if(found != nullptr && lastIndex != -1)
-        {
-            // search previous node
-            Node* n = data[lastIndex];
-            if(found == n)
-            {
-                data[lastIndex] = n->next;
-                delete n;
-            }
-            else
-            {
-                while(n->next != found)
-                {
-                    n = n->next;
-                }
-                n->next = found->next;
-                delete found;
-            }
-            entries--;
-            found = nullptr;
-        }
-    }
-    
-    bool isFound() const
-    {
-        return found != nullptr && lastIndex != -1;
-    }
-    
-    V getValue() const
-    {
-        return found->v;
-    }
-    
-    int getCapacity() const
-    {
-        return capacity;
-    }
-    
-    int getSize() const
-    {
-        return entries;
-    }
-    
-    void forEach(void (*w)(K, V)) const
-    {
-        for(int i = 0; i < capacity; i++)
-        {
-            Node* n = data[i];
-            if(n != nullptr)
-            {
-                (*w)(n->k, n->v);
-                while(n->next != nullptr)
-                {
-                    n = n->next;
-                    (*w)(n->k, n->v);
-                }
-            }
-        }
-    }
-};
-
-#endif
-

+ 0 - 91
data/Stack.h

@@ -1,91 +0,0 @@
-#ifndef STACK_H
-#define STACK_H
-
-#include "../Exception.h"
-
-template<class T>
-class Stack
-{
-public:
-    Stack()
-    {
-        pos = 0;
-        capacity = 4;
-        data = new T[capacity];
-    }
-    
-    Stack(const Stack& orig)
-    {
-        pos = orig.pos;
-        capacity = orig.capacity;
-        data = new T[capacity];
-        memcpy(data, orig.data, capacity * sizeof(T));
-    }
-    
-    Stack& operator=(const Stack& orig)
-    {
-        delete[] data;
-        
-        pos = orig.pos;
-        capacity = orig.capacity;
-        data = new T[capacity];
-        memcpy(data, orig.data, capacity * sizeof(T));
-        
-        return *this;
-    }
-    
-    virtual ~Stack()
-    {
-        delete[] data;
-    }
-    
-    int getSize()
-    {
-        return pos;
-    }
-    
-    bool isEmpty()
-    {
-        return pos == 0;
-    }
-    
-    void push(T t)
-    {
-        if(pos >= capacity)
-        {
-            int newCapacity = capacity * 2;
-            T* t = new T[newCapacity];
-            memcpy(t, data, capacity * sizeof(T));
-            delete[] data;
-            data = t;
-            capacity = newCapacity;
-        }
-        data[pos] = t;
-        pos++;
-    }
-    
-    T pop()
-    {
-        if(pos == 0)
-        {
-            throw Exception("pop on empty stack");
-        }
-        return data[--pos]; 
-    }
-    
-    T peek()
-    {
-        if(pos == 0)
-        {
-            throw Exception("peek on empty stack");
-        }
-        return data[pos - 1];
-    }
-private:
-    int capacity;
-    int pos;
-    T* data;
-};
-
-#endif
-

+ 22 - 0
snuviscript/code/ISnuviLogger.h

@@ -0,0 +1,22 @@
+#ifndef ISNUVILOGGER_H
+#define ISNUVILOGGER_H
+
+#include <string>
+#include <exception>
+#include "Script.h"
+
+using namespace std;
+
+class ISnuviLogger
+{
+    virtual void print(
+            const string* message = nullptr, 
+            exception* ex = nullptr, 
+            const string* function = nullptr, 
+            const string* scriptname = nullptr, 
+            const Script* sc = nullptr,
+            int line = -1) = 0;
+};
+
+#endif
+

+ 14 - 0
snuviscript/code/Script.cpp

@@ -0,0 +1,14 @@
+#include "Script.h"
+
+Script::Script()
+{
+}
+
+Script::Script(const Script& orig)
+{
+}
+
+Script::~Script()
+{
+}
+

+ 15 - 0
snuviscript/code/Script.h

@@ -0,0 +1,15 @@
+#ifndef SCRIPT_H
+#define SCRIPT_H
+
+class Script
+{
+public:
+    Script();
+    Script(const Script& orig);
+    virtual ~Script();
+private:
+
+};
+
+#endif
+

+ 11 - 0
snuviscript/exceptions/PreScriptException.cpp

@@ -0,0 +1,11 @@
+#include "PreScriptException.h"
+
+PreScriptException::PreScriptException(string message, int line) : message(message), line(line)
+{
+}
+
+/*const char* PreScriptException::what() const
+{
+    return message;
+}*/
+

+ 22 - 0
snuviscript/exceptions/PreScriptException.h

@@ -0,0 +1,22 @@
+#ifndef PRESCRIPTEXCEPTION_H
+#define PRESCRIPTEXCEPTION_H
+
+#include <exception>
+#include <string>
+
+using namespace std;
+
+class PreScriptException : public exception
+{
+public:
+    PreScriptException(string message, int line);
+
+    //const char* what() const override;
+    
+private:
+    string message;
+    int line;
+};
+
+#endif
+

+ 159 - 0
snuviscript/test/Test.cpp

@@ -0,0 +1,159 @@
+#include "Test.h"
+#include <dirent.h>
+#include <cstring>
+#include "../tokenizer/Tokenizer.h"
+
+int Test::done = 0;
+int Test::tests = 0;
+TestLogger Test::logger;
+
+void Test::test()
+{
+    testTokenizer();
+    //testCompiler();
+    //testOutput();
+}
+
+void Test::testTokenizer()
+{
+    done = 0;
+    tests = 0;
+    forEachFile("test", ".tout", [](const string& input, const string& output)
+    {
+        tests++;
+        
+        vector<unique_ptr<istream>> streams;
+        streams.push_back(unique_ptr<istream>(new fstream));
+        ((fstream*) streams[0].get())->open(input);
+        
+        fstream oStream;
+        oStream.open(output);
+        
+        if(!streams[0]->good() || !oStream.good())
+        {
+            return;
+        }
+        
+        Tokenizer tokenizer;
+        vector<unique_ptr<Token>> tokens;
+        
+        try
+        {
+            tokenizer.tokenize(tokens, streams);
+        }
+        catch(exception& ex)
+        {
+            return;
+        }
+        
+        logger.reset();
+        for(unsigned int i = 0; i < tokens.size(); i++)
+        {
+            string s = tokens[i]->toString();
+            logger.print(&s);
+        }
+        
+        if(logger.check(input, oStream))
+        {
+            done++;
+        }
+    });
+    cout << done << " / " << tests << " tokenizer tests succeeded" << endl;
+}
+
+void Test::testCompiler()
+{
+    /*
+     done = 0;
+        tests = 0; 
+        final Compiler c = new Compiler();
+        forEachFile(new File("./test"), ".cout", (inFile, checkFile) -> 
+        {
+            tests++;
+            try
+            {
+                try(FileInputStream in = new FileInputStream(inFile))
+                {
+                    Tokenizer tokenizer = new Tokenizer();
+                    LOGGER.reset();
+                    Instruction[] instr = c.compile(tokenizer.tokenize(in), 
+                            new HashMap<>(), new HashMap<>(), new HashMap<>(), 
+                            new HashMap<>());
+                    for(Instruction i : instr)
+                    {
+                        LOGGER.print(i.toString(), null, null, null, null, -1);
+                    }
+                    if(LOGGER.check(checkFile))
+                    {
+                        done++;
+                    }
+                }
+            }
+            catch(Exception ex)
+            {
+                System.out.println("_________________________________________");
+                System.out.println(inFile + " failed:");
+                System.out.println(ex.getMessage());
+                ex.printStackTrace();
+            }
+        });
+        System.out.println(String.format("%d / %d compiler tests succeeded", done, tests));
+     
+     */
+}
+
+void Test::testOutput()
+{
+    /*
+     
+     done = 0;
+        tests = 0;  
+        forEachFile(new File("./test"), ".out", (inFile, checkFile) -> 
+        {
+            tests++;
+                
+            LOGGER.reset();
+            
+            Script sc = new Script(PARSER, null, null, inFile.getName(), inFile.getPath());
+            sc.run();
+
+            if(LOGGER.check(checkFile))
+            {
+                done++;
+            }
+        });
+        System.out.println(String.format("%d / %d output tests succeeded", done, tests));
+     
+     */
+}
+
+void Test::forEachFile(const string& path, const string& ending, void (*f) (const string&, const string&))
+{
+    DIR* dir;
+    dir = opendir(path.c_str());
+    struct dirent* entry = nullptr;
+    if(dir != nullptr)
+    {
+        while((entry = readdir(dir)) != nullptr)
+        {
+            if(strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
+            {
+                continue;
+            }
+            if(entry->d_type == DT_DIR) // Folder
+            {
+                forEachFile(path + "/" + entry->d_name, ending, f);
+            }
+            else if(entry->d_type == DT_REG) // File
+            {
+                if(strchr(entry->d_name, '.') == nullptr)
+                {
+                    string pathInputFile = path + "/" + entry->d_name;
+                    string pathOutputFile = pathInputFile + ending;
+                    f(pathInputFile, pathOutputFile);
+                }
+            }
+        }
+        closedir(dir);
+    }
+}

+ 26 - 0
snuviscript/test/Test.h

@@ -0,0 +1,26 @@
+#ifndef TEST_H
+#define TEST_H
+
+#include <iostream>
+#include "TestLogger.h"
+
+using namespace std;
+
+class Test
+{
+public:
+    static void test();
+private:
+    static int done;
+    static int tests;
+    static TestLogger logger;
+    
+    static void testTokenizer();
+    static void testCompiler();
+    static void testOutput();
+    
+    static void forEachFile(const string& path, const string& ending, void (*f) (const string&, const string&));
+};
+
+#endif
+

+ 72 - 0
snuviscript/test/TestLogger.cpp

@@ -0,0 +1,72 @@
+#include "TestLogger.h"
+
+TestLogger::TestLogger()
+{
+}
+
+void TestLogger::print(const string* message, exception* ex, const string* function, const string* scriptname, const Script* sc, int line)
+{
+    if(ex == nullptr)
+    {
+        if(message != nullptr)
+        {
+            output.push_back(*message);
+        }
+    }
+    else
+    {
+        output.push_back(ex->what());
+    }
+}
+
+void TestLogger::reset()
+{
+    output.clear();
+}
+
+bool TestLogger::check(const string& name, fstream& check)
+{
+    vector<string> file;
+    
+    while(!check.eof())
+    {
+        char buffer[256];
+        check.getline(buffer, 256);
+        if(buffer[0] != '\0')
+        {
+            file.push_back(buffer);
+        }
+    }
+    
+    if(file.size() != output.size())
+    {
+        printNoMatch(name, file);
+        return false;
+    }
+    for(unsigned int i = 0; i < file.size(); i++)
+    {
+        if(file[i] != output[i])
+        {
+            printNoMatch(name, file);
+            return false;
+        }
+    }
+    
+    return true;
+}
+
+void TestLogger::printNoMatch(const string& name, vector<string>& file)
+{
+    cout << "error checking " << name << endl;
+    cout << "Expected ---------------------------------------------" << endl;
+    for(unsigned int i = 0; i < file.size(); i++)
+    {
+        cout << file[i] << endl;
+    }
+    cout << "Actual -----------------------------------------------" << endl;
+    for(unsigned int i = 0; i < output.size(); i++)
+    {
+        cout << output[i] << endl;
+    }
+    cout << "------------------------------------------------------" << endl;
+}

+ 32 - 0
snuviscript/test/TestLogger.h

@@ -0,0 +1,32 @@
+#ifndef TESTLOGGER_H
+#define TESTLOGGER_H
+
+#include "../code/ISnuviLogger.h"
+#include <iostream>
+#include <fstream>
+#include <vector>
+
+using namespace std;
+
+class TestLogger : public ISnuviLogger
+{
+public:
+    TestLogger();
+    void print(
+            const string* message = nullptr, 
+            exception* ex = nullptr, 
+            const string* function = nullptr, 
+            const string* scriptname = nullptr, 
+            const Script* sc = nullptr,
+            int line = -1) override;
+    void reset();
+    bool check(const string& name, fstream& check);
+
+private:
+    void printNoMatch(const string& name, vector<string>& file);
+    
+    vector<string> output;
+};
+
+#endif
+

+ 28 - 0
snuviscript/tokenizer/DoubleToken.cpp

@@ -0,0 +1,28 @@
+#include "DoubleToken.h"
+
+DoubleToken::DoubleToken(TokenType tt, int line, double data) : Token(tt, line), data(data)
+{
+}
+
+DoubleToken::~DoubleToken()
+{
+}
+
+const void* DoubleToken::getData() const
+{
+    return &data;
+}
+
+string DoubleToken::getDataString() const
+{
+    if(data == (long) data)
+    {
+        char buffer[20];
+        snprintf(buffer, 20, "%lg.0", data);
+        return buffer;
+    }
+    char buffer[20];
+    snprintf(buffer, 20, "%lg", data);
+    return buffer;
+}
+

+ 20 - 0
snuviscript/tokenizer/DoubleToken.h

@@ -0,0 +1,20 @@
+#ifndef DOUBLETOKEN_H
+#define DOUBLETOKEN_H
+
+#include "Token.h"
+
+class DoubleToken : public Token
+{
+public:
+    DoubleToken(TokenType tt, int line, double data);
+    ~DoubleToken();
+    
+    const void* getData() const override;
+    string getDataString() const override;
+    
+private:
+    double data;
+};
+
+#endif
+

+ 19 - 0
snuviscript/tokenizer/StringToken.cpp

@@ -0,0 +1,19 @@
+#include "StringToken.h"
+
+StringToken::StringToken(TokenType tt, int line, string data) : Token(tt, line), data(data)
+{
+}
+
+StringToken::~StringToken()
+{
+}
+
+const void* StringToken::getData() const
+{
+    return &data;
+}
+
+string StringToken::getDataString() const
+{
+    return "\"" + data + "\"";
+}

+ 20 - 0
snuviscript/tokenizer/StringToken.h

@@ -0,0 +1,20 @@
+#ifndef STRINGTOKEN_H
+#define STRINGTOKEN_H
+
+#include "Token.h"
+
+class StringToken : public Token
+{
+public:
+    StringToken(TokenType tt, int line, string data);
+    virtual ~StringToken();
+    
+    const void* getData() const override;
+    string getDataString() const override;
+    
+private:
+    string data;
+};
+
+#endif
+

+ 46 - 0
snuviscript/tokenizer/Token.cpp

@@ -0,0 +1,46 @@
+#include "Token.h"
+#include <sstream>
+
+Token::Token(TokenType tt, int line) : type(tt), line(line)
+{
+}
+
+Token::~Token()
+{
+}
+
+TokenType Token::getType() const
+{
+    return type;
+}
+
+int Token::getLine() const
+{
+    return line;
+}
+
+const void* Token::getData() const
+{
+    return nullptr;
+}
+
+string Token::getDataString() const
+{
+    return "";
+}
+
+string Token::toString() const
+{
+    stringstream ss;
+    ss << '(';
+    ss << line;
+    ss << ", ";
+    ss << TokenTypeUtils::getEnumName(type);
+    if(getData() != nullptr)
+    {
+        ss << ", ";
+        ss << getDataString();
+    }
+    ss << ')';
+    return ss.str();
+}

+ 26 - 0
snuviscript/tokenizer/Token.h

@@ -0,0 +1,26 @@
+#ifndef TOKEN_H
+#define TOKEN_H
+
+#include "TokenType.h"
+#include <memory>
+#include "../base/Object.h"
+
+class Token
+{
+public:
+    Token(TokenType tt, int line);
+    virtual ~Token();
+    
+    TokenType getType() const;
+    int getLine() const;
+    virtual const void* getData() const;
+    virtual string getDataString() const;
+    virtual string toString() const;
+    
+private:
+    TokenType type;
+    int line;
+};
+
+#endif
+

+ 137 - 0
snuviscript/tokenizer/TokenType.cpp

@@ -0,0 +1,137 @@
+#include "TokenType.h"
+
+string TokenTypeUtils::getName(TokenType tt)
+{
+    switch(tt)
+    {
+        case NUMBER: return "number";
+        case STRING: return "string";
+        case LITERAL: return "literal";
+        case LABEL: return "label";
+        case TRUE: return "true";
+        case FALSE: return "false";
+        case NULL_TOKEN: return "null";
+        case OPEN_BRACKET: return "(";
+        case CLOSE_BRACKET: return ")";
+        case OPEN_SQUARE_BRACKET: return "[";
+        case CLOSE_SQUARE_BRACKET: return "]";
+        case OPEN_CURVED_BRACKET: return "{";
+        case CLOSE_CURVED_BRACKET: return "}";
+        case SEMICOLON: return ";";
+        case COMMA: return ",";
+        case INC: return "++";
+        case DEC: return "--";
+        case INVERT: return "!";
+        case BIT_INVERT: return "~";
+        case MUL: return "*";
+        case DIV: return "/";
+        case MOD: return "%";
+        case ADD: return "+";
+        case SUB: return "-";
+        case ADD_SET: return "+=";
+        case SUB_SET: return "-=";
+        case MUL_SET: return "*=";
+        case DIV_SET: return "/=";
+        case MOD_SET: return "%=";
+        case LEFT_SHIFT: return "<<";
+        case RIGHT_SHIFT: return ">>";
+        case LEFT_SHIFT_SET: return "<<=";
+        case RIGHT_SHIFT_SET: return ">>=";
+        case BIT_AND_SET: return "&=";
+        case BIT_XOR_SET: return "^=";
+        case BIT_OR_SET: return "|=";
+        case LESS: return "<";
+        case LESS_EQUAL: return "<=";
+        case GREATER: return ">";
+        case GREATER_EQUAL: return ">=";
+        case EQUAL: return "==";
+        case NOT_EQUAL: return "!=";
+        case BIT_AND: return "&";
+        case BIT_XOR: return "^";
+        case BIT_OR: return "|";
+        case AND: return "&&";
+        case OR: return "||";
+        case SET: return "=";
+        case IF: return "if";
+        case ELSE: return "else";
+        case ELSEIF: return "else if";
+        case WHILE: return "while";
+        case TRY: return "try";
+        case CATCH: return "catch";
+        case FOR: return "for";
+        case FUNCTION: return "function";
+        case BREAK: return "break";
+        case CONTINUE: return "continue";
+        case RETURN: return "return";
+        case EOF_TOKEN: return "end of file";
+    }
+    return "Unknown TokenType";
+}
+
+string TokenTypeUtils::getEnumName(TokenType tt)
+{
+    switch(tt)
+    {
+        case NUMBER: return "NUMBER";
+        case STRING: return "STRING";
+        case LITERAL: return "LITERAL";
+        case LABEL: return "LABEL";
+        case TRUE: return "TRUE";
+        case FALSE: return "FALSE";
+        case NULL_TOKEN: return "NULL_TOKEN";
+        case OPEN_BRACKET: return "OPEN_BRACKET";
+        case CLOSE_BRACKET: return "CLOSE_BRACKET";
+        case OPEN_SQUARE_BRACKET: return "OPEN_SQUARE_BRACKET";
+        case CLOSE_SQUARE_BRACKET: return "CLOSE_SQUARE_BRACKET";
+        case OPEN_CURVED_BRACKET: return "OPEN_CURVED_BRACKET";
+        case CLOSE_CURVED_BRACKET: return "CLOSE_CURVED_BRACKET";
+        case SEMICOLON: return "SEMICOLON";
+        case COMMA: return "COMMA";
+        case INC: return "INC";
+        case DEC: return "DEC";
+        case INVERT: return "INVERT";
+        case BIT_INVERT: return "BIT_INVERT";
+        case MUL: return "MUL";
+        case DIV: return "DIV";
+        case MOD: return "MOD";
+        case ADD: return "ADD";
+        case SUB: return "SUB";
+        case ADD_SET: return "ADD_SET";
+        case SUB_SET: return "SUB_SET";
+        case MUL_SET: return "MUL_SET";
+        case DIV_SET: return "DIV_SET";
+        case MOD_SET: return "MOD_SET";
+        case LEFT_SHIFT: return "LEFT_SHIFT";
+        case RIGHT_SHIFT: return "RIGHT_SHIFT";
+        case LEFT_SHIFT_SET: return "LEFT_SHIFT_SET";
+        case RIGHT_SHIFT_SET: return "RIGHT_SHIFT_SET";
+        case BIT_AND_SET: return "BIT_AND_SET";
+        case BIT_XOR_SET: return "BIT_XOR_SET";
+        case BIT_OR_SET: return "BIT_OR_SET";
+        case LESS: return "LESS";
+        case LESS_EQUAL: return "LESS_EQUAL";
+        case GREATER: return "GREATER";
+        case GREATER_EQUAL: return "GREATER_EQUAL";
+        case EQUAL: return "EQUAL";
+        case NOT_EQUAL: return "NOT_EQUAL";
+        case BIT_AND: return "BIT_AND";
+        case BIT_XOR: return "BIT_XOR";
+        case BIT_OR: return "BIT_OR";
+        case AND: return "AND";
+        case OR: return "OR";
+        case SET: return "SET";
+        case IF: return "IF";
+        case ELSE: return "ELSE";
+        case ELSEIF: return "ELSEIF";
+        case WHILE: return "WHILE";
+        case TRY: return "TRY";
+        case CATCH: return "CATCH";
+        case FOR: return "FOR";
+        case FUNCTION: return "FUNCTION";
+        case BREAK: return "BREAK";
+        case CONTINUE: return "CONTINUE";
+        case RETURN: return "RETURN";
+        case EOF_TOKEN: return "EOF";
+    }
+    return "UNKNOWN";
+}

+ 46 - 0
snuviscript/tokenizer/TokenType.h

@@ -0,0 +1,46 @@
+#ifndef TOKENTYPE_H
+#define TOKENTYPE_H
+
+#include <iostream>
+
+using namespace std;
+
+enum TokenType
+{
+    NUMBER, STRING, LITERAL, LABEL, 
+    TRUE, FALSE, NULL_TOKEN,
+    
+    OPEN_BRACKET, CLOSE_BRACKET, 
+    OPEN_SQUARE_BRACKET, CLOSE_SQUARE_BRACKET, 
+    OPEN_CURVED_BRACKET, CLOSE_CURVED_BRACKET, 
+    
+    SEMICOLON, COMMA, 
+    
+    INC, DEC, 
+    
+    INVERT, BIT_INVERT, 
+    
+    MUL, DIV, MOD, ADD, SUB, 
+    ADD_SET, SUB_SET, MUL_SET, DIV_SET, MOD_SET, 
+    
+    LEFT_SHIFT, RIGHT_SHIFT, 
+    LEFT_SHIFT_SET, RIGHT_SHIFT_SET, BIT_AND_SET, BIT_XOR_SET, BIT_OR_SET,
+    
+    LESS, LESS_EQUAL, GREATER, GREATER_EQUAL, EQUAL, NOT_EQUAL, 
+    BIT_AND, BIT_XOR, BIT_OR, 
+    AND, OR, SET,
+    
+    IF, ELSE, ELSEIF, WHILE, TRY, 
+    CATCH, FOR, FUNCTION, BREAK, 
+    CONTINUE, RETURN,
+    
+    EOF_TOKEN
+};
+
+namespace TokenTypeUtils
+{
+    string getName(TokenType tt);
+    string getEnumName(TokenType tt);
+}
+
+#endif

+ 349 - 0
snuviscript/tokenizer/Tokenizer.cpp

@@ -0,0 +1,349 @@
+#include "Tokenizer.h"
+#include "../exceptions/PreScriptException.h"
+#include <ctype.h>
+#include <sstream>
+
+Tokenizer::Tokenizer()
+{
+}
+
+void Tokenizer::tokenize(vector<unique_ptr<Token>>& tokens, vector<unique_ptr<istream>>& streams)
+{
+    Tokenizer::tokens = &tokens;
+    Tokenizer::streams = &streams;
+    
+    for(streamIndex = 0; streamIndex < streams.size(); streamIndex++)
+    {
+        buffer = -1;
+        line = 1;
+
+        int c;
+        while((c = next()) != -1)
+        {
+            handleChar(c);
+        }
+    }
+    add(TokenType::EOF_TOKEN);
+}
+
+int Tokenizer::next()
+{
+    if(buffer != -1)
+    {
+        int r = buffer;
+        buffer = -1;
+        return r;
+    }
+    istream& in = *(*streams)[streamIndex].get();
+    if(!in.good())
+    {
+        return -1;
+    }
+    
+    int data = in.get();
+    if((data & 0x80) != 0 && data != -1) // special char
+    {
+        if((data & 0x40) != 0) // this should always be true
+        {
+            if((data & 0x20) != 0) // 3 byte unicode
+            {
+                int a = in.get();
+                int b = in.get();
+                data = ((data & 0xFF) << 16) | ((a & 0xFF) << 8) | (b & 0xFF);
+            }
+            else // 2 byte unicode
+            {
+                data = ((data & 0xFF) << 8) | (in.get() & 0xFF);
+            }
+        }
+        else
+        {
+            // should not happen as unicode starts with 11
+        }
+    }
+    return data;
+}
+
+int Tokenizer::peek()
+{
+    if(buffer == -1)
+    {
+        buffer = next();
+        return buffer;
+    }
+    return buffer;
+}
+
+bool Tokenizer::next(char c)
+{
+    if(peek() == c)
+    {
+        next();
+        return true;
+    }
+    return false;
+}
+
+void Tokenizer::add(TokenType type)
+{
+    tokens->push_back(unique_ptr<Token>(new Token(type, line)));
+}
+
+void Tokenizer::add(TokenType type, double data)
+{
+    tokens->push_back(unique_ptr<Token>(new DoubleToken(type, line, data)));
+}
+
+void Tokenizer::add(TokenType type, string data)
+{
+    tokens->push_back(unique_ptr<Token>(new StringToken(type, line, data)));
+}
+
+void Tokenizer::add(char c, TokenType t1, TokenType t2, TokenType t3, TokenType t4)
+{
+    int peeked = peek();
+    if(peeked == c)
+    {
+        next();
+        if(peek() == '=')
+        {
+            next();
+            add(t1);
+        }
+        else
+        {
+            add(t2);
+        }
+    }
+    else if(peeked == '=')
+    {
+        next();
+        add(t3);
+    }
+    else
+    {
+        add(t4);
+    }
+}
+
+void Tokenizer::handleChar(int c)
+{
+    if(isLetter(c) || c == '_' || c == '.')
+    {
+        handleLiteral(c, TokenType::LITERAL);
+    }
+    else if(isDigit(c))
+    {
+        handleNumber(c);
+    }
+    else
+    {
+        handleSpecial(c);
+    }
+}
+
+void Tokenizer::handleLiteral(int c, TokenType type)
+{
+    stringstream ss;
+    ss << (char) c;
+
+    while(true)
+    {
+        int data = peek();
+        if(!isValidNamePart(data))
+        {
+            break;
+        }
+        ss << (char) data;
+        next();
+    }
+
+    string s = ss.str();
+    if(s == "if") { add(TokenType::IF); }
+    else if(s == "if") { add(TokenType::IF); }
+    else if(s == "else") { add(TokenType::ELSE); }
+    else if(s == "elseif") { add(TokenType::ELSEIF); }
+    else if(s == "while") { add(TokenType::WHILE); }
+    else if(s == "try") { add(TokenType::TRY); }
+    else if(s == "catch") { add(TokenType::CATCH); }
+    else if(s == "for") { add(TokenType::FOR); }
+    else if(s == "function") { add(TokenType::FUNCTION); }
+    else if(s == "break") { add(TokenType::BREAK); }
+    else if(s == "continue") { add(TokenType::CONTINUE); }
+    else if(s == "return") { add(TokenType::RETURN); }
+    else if(s == "true") { add(TokenType::TRUE); }
+    else if(s == "false") { add(TokenType::FALSE); }
+    else if(s == "null") { add(TokenType::NULL_TOKEN); }
+    else { add(type, s); };
+}
+
+void Tokenizer::handleNumber(int c)
+{
+    double d = c - '0';
+
+    while(true)
+    {
+        int data = peek();
+        if(!isDigit(data))
+        {
+            if(data == '.')
+            {
+                next();
+                double factor = 10;
+                while(true)
+                {
+                    int data = peek();
+                    if(!isDigit(data))
+                    {
+                        break;
+                    }
+                    d += (data - '0') / factor;
+                    factor *= 10;
+                    next();
+                }
+            }
+            break;
+        }
+        d = (d * 10) + (data - '0');
+        next();
+    }
+
+    add(NUMBER, d);
+}
+
+void Tokenizer::handleSpecial(int c)
+{
+    switch(c)
+    {
+        case ' ':
+        case '\t':
+        case '\r': break;
+        case '\n': line++; break;
+        case '"': handleString(); break;
+        case '(': add(OPEN_BRACKET); break;
+        case ')': add(CLOSE_BRACKET); break;
+        case '[': add(OPEN_SQUARE_BRACKET); break;
+        case ']': add(CLOSE_SQUARE_BRACKET); break;
+        case '{': add(OPEN_CURVED_BRACKET); break;
+        case '}': add(CLOSE_CURVED_BRACKET); break;
+        case '$': handleLiteral(c, LITERAL); break;
+        case '@': handleLiteral(c, LABEL); break;
+        case ';': add(SEMICOLON); break;
+        case ',': add(COMMA); break;
+        case '~': add(BIT_INVERT); break;
+        case '+': add(next('=') ? ADD_SET : (next('+') ? INC : ADD)); break;
+        case '-': add(next('=') ? SUB_SET : (next('-') ? DEC : SUB)); break;
+        case '!': add(next('=') ? NOT_EQUAL : INVERT); break;
+        case '=': add(next('=') ? EQUAL : SET); break;
+        case '*': add(next('=') ? MUL_SET : MUL); break;
+        case '/': handleSlash(); break;
+        case '%': add(next('=') ? MOD_SET : MOD); break;
+        case '&': add(next('=') ? BIT_AND_SET : (next('&') ? AND : BIT_AND)); break; 
+        case '|': add(next('=') ? BIT_OR_SET : (next('|') ? OR : BIT_OR)); break;
+        case '^': add(next('=') ? BIT_XOR_SET : BIT_XOR); break;
+        case '<': add('<', LEFT_SHIFT_SET, LEFT_SHIFT, LESS_EQUAL, LESS); break;
+        case '>': add('>', RIGHT_SHIFT_SET, RIGHT_SHIFT, GREATER_EQUAL, GREATER); break;
+        default: throw PreScriptException("unknown token " + c, line);
+    }
+}
+
+void Tokenizer::handleString()
+{
+    stringstream ss;
+    while(true)
+    {
+        int data = next();
+        if(data == '"')
+        {
+            add(STRING, ss.str());
+            break;
+        }
+        if(data == '\n')
+        {
+            line++;
+        }
+        if(data > 0xFFFF)
+        {
+            ss << (char) ((data & 0xFF0000) >> 16);
+            ss << (char) ((data & 0xFF00) >> 8);
+            ss << (char) (data & 0xFF);
+        }
+        else if(data > 0xFF)
+        {
+            ss << (char) ((data & 0xFF00) >> 8);
+            ss << (char) (data & 0xFF);
+        }
+        else
+        {
+            ss << (char) data;
+        }
+    }
+}
+
+void Tokenizer::handleSlash()
+{
+    switch(peek())
+    {
+        case '/': 
+            next();
+            handleOneLineComment();
+            break;
+        case '*': 
+            next();
+            handleMultiLineComment();
+            break;
+        case '=': 
+            next();
+            add(DIV_SET);
+            break;
+        default:
+            add(DIV);
+    }
+}
+
+void Tokenizer::handleOneLineComment()
+{
+    while(true)
+    {
+        int data = next();
+        if(data == -1 || data == '\n')
+        {
+            line++;
+            break;
+        }
+    }
+}
+
+void Tokenizer::handleMultiLineComment()
+{
+    int first;
+    int sec = -1;
+    while(true)
+    {
+        first = sec;
+        sec = next();
+        if(sec == -1 || (first == '*' && sec == '/'))
+        {
+            break;
+        }
+        if(sec == '\n')
+        {
+            line++;
+        }
+    }
+}
+
+bool Tokenizer::isLetter(int c)
+{
+    return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
+}
+
+bool Tokenizer::isDigit(int c)
+{
+    return c >= '0' && c <= '9';
+}
+
+bool Tokenizer::isValidNamePart(int c)
+{
+    return isLetter(c) || isDigit(c) || c == '.' || c == '_';
+}

+ 48 - 0
snuviscript/tokenizer/Tokenizer.h

@@ -0,0 +1,48 @@
+#ifndef TOKENIZER_H
+#define TOKENIZER_H
+
+#include "Token.h"
+#include "DoubleToken.h"
+#include "StringToken.h"
+#include <vector>
+#include <memory>
+
+using namespace std;
+
+class Tokenizer
+{
+public:
+    Tokenizer();
+    
+    void tokenize(vector<unique_ptr<Token>>& tokens, vector<unique_ptr<istream>>& streams);
+    
+private:
+    int next();
+    int peek();
+    bool next(char c);
+    void add(TokenType type);
+    void add(TokenType type, double data);
+    void add(TokenType type, string data);
+    void add(char c, TokenType t1, TokenType t2, TokenType t3, TokenType t4);
+    void handleChar(int c);
+    void handleLiteral(int c, TokenType type);
+    void handleNumber(int c);
+    void handleSpecial(int c);
+    void handleString();
+    void handleSlash();
+    void handleOneLineComment();
+    void handleMultiLineComment();
+    
+    bool isLetter(int c);
+    bool isDigit(int c);
+    bool isValidNamePart(int c);
+    
+    int buffer;
+    unsigned int line;
+    vector<unique_ptr<Token>>* tokens;
+    unsigned int streamIndex;
+    vector<unique_ptr<istream>>* streams;
+};
+
+#endif
+

+ 10 - 0
test/arrays/array_dim1

@@ -0,0 +1,10 @@
+a = array.new(3);
+for(i = 0; i < array.length(a); i++)
+{
+    a[i] = i;
+}
+for(i = 0; i < array.length(a); i++)
+{
+    print(a[i]);
+}
+

+ 37 - 0
test/arrays/array_dim1.cout

@@ -0,0 +1,37 @@
+push a
+push 3
+use array.new(1)
+use =(2)
+push i
+push 0
+use =(2)
+push i
+push a
+use array.getsize(1)
+use <(2)
+goto(14)
+push i
+use p++(1)
+goto(6)
+for(20)
+push i
+push a[]
+push i
+use =(2)
+goto(11)
+push i
+push 0
+use =(2)
+push i
+push a
+use array.getsize(1)
+use <(2)
+goto(31)
+push i
+use p++(1)
+goto(23)
+for(36)
+push i
+push a[]
+use print(1)
+goto(28)

+ 3 - 0
test/arrays/array_dim1.out

@@ -0,0 +1,3 @@
+0.0
+1.0
+2.0

+ 59 - 0
test/arrays/array_dim1.tout

@@ -0,0 +1,59 @@
+(1, LITERAL, "a")
+(1, SET)
+(1, LITERAL, "array.new")
+(1, OPEN_BRACKET)
+(1, NUMBER, 3.0)
+(1, CLOSE_BRACKET)
+(1, SEMICOLON)
+(2, FOR)
+(2, OPEN_BRACKET)
+(2, LITERAL, "i")
+(2, SET)
+(2, NUMBER, 0.0)
+(2, SEMICOLON)
+(2, LITERAL, "i")
+(2, LESS)
+(2, LITERAL, "array.length")
+(2, OPEN_BRACKET)
+(2, LITERAL, "a")
+(2, CLOSE_BRACKET)
+(2, SEMICOLON)
+(2, LITERAL, "i")
+(2, INC)
+(2, CLOSE_BRACKET)
+(3, OPEN_CURVED_BRACKET)
+(4, LITERAL, "a")
+(4, OPEN_SQUARE_BRACKET)
+(4, LITERAL, "i")
+(4, CLOSE_SQUARE_BRACKET)
+(4, SET)
+(4, LITERAL, "i")
+(4, SEMICOLON)
+(5, CLOSE_CURVED_BRACKET)
+(6, FOR)
+(6, OPEN_BRACKET)
+(6, LITERAL, "i")
+(6, SET)
+(6, NUMBER, 0.0)
+(6, SEMICOLON)
+(6, LITERAL, "i")
+(6, LESS)
+(6, LITERAL, "array.length")
+(6, OPEN_BRACKET)
+(6, LITERAL, "a")
+(6, CLOSE_BRACKET)
+(6, SEMICOLON)
+(6, LITERAL, "i")
+(6, INC)
+(6, CLOSE_BRACKET)
+(7, OPEN_CURVED_BRACKET)
+(8, LITERAL, "print")
+(8, OPEN_BRACKET)
+(8, LITERAL, "a")
+(8, OPEN_SQUARE_BRACKET)
+(8, LITERAL, "i")
+(8, CLOSE_SQUARE_BRACKET)
+(8, CLOSE_BRACKET)
+(8, SEMICOLON)
+(9, CLOSE_CURVED_BRACKET)
+(11, EOF)

+ 15 - 0
test/arrays/array_dim2

@@ -0,0 +1,15 @@
+a = array.new(3, 2);
+for(x = 0; x < array.length(a); x++)
+{
+    for(y = 0; y < array.length(a[x]); y++)
+    {
+        a[x, y] = x * 2 + y;
+    }
+}
+for(x = 0; x < array.length(a); x++)
+{
+    for(y = 0; y < array.length(a[x]); y++)
+    {
+        print(a[x, y]);
+    }
+}

+ 72 - 0
test/arrays/array_dim2.cout

@@ -0,0 +1,72 @@
+push a
+push 3
+push 2
+use array.new(2)
+use =(2)
+push x
+push 0
+use =(2)
+push x
+push a
+use array.getsize(1)
+use <(2)
+goto(15)
+push x
+use p++(1)
+goto(7)
+for(40)
+push y
+push 0
+use =(2)
+push y
+push x
+push a[]
+use array.getsize(1)
+use <(2)
+goto(28)
+push y
+use p++(1)
+goto(19)
+for(39)
+push x
+push y
+push a[,]
+push x
+push 2
+use *(2)
+push y
+use +(2)
+use =(2)
+goto(25)
+goto(12)
+push x
+push 0
+use =(2)
+push x
+push a
+use array.getsize(1)
+use <(2)
+goto(51)
+push x
+use p++(1)
+goto(43)
+for(71)
+push y
+push 0
+use =(2)
+push y
+push x
+push a[]
+use array.getsize(1)
+use <(2)
+goto(64)
+push y
+use p++(1)
+goto(55)
+for(70)
+push x
+push y
+push a[,]
+use print(1)
+goto(61)
+goto(48)

+ 6 - 0
test/arrays/array_dim2.out

@@ -0,0 +1,6 @@
+0.0
+1.0
+2.0
+3.0
+4.0
+5.0

+ 111 - 0
test/arrays/array_dim2.tout

@@ -0,0 +1,111 @@
+(1, LITERAL, "a")
+(1, SET)
+(1, LITERAL, "array.new")
+(1, OPEN_BRACKET)
+(1, NUMBER, 3.0)
+(1, COMMA)
+(1, NUMBER, 2.0)
+(1, CLOSE_BRACKET)
+(1, SEMICOLON)
+(2, FOR)
+(2, OPEN_BRACKET)
+(2, LITERAL, "x")
+(2, SET)
+(2, NUMBER, 0.0)
+(2, SEMICOLON)
+(2, LITERAL, "x")
+(2, LESS)
+(2, LITERAL, "array.length")
+(2, OPEN_BRACKET)
+(2, LITERAL, "a")
+(2, CLOSE_BRACKET)
+(2, SEMICOLON)
+(2, LITERAL, "x")
+(2, INC)
+(2, CLOSE_BRACKET)
+(3, OPEN_CURVED_BRACKET)
+(4, FOR)
+(4, OPEN_BRACKET)
+(4, LITERAL, "y")
+(4, SET)
+(4, NUMBER, 0.0)
+(4, SEMICOLON)
+(4, LITERAL, "y")
+(4, LESS)
+(4, LITERAL, "array.length")
+(4, OPEN_BRACKET)
+(4, LITERAL, "a")
+(4, OPEN_SQUARE_BRACKET)
+(4, LITERAL, "x")
+(4, CLOSE_SQUARE_BRACKET)
+(4, CLOSE_BRACKET)
+(4, SEMICOLON)
+(4, LITERAL, "y")
+(4, INC)
+(4, CLOSE_BRACKET)
+(5, OPEN_CURVED_BRACKET)
+(6, LITERAL, "a")
+(6, OPEN_SQUARE_BRACKET)
+(6, LITERAL, "x")
+(6, COMMA)
+(6, LITERAL, "y")
+(6, CLOSE_SQUARE_BRACKET)
+(6, SET)
+(6, LITERAL, "x")
+(6, MUL)
+(6, NUMBER, 2.0)
+(6, ADD)
+(6, LITERAL, "y")
+(6, SEMICOLON)
+(7, CLOSE_CURVED_BRACKET)
+(8, CLOSE_CURVED_BRACKET)
+(9, FOR)
+(9, OPEN_BRACKET)
+(9, LITERAL, "x")
+(9, SET)
+(9, NUMBER, 0.0)
+(9, SEMICOLON)
+(9, LITERAL, "x")
+(9, LESS)
+(9, LITERAL, "array.length")
+(9, OPEN_BRACKET)
+(9, LITERAL, "a")
+(9, CLOSE_BRACKET)
+(9, SEMICOLON)
+(9, LITERAL, "x")
+(9, INC)
+(9, CLOSE_BRACKET)
+(10, OPEN_CURVED_BRACKET)
+(11, FOR)
+(11, OPEN_BRACKET)
+(11, LITERAL, "y")
+(11, SET)
+(11, NUMBER, 0.0)
+(11, SEMICOLON)
+(11, LITERAL, "y")
+(11, LESS)
+(11, LITERAL, "array.length")
+(11, OPEN_BRACKET)
+(11, LITERAL, "a")
+(11, OPEN_SQUARE_BRACKET)
+(11, LITERAL, "x")
+(11, CLOSE_SQUARE_BRACKET)
+(11, CLOSE_BRACKET)
+(11, SEMICOLON)
+(11, LITERAL, "y")
+(11, INC)
+(11, CLOSE_BRACKET)
+(12, OPEN_CURVED_BRACKET)
+(13, LITERAL, "print")
+(13, OPEN_BRACKET)
+(13, LITERAL, "a")
+(13, OPEN_SQUARE_BRACKET)
+(13, LITERAL, "x")
+(13, COMMA)
+(13, LITERAL, "y")
+(13, CLOSE_SQUARE_BRACKET)
+(13, CLOSE_BRACKET)
+(13, SEMICOLON)
+(14, CLOSE_CURVED_BRACKET)
+(15, CLOSE_CURVED_BRACKET)
+(16, EOF)

+ 21 - 0
test/arrays/array_dim3

@@ -0,0 +1,21 @@
+a = array.new(4, 3, 2);
+for(x = 0; x < array.length(a); x++)
+{
+    for(y = 0; y < array.length(a[x]); y++)
+    {
+        for(z = 0; z < array.length(a[x, y]); z++)
+        {
+            a[x, y, z] = x * 3 * 2 + y * 2 + z;
+        }
+    }
+}
+for(x = 0; x < array.length(a); x++)
+{
+    for(y = 0; y < array.length(a[x]); y++)
+    {
+        for(z = 0; z < array.length(a[x, y]); z++)
+        {
+            print(a[x, y, z]);
+        }
+    }
+}

+ 111 - 0
test/arrays/array_dim3.cout

@@ -0,0 +1,111 @@
+push a
+push 4
+push 3
+push 2
+use array.new(3)
+use =(2)
+push x
+push 0
+use =(2)
+push x
+push a
+use array.getsize(1)
+use <(2)
+goto(16)
+push x
+use p++(1)
+goto(8)
+for(63)
+push y
+push 0
+use =(2)
+push y
+push x
+push a[]
+use array.getsize(1)
+use <(2)
+goto(29)
+push y
+use p++(1)
+goto(20)
+for(62)
+push z
+push 0
+use =(2)
+push z
+push x
+push y
+push a[,]
+use array.getsize(1)
+use <(2)
+goto(43)
+push z
+use p++(1)
+goto(33)
+for(61)
+push x
+push y
+push z
+push a[,,]
+push x
+push 3
+use *(2)
+push 2
+use *(2)
+push y
+push 2
+use *(2)
+use +(2)
+push z
+use +(2)
+use =(2)
+goto(40)
+goto(26)
+goto(13)
+push x
+push 0
+use =(2)
+push x
+push a
+use array.getsize(1)
+use <(2)
+goto(74)
+push x
+use p++(1)
+goto(66)
+for(110)
+push y
+push 0
+use =(2)
+push y
+push x
+push a[]
+use array.getsize(1)
+use <(2)
+goto(87)
+push y
+use p++(1)
+goto(78)
+for(109)
+push z
+push 0
+use =(2)
+push z
+push x
+push y
+push a[,]
+use array.getsize(1)
+use <(2)
+goto(101)
+push z
+use p++(1)
+goto(91)
+for(108)
+push x
+push y
+push z
+push a[,,]
+use print(1)
+goto(98)
+goto(84)
+goto(71)

+ 24 - 0
test/arrays/array_dim3.out

@@ -0,0 +1,24 @@
+0.0
+1.0
+2.0
+3.0
+4.0
+5.0
+6.0
+7.0
+8.0
+9.0
+10.0
+11.0
+12.0
+13.0
+14.0
+15.0
+16.0
+17.0
+18.0
+19.0
+20.0
+21.0
+22.0
+23.0

+ 169 - 0
test/arrays/array_dim3.tout

@@ -0,0 +1,169 @@
+(1, LITERAL, "a")
+(1, SET)
+(1, LITERAL, "array.new")
+(1, OPEN_BRACKET)
+(1, NUMBER, 4.0)
+(1, COMMA)
+(1, NUMBER, 3.0)
+(1, COMMA)
+(1, NUMBER, 2.0)
+(1, CLOSE_BRACKET)
+(1, SEMICOLON)
+(2, FOR)
+(2, OPEN_BRACKET)
+(2, LITERAL, "x")
+(2, SET)
+(2, NUMBER, 0.0)
+(2, SEMICOLON)
+(2, LITERAL, "x")
+(2, LESS)
+(2, LITERAL, "array.length")
+(2, OPEN_BRACKET)
+(2, LITERAL, "a")
+(2, CLOSE_BRACKET)
+(2, SEMICOLON)
+(2, LITERAL, "x")
+(2, INC)
+(2, CLOSE_BRACKET)
+(3, OPEN_CURVED_BRACKET)
+(4, FOR)
+(4, OPEN_BRACKET)
+(4, LITERAL, "y")
+(4, SET)
+(4, NUMBER, 0.0)
+(4, SEMICOLON)
+(4, LITERAL, "y")
+(4, LESS)
+(4, LITERAL, "array.length")
+(4, OPEN_BRACKET)
+(4, LITERAL, "a")
+(4, OPEN_SQUARE_BRACKET)
+(4, LITERAL, "x")
+(4, CLOSE_SQUARE_BRACKET)
+(4, CLOSE_BRACKET)
+(4, SEMICOLON)
+(4, LITERAL, "y")
+(4, INC)
+(4, CLOSE_BRACKET)
+(5, OPEN_CURVED_BRACKET)
+(6, FOR)
+(6, OPEN_BRACKET)
+(6, LITERAL, "z")
+(6, SET)
+(6, NUMBER, 0.0)
+(6, SEMICOLON)
+(6, LITERAL, "z")
+(6, LESS)
+(6, LITERAL, "array.length")
+(6, OPEN_BRACKET)
+(6, LITERAL, "a")
+(6, OPEN_SQUARE_BRACKET)
+(6, LITERAL, "x")
+(6, COMMA)
+(6, LITERAL, "y")
+(6, CLOSE_SQUARE_BRACKET)
+(6, CLOSE_BRACKET)
+(6, SEMICOLON)
+(6, LITERAL, "z")
+(6, INC)
+(6, CLOSE_BRACKET)
+(7, OPEN_CURVED_BRACKET)
+(8, LITERAL, "a")
+(8, OPEN_SQUARE_BRACKET)
+(8, LITERAL, "x")
+(8, COMMA)
+(8, LITERAL, "y")
+(8, COMMA)
+(8, LITERAL, "z")
+(8, CLOSE_SQUARE_BRACKET)
+(8, SET)
+(8, LITERAL, "x")
+(8, MUL)
+(8, NUMBER, 3.0)
+(8, MUL)
+(8, NUMBER, 2.0)
+(8, ADD)
+(8, LITERAL, "y")
+(8, MUL)
+(8, NUMBER, 2.0)
+(8, ADD)
+(8, LITERAL, "z")
+(8, SEMICOLON)
+(9, CLOSE_CURVED_BRACKET)
+(10, CLOSE_CURVED_BRACKET)
+(11, CLOSE_CURVED_BRACKET)
+(12, FOR)
+(12, OPEN_BRACKET)
+(12, LITERAL, "x")
+(12, SET)
+(12, NUMBER, 0.0)
+(12, SEMICOLON)
+(12, LITERAL, "x")
+(12, LESS)
+(12, LITERAL, "array.length")
+(12, OPEN_BRACKET)
+(12, LITERAL, "a")
+(12, CLOSE_BRACKET)
+(12, SEMICOLON)
+(12, LITERAL, "x")
+(12, INC)
+(12, CLOSE_BRACKET)
+(13, OPEN_CURVED_BRACKET)
+(14, FOR)
+(14, OPEN_BRACKET)
+(14, LITERAL, "y")
+(14, SET)
+(14, NUMBER, 0.0)
+(14, SEMICOLON)
+(14, LITERAL, "y")
+(14, LESS)
+(14, LITERAL, "array.length")
+(14, OPEN_BRACKET)
+(14, LITERAL, "a")
+(14, OPEN_SQUARE_BRACKET)
+(14, LITERAL, "x")
+(14, CLOSE_SQUARE_BRACKET)
+(14, CLOSE_BRACKET)
+(14, SEMICOLON)
+(14, LITERAL, "y")
+(14, INC)
+(14, CLOSE_BRACKET)
+(15, OPEN_CURVED_BRACKET)
+(16, FOR)
+(16, OPEN_BRACKET)
+(16, LITERAL, "z")
+(16, SET)
+(16, NUMBER, 0.0)
+(16, SEMICOLON)
+(16, LITERAL, "z")
+(16, LESS)
+(16, LITERAL, "array.length")
+(16, OPEN_BRACKET)
+(16, LITERAL, "a")
+(16, OPEN_SQUARE_BRACKET)
+(16, LITERAL, "x")
+(16, COMMA)
+(16, LITERAL, "y")
+(16, CLOSE_SQUARE_BRACKET)
+(16, CLOSE_BRACKET)
+(16, SEMICOLON)
+(16, LITERAL, "z")
+(16, INC)
+(16, CLOSE_BRACKET)
+(17, OPEN_CURVED_BRACKET)
+(18, LITERAL, "print")
+(18, OPEN_BRACKET)
+(18, LITERAL, "a")
+(18, OPEN_SQUARE_BRACKET)
+(18, LITERAL, "x")
+(18, COMMA)
+(18, LITERAL, "y")
+(18, COMMA)
+(18, LITERAL, "z")
+(18, CLOSE_SQUARE_BRACKET)
+(18, CLOSE_BRACKET)
+(18, SEMICOLON)
+(19, CLOSE_CURVED_BRACKET)
+(20, CLOSE_CURVED_BRACKET)
+(21, CLOSE_CURVED_BRACKET)
+(22, EOF)

+ 8 - 0
test/basic/gosub

@@ -0,0 +1,8 @@
+print("start");
+gosub(@sub);
+gosub("sub");
+term();
+
+@sub
+print("hi");
+return;

+ 10 - 0
test/basic/gosub.cout

@@ -0,0 +1,10 @@
+push "start"
+use print(1)
+push "sub"
+use gosub(1)
+push "sub"
+use gosub(1)
+use term(0)
+push "hi"
+use print(1)
+return(0)

+ 3 - 0
test/basic/gosub.out

@@ -0,0 +1,3 @@
+start
+hi
+hi

+ 28 - 0
test/basic/gosub.tout

@@ -0,0 +1,28 @@
+(1, LITERAL, "print")
+(1, OPEN_BRACKET)
+(1, STRING, "start")
+(1, CLOSE_BRACKET)
+(1, SEMICOLON)
+(2, LITERAL, "gosub")
+(2, OPEN_BRACKET)
+(2, LABEL, "@sub")
+(2, CLOSE_BRACKET)
+(2, SEMICOLON)
+(3, LITERAL, "gosub")
+(3, OPEN_BRACKET)
+(3, STRING, "sub")
+(3, CLOSE_BRACKET)
+(3, SEMICOLON)
+(4, LITERAL, "term")
+(4, OPEN_BRACKET)
+(4, CLOSE_BRACKET)
+(4, SEMICOLON)
+(6, LABEL, "@sub")
+(7, LITERAL, "print")
+(7, OPEN_BRACKET)
+(7, STRING, "hi")
+(7, CLOSE_BRACKET)
+(7, SEMICOLON)
+(8, RETURN)
+(8, SEMICOLON)
+(9, EOF)

+ 21 - 0
test/basic/goto

@@ -0,0 +1,21 @@
+print("a");
+invstring = "";
+goto(@label4);
+@label3
+print("e");
+goto(@label5);
+@label4
+
+goto(@label1);
+print("b");
+@label1
+
+goto("label2");
+print("c");
+@label2;
+
+goto(@label3);
+@label5
+print("d");
+
+print("b");

+ 25 - 0
test/basic/goto.cout

@@ -0,0 +1,25 @@
+push "a"
+use print(1)
+push invstring
+push ""
+use =(2)
+push "label4"
+use goto(1)
+push "e"
+use print(1)
+push "label5"
+use goto(1)
+push "label1"
+use goto(1)
+push "b"
+use print(1)
+push "label2"
+use goto(1)
+push "c"
+use print(1)
+push "label3"
+use goto(1)
+push "d"
+use print(1)
+push "b"
+use print(1)

+ 4 - 0
test/basic/goto.out

@@ -0,0 +1,4 @@
+a
+e
+d
+b

+ 66 - 0
test/basic/goto.tout

@@ -0,0 +1,66 @@
+(1, LITERAL, "print")
+(1, OPEN_BRACKET)
+(1, STRING, "a")
+(1, CLOSE_BRACKET)
+(1, SEMICOLON)
+(2, LITERAL, "invstring")
+(2, SET)
+(2, STRING, "")
+(2, SEMICOLON)
+(3, LITERAL, "goto")
+(3, OPEN_BRACKET)
+(3, LABEL, "@label4")
+(3, CLOSE_BRACKET)
+(3, SEMICOLON)
+(4, LABEL, "@label3")
+(5, LITERAL, "print")
+(5, OPEN_BRACKET)
+(5, STRING, "e")
+(5, CLOSE_BRACKET)
+(5, SEMICOLON)
+(6, LITERAL, "goto")
+(6, OPEN_BRACKET)
+(6, LABEL, "@label5")
+(6, CLOSE_BRACKET)
+(6, SEMICOLON)
+(7, LABEL, "@label4")
+(9, LITERAL, "goto")
+(9, OPEN_BRACKET)
+(9, LABEL, "@label1")
+(9, CLOSE_BRACKET)
+(9, SEMICOLON)
+(10, LITERAL, "print")
+(10, OPEN_BRACKET)
+(10, STRING, "b")
+(10, CLOSE_BRACKET)
+(10, SEMICOLON)
+(11, LABEL, "@label1")
+(13, LITERAL, "goto")
+(13, OPEN_BRACKET)
+(13, STRING, "label2")
+(13, CLOSE_BRACKET)
+(13, SEMICOLON)
+(14, LITERAL, "print")
+(14, OPEN_BRACKET)
+(14, STRING, "c")
+(14, CLOSE_BRACKET)
+(14, SEMICOLON)
+(15, LABEL, "@label2")
+(15, SEMICOLON)
+(17, LITERAL, "goto")
+(17, OPEN_BRACKET)
+(17, LABEL, "@label3")
+(17, CLOSE_BRACKET)
+(17, SEMICOLON)
+(18, LABEL, "@label5")
+(19, LITERAL, "print")
+(19, OPEN_BRACKET)
+(19, STRING, "d")
+(19, CLOSE_BRACKET)
+(19, SEMICOLON)
+(21, LITERAL, "print")
+(21, OPEN_BRACKET)
+(21, STRING, "b")
+(21, CLOSE_BRACKET)
+(21, SEMICOLON)
+(22, EOF)

+ 7 - 0
test/basic/local

@@ -0,0 +1,7 @@
+print(get());
+
+function get()
+{
+    a = 5;
+    return a;
+}

+ 9 - 0
test/basic/local.cout

@@ -0,0 +1,9 @@
+use get(0)
+use print(1)
+get(8)
+push a#L
+push 5
+use =(2)
+push a#L
+return(1)
+return(0)

+ 1 - 0
test/basic/local.out

@@ -0,0 +1 @@
+5.0

+ 21 - 0
test/basic/local.tout

@@ -0,0 +1,21 @@
+(1, LITERAL, "print")
+(1, OPEN_BRACKET)
+(1, LITERAL, "get")
+(1, OPEN_BRACKET)
+(1, CLOSE_BRACKET)
+(1, CLOSE_BRACKET)
+(1, SEMICOLON)
+(3, FUNCTION)
+(3, LITERAL, "get")
+(3, OPEN_BRACKET)
+(3, CLOSE_BRACKET)
+(4, OPEN_CURVED_BRACKET)
+(5, LITERAL, "a")
+(5, SET)
+(5, NUMBER, 5.0)
+(5, SEMICOLON)
+(6, RETURN)
+(6, LITERAL, "a")
+(6, SEMICOLON)
+(7, CLOSE_CURVED_BRACKET)
+(8, EOF)

+ 2 - 0
test/basic/print

@@ -0,0 +1,2 @@
+print("HI");
+print( 	 "HI2"	  )  	;

+ 4 - 0
test/basic/print.cout

@@ -0,0 +1,4 @@
+push "HI"
+use print(1)
+push "HI2"
+use print(1)

+ 2 - 0
test/basic/print.out

@@ -0,0 +1,2 @@
+HI
+HI2

+ 11 - 0
test/basic/print.tout

@@ -0,0 +1,11 @@
+(1, LITERAL, "print")
+(1, OPEN_BRACKET)
+(1, STRING, "HI")
+(1, CLOSE_BRACKET)
+(1, SEMICOLON)
+(2, LITERAL, "print")
+(2, OPEN_BRACKET)
+(2, STRING, "HI2")
+(2, CLOSE_BRACKET)
+(2, SEMICOLON)
+(3, EOF)

+ 4 - 0
test/basic/unicode

@@ -0,0 +1,4 @@
+print("▇");
+print("äöü");
+print("ÄÖÜ");
+print("ß");

+ 8 - 0
test/basic/unicode.cout

@@ -0,0 +1,8 @@
+push "▇"
+use print(1)
+push "äöü"
+use print(1)
+push "ÄÖÜ"
+use print(1)
+push "ß"
+use print(1)

+ 4 - 0
test/basic/unicode.out

@@ -0,0 +1,4 @@
+▇
+äöü
+ÄÖÜ

+ 21 - 0
test/basic/unicode.tout

@@ -0,0 +1,21 @@
+(1, LITERAL, "print")
+(1, OPEN_BRACKET)
+(1, STRING, "▇")
+(1, CLOSE_BRACKET)
+(1, SEMICOLON)
+(2, LITERAL, "print")
+(2, OPEN_BRACKET)
+(2, STRING, "äöü")
+(2, CLOSE_BRACKET)
+(2, SEMICOLON)
+(3, LITERAL, "print")
+(3, OPEN_BRACKET)
+(3, STRING, "ÄÖÜ")
+(3, CLOSE_BRACKET)
+(3, SEMICOLON)
+(4, LITERAL, "print")
+(4, OPEN_BRACKET)
+(4, STRING, "ß")
+(4, CLOSE_BRACKET)
+(4, SEMICOLON)
+(5, EOF)

+ 15 - 0
test/calc/base

@@ -0,0 +1,15 @@
+print(1 + 1);
+print(1 + -3);
+
+print(1 - 3);
+print(1 - -3);
+
+print(4 * 3);
+print(6 * -3);
+print(-6 * 4);
+print(-6 * -4);
+
+print(4 / 2);
+print(6 / -2);
+print(-6 / 3);
+print(-6 / -2);

+ 58 - 0
test/calc/base.cout

@@ -0,0 +1,58 @@
+push 1
+push 1
+use +(2)
+use print(1)
+push 1
+push 3
+use -(1)
+use +(2)
+use print(1)
+push 1
+push 3
+use -(2)
+use print(1)
+push 1
+push 3
+use -(1)
+use -(2)
+use print(1)
+push 4
+push 3
+use *(2)
+use print(1)
+push 6
+push 3
+use -(1)
+use *(2)
+use print(1)
+push 6
+use -(1)
+push 4
+use *(2)
+use print(1)
+push 6
+use -(1)
+push 4
+use -(1)
+use *(2)
+use print(1)
+push 4
+push 2
+use /(2)
+use print(1)
+push 6
+push 2
+use -(1)
+use /(2)
+use print(1)
+push 6
+use -(1)
+push 3
+use /(2)
+use print(1)
+push 6
+use -(1)
+push 2
+use -(1)
+use /(2)
+use print(1)

+ 12 - 0
test/calc/base.out

@@ -0,0 +1,12 @@
+2.0
+-2.0
+-2.0
+4.0
+12.0
+-18.0
+-24.0
+24.0
+2.0
+-3.0
+-2.0
+3.0

+ 95 - 0
test/calc/base.tout

@@ -0,0 +1,95 @@
+(1, LITERAL, "print")
+(1, OPEN_BRACKET)
+(1, NUMBER, 1.0)
+(1, ADD)
+(1, NUMBER, 1.0)
+(1, CLOSE_BRACKET)
+(1, SEMICOLON)
+(2, LITERAL, "print")
+(2, OPEN_BRACKET)
+(2, NUMBER, 1.0)
+(2, ADD)
+(2, SUB)
+(2, NUMBER, 3.0)
+(2, CLOSE_BRACKET)
+(2, SEMICOLON)
+(4, LITERAL, "print")
+(4, OPEN_BRACKET)
+(4, NUMBER, 1.0)
+(4, SUB)
+(4, NUMBER, 3.0)
+(4, CLOSE_BRACKET)
+(4, SEMICOLON)
+(5, LITERAL, "print")
+(5, OPEN_BRACKET)
+(5, NUMBER, 1.0)
+(5, SUB)
+(5, SUB)
+(5, NUMBER, 3.0)
+(5, CLOSE_BRACKET)
+(5, SEMICOLON)
+(7, LITERAL, "print")
+(7, OPEN_BRACKET)
+(7, NUMBER, 4.0)
+(7, MUL)
+(7, NUMBER, 3.0)
+(7, CLOSE_BRACKET)
+(7, SEMICOLON)
+(8, LITERAL, "print")
+(8, OPEN_BRACKET)
+(8, NUMBER, 6.0)
+(8, MUL)
+(8, SUB)
+(8, NUMBER, 3.0)
+(8, CLOSE_BRACKET)
+(8, SEMICOLON)
+(9, LITERAL, "print")
+(9, OPEN_BRACKET)
+(9, SUB)
+(9, NUMBER, 6.0)
+(9, MUL)
+(9, NUMBER, 4.0)
+(9, CLOSE_BRACKET)
+(9, SEMICOLON)
+(10, LITERAL, "print")
+(10, OPEN_BRACKET)
+(10, SUB)
+(10, NUMBER, 6.0)
+(10, MUL)
+(10, SUB)
+(10, NUMBER, 4.0)
+(10, CLOSE_BRACKET)
+(10, SEMICOLON)
+(12, LITERAL, "print")
+(12, OPEN_BRACKET)
+(12, NUMBER, 4.0)
+(12, DIV)
+(12, NUMBER, 2.0)
+(12, CLOSE_BRACKET)
+(12, SEMICOLON)
+(13, LITERAL, "print")
+(13, OPEN_BRACKET)
+(13, NUMBER, 6.0)
+(13, DIV)
+(13, SUB)
+(13, NUMBER, 2.0)
+(13, CLOSE_BRACKET)
+(13, SEMICOLON)
+(14, LITERAL, "print")
+(14, OPEN_BRACKET)
+(14, SUB)
+(14, NUMBER, 6.0)
+(14, DIV)
+(14, NUMBER, 3.0)
+(14, CLOSE_BRACKET)
+(14, SEMICOLON)
+(15, LITERAL, "print")
+(15, OPEN_BRACKET)
+(15, SUB)
+(15, NUMBER, 6.0)
+(15, DIV)
+(15, SUB)
+(15, NUMBER, 2.0)
+(15, CLOSE_BRACKET)
+(15, SEMICOLON)
+(16, EOF)

+ 1 - 0
test/calc/comma

@@ -0,0 +1 @@
+print(5.125 + 3.125 + 1.25 + 0.5);

+ 8 - 0
test/calc/comma.cout

@@ -0,0 +1,8 @@
+push 5.125
+push 3.125
+use +(2)
+push 1.25
+use +(2)
+push 0.5
+use +(2)
+use print(1)

+ 1 - 0
test/calc/comma.out

@@ -0,0 +1 @@
+10.0

+ 12 - 0
test/calc/comma.tout

@@ -0,0 +1,12 @@
+(1, LITERAL, "print")
+(1, OPEN_BRACKET)
+(1, NUMBER, 5.125)
+(1, ADD)
+(1, NUMBER, 3.125)
+(1, ADD)
+(1, NUMBER, 1.25)
+(1, ADD)
+(1, NUMBER, 0.5)
+(1, CLOSE_BRACKET)
+(1, SEMICOLON)
+(2, EOF)

+ 8 - 0
test/calc/mixed

@@ -0,0 +1,8 @@
+print(2 + 3 * 4);
+print((2 + 3) * 4);
+print(2 + 3 * 4 + 2);
+print(2 + 3 * (4 + 2));
+print(2 + 3 * (4 + 2));
+print(2 + -3 * (4 + 2));
+print(2 + 3 * (-4 + 2));
+print((2 - 3) * 4);

+ 60 - 0
test/calc/mixed.cout

@@ -0,0 +1,60 @@
+push 2
+push 3
+push 4
+use *(2)
+use +(2)
+use print(1)
+push 2
+push 3
+use +(2)
+push 4
+use *(2)
+use print(1)
+push 2
+push 3
+push 4
+use *(2)
+use +(2)
+push 2
+use +(2)
+use print(1)
+push 2
+push 3
+push 4
+push 2
+use +(2)
+use *(2)
+use +(2)
+use print(1)
+push 2
+push 3
+push 4
+push 2
+use +(2)
+use *(2)
+use +(2)
+use print(1)
+push 2
+push 3
+use -(1)
+push 4
+push 2
+use +(2)
+use *(2)
+use +(2)
+use print(1)
+push 2
+push 3
+push 4
+use -(1)
+push 2
+use +(2)
+use *(2)
+use +(2)
+use print(1)
+push 2
+push 3
+use -(2)
+push 4
+use *(2)
+use print(1)

+ 8 - 0
test/calc/mixed.out

@@ -0,0 +1,8 @@
+14.0
+20.0
+16.0
+20.0
+20.0
+-16.0
+-4.0
+-4.0

+ 97 - 0
test/calc/mixed.tout

@@ -0,0 +1,97 @@
+(1, LITERAL, "print")
+(1, OPEN_BRACKET)
+(1, NUMBER, 2.0)
+(1, ADD)
+(1, NUMBER, 3.0)
+(1, MUL)
+(1, NUMBER, 4.0)
+(1, CLOSE_BRACKET)
+(1, SEMICOLON)
+(2, LITERAL, "print")
+(2, OPEN_BRACKET)
+(2, OPEN_BRACKET)
+(2, NUMBER, 2.0)
+(2, ADD)
+(2, NUMBER, 3.0)
+(2, CLOSE_BRACKET)
+(2, MUL)
+(2, NUMBER, 4.0)
+(2, CLOSE_BRACKET)
+(2, SEMICOLON)
+(3, LITERAL, "print")
+(3, OPEN_BRACKET)
+(3, NUMBER, 2.0)
+(3, ADD)
+(3, NUMBER, 3.0)
+(3, MUL)
+(3, NUMBER, 4.0)
+(3, ADD)
+(3, NUMBER, 2.0)
+(3, CLOSE_BRACKET)
+(3, SEMICOLON)
+(4, LITERAL, "print")
+(4, OPEN_BRACKET)
+(4, NUMBER, 2.0)
+(4, ADD)
+(4, NUMBER, 3.0)
+(4, MUL)
+(4, OPEN_BRACKET)
+(4, NUMBER, 4.0)
+(4, ADD)
+(4, NUMBER, 2.0)
+(4, CLOSE_BRACKET)
+(4, CLOSE_BRACKET)
+(4, SEMICOLON)
+(5, LITERAL, "print")
+(5, OPEN_BRACKET)
+(5, NUMBER, 2.0)
+(5, ADD)
+(5, NUMBER, 3.0)
+(5, MUL)
+(5, OPEN_BRACKET)
+(5, NUMBER, 4.0)
+(5, ADD)
+(5, NUMBER, 2.0)
+(5, CLOSE_BRACKET)
+(5, CLOSE_BRACKET)
+(5, SEMICOLON)
+(6, LITERAL, "print")
+(6, OPEN_BRACKET)
+(6, NUMBER, 2.0)
+(6, ADD)
+(6, SUB)
+(6, NUMBER, 3.0)
+(6, MUL)
+(6, OPEN_BRACKET)
+(6, NUMBER, 4.0)
+(6, ADD)
+(6, NUMBER, 2.0)
+(6, CLOSE_BRACKET)
+(6, CLOSE_BRACKET)
+(6, SEMICOLON)
+(7, LITERAL, "print")
+(7, OPEN_BRACKET)
+(7, NUMBER, 2.0)
+(7, ADD)
+(7, NUMBER, 3.0)
+(7, MUL)
+(7, OPEN_BRACKET)
+(7, SUB)
+(7, NUMBER, 4.0)
+(7, ADD)
+(7, NUMBER, 2.0)
+(7, CLOSE_BRACKET)
+(7, CLOSE_BRACKET)
+(7, SEMICOLON)
+(8, LITERAL, "print")
+(8, OPEN_BRACKET)
+(8, OPEN_BRACKET)
+(8, NUMBER, 2.0)
+(8, SUB)
+(8, NUMBER, 3.0)
+(8, CLOSE_BRACKET)
+(8, MUL)
+(8, NUMBER, 4.0)
+(8, CLOSE_BRACKET)
+(8, SEMICOLON)
+(9, EOF)

+ 1 - 0
test/calc/mod

@@ -0,0 +1 @@
+print(7 % 5);

+ 4 - 0
test/calc/mod.cout

@@ -0,0 +1,4 @@
+push 7
+push 5
+use %(2)
+use print(1)

+ 1 - 0
test/calc/mod.out

@@ -0,0 +1 @@
+2.0

Alguns arquivos não foram mostrados porque muitos arquivos mudaram nesse diff