瀏覽代碼

basic compiling, basic execution, refactoring

Kajetan Johannes Hammerle 6 年之前
父節點
當前提交
7c06ea0e6a

+ 11 - 4
Main.cpp

@@ -2,23 +2,30 @@
 #include "File.h"
 #include "compiler/Tokenizer.h"
 #include "Exception.h"
-#include "data/HashMap.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;
 
 int main(int argc, char** argv) 
-{    
+{        
     File f("tests/vars.snuvi");
     if(f.exists())
     {
         Compiler c(f.read());
-        c.compile();
+        Script sc;
+        c.compile(sc);
+        sc.execute();
     }
     else
     {
         cout << "no" << endl;
-    }    
+    }
+
     return 0;
 }
 

+ 2 - 3
Makefile

@@ -1,9 +1,8 @@
-
 run: all
 	./LonelyTiger
 
-all: *.cpp *.h compiler/*.cpp compiler/*.h
-	g++ -Wall -std=c++14 *.cpp compiler/*.cpp -o LonelyTiger
+all: *.cpp *.h compiler/*.cpp compiler/*.h code/*.cpp code/*.h
+	g++ -Wall -std=c++14 *.cpp compiler/*.cpp code/*.cpp -o LonelyTiger
 	
 clean:
 	rm LonelyTiger

+ 31 - 0
code/BoolData.cpp

@@ -0,0 +1,31 @@
+#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)";
+    }
+}
+

+ 20 - 0
code/BoolData.h

@@ -0,0 +1,20 @@
+#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
+

+ 55 - 0
code/Data.cpp

@@ -0,0 +1,55 @@
+#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_";
+}
+

+ 33 - 0
code/Data.h

@@ -0,0 +1,33 @@
+#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
+

+ 25 - 0
code/FloatData.cpp

@@ -0,0 +1,25 @@
+#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 << ")";
+}

+ 21 - 0
code/FloatData.h

@@ -0,0 +1,21 @@
+#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
+

+ 1 - 0
code/Function.c

@@ -0,0 +1 @@
+

+ 18 - 0
code/Function.h

@@ -0,0 +1,18 @@
+#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
+

+ 15 - 0
code/Instruction.cpp

@@ -0,0 +1,15 @@
+#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);
+}
+

+ 22 - 0
code/Instruction.h

@@ -0,0 +1,22 @@
+#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
+

+ 34 - 0
code/Script.cpp

@@ -0,0 +1,34 @@
+#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;
+}
+

+ 27 - 0
code/Script.h

@@ -0,0 +1,27 @@
+#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
+

+ 67 - 6
compiler/Compiler.cpp

@@ -1,5 +1,8 @@
 #include "Compiler.h"
 #include "../Exception.h"
+#include "../data/Stack.h"
+#include "../code/Function.h"
+#include "../code/FloatData.h"
 
 Compiler::Compiler(string s) : tokenizer(s)
 {
@@ -9,13 +12,13 @@ Compiler::~Compiler()
 {
 }
 
-void Compiler::compile()
+void Compiler::compile(Script& sc)
 {
     TokenList tokens;
     try
     {
         tokenizer.tokenize(tokens);
-        compile(tokens);
+        compile(sc, tokens);
     }
     catch(Exception ex)
     {
@@ -23,10 +26,68 @@ void Compiler::compile()
     }
 }
 
-void Compiler::compile(TokenList& tokens)
+void Compiler::addInstruction(ArrayList<Instruction*>& code, Stack<Token*>& st, Token* t)
 {
-    tokens.forEach([](Token* t) 
+    if(t->getType() == Tokens::FLOAT)
     {
-        cout << *t << endl;
-    });
+        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);
+    }
 }

+ 5 - 3
compiler/Compiler.h

@@ -5,6 +5,7 @@
 #include "../data/ArrayList.h"
 #include "Token.h"
 #include "Tokenizer.h"
+#include "../code/Script.h"
 
 using namespace std;
 
@@ -13,12 +14,13 @@ class Compiler
 public:
     Compiler(string s);
     virtual ~Compiler();
-    
-    void compile();
+
+    void compile(Script& sc);
 private:
     Tokenizer tokenizer;
     
-    void compile(TokenList& tokens);
+    void compile(Script& sc, TokenList& tokens);
+    void addInstruction(ArrayList<Instruction*>& code, Stack<Token*>& st, Token* t);
 };
 
 #endif

+ 10 - 5
compiler/Token.cpp

@@ -3,7 +3,7 @@
 #include <iostream>
 #include "TokenType.h"
 
-Token::Token(TokenType type, int line) : type(type)
+Token::Token(TokenType type, int line) : type(&type)
 {
     this->line = line;
     f = 0.0f;
@@ -16,7 +16,7 @@ Token::~Token()
 
 void Token::setFloat(float f)
 {
-    if(type != Tokens::FLOAT)
+    if((*type) != Tokens::FLOAT)
     {
         throw Exception("token contains no float");
     }
@@ -25,7 +25,7 @@ void Token::setFloat(float f)
 
 void Token::setString(string s)
 {
-    if(type != Tokens::TEXT && type != Tokens::LABEL && type != Tokens::VAR)
+    if(*type != Tokens::TEXT && *type != Tokens::LABEL && *type != Tokens::VAR)
     {
         throw Exception("token contains no string");
     }
@@ -39,7 +39,7 @@ float Token::getFloat() const
 
 bool Token::getBool() const
 {
-    if(type == Tokens::TRUE)
+    if(*type == Tokens::TRUE)
     {
         return true;
     }
@@ -56,9 +56,14 @@ int Token::getLine() const
     return line;
 }
 
+void Token::setType(TokenType type)
+{
+    this->type = &type;
+}
+
 TokenType Token::getType() const
 {
-    return type;
+    return *type;
 }
 
 std::ostream& operator<<(std::ostream& stream, const Token& t)

+ 2 - 1
compiler/Token.h

@@ -20,9 +20,10 @@ public:
     bool getBool() const;
     string getString() const;
     int getLine() const;
+    void setType(TokenType type);
     TokenType getType() const;
 private:
-    TokenType type;
+    const TokenTypeClass* type;
     float f;
     string s;
     int line;

+ 10 - 0
compiler/TokenList.cpp

@@ -31,3 +31,13 @@ void TokenList::forEach(void (*f) (Token*))
     list.forEach(f);
 }
 
+int TokenList::getSize()
+{
+    return list.getSize();
+}
+
+Token* TokenList::get(int index)
+{
+    return list.get(index);
+}
+

+ 2 - 0
compiler/TokenList.h

@@ -13,6 +13,8 @@ public:
     
     void add(Token* t);
     void remove(int index);
+    int getSize();
+    Token* get(int index);
     void forEach(void (*f) (Token*));
 private:
     ArrayList<Token*> list;

+ 74 - 76
compiler/TokenType.cpp

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

+ 70 - 66
compiler/TokenType.h

@@ -9,87 +9,91 @@ using namespace std;
 class TokenTypeClass
 {
 public:
-    TokenTypeClass(string name, int level);
-    TokenTypeClass(string name);
-    TokenTypeClass(const TokenTypeClass& orig);
+    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* const TokenType;
+typedef const TokenTypeClass& TokenType;
 
-std::ostream& operator<<(std::ostream& os, TokenType& c);
+std::ostream& operator<<(std::ostream& os, const TokenType& c);
 
 namespace Tokens
 {
-    extern TokenType FLOAT;
-    extern TokenType TRUE;
-    extern TokenType FALSE;
-    extern TokenType TNULL;
-    extern TokenType TEXT;
-    extern TokenType LABEL;
-    extern TokenType VAR;
-    extern TokenType GLOBAL;
+    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 TokenType INC;
-    extern TokenType DEC;
-    extern TokenType INVERT;
-    extern TokenType BIT_INVERT;
-    extern TokenType MUL;
-    extern TokenType DIV;
-    extern TokenType MOD;
-    extern TokenType ADD;
-    extern TokenType SUB;
-    extern TokenType LEFT_SHIFT;
-    extern TokenType RIGHT_SHIFT;
-    extern TokenType LESS;
-    extern TokenType LESS_EQUAL;
-    extern TokenType GREATER;
-    extern TokenType GREATER_EQUAL;
-    extern TokenType EQUAL;
-    extern TokenType NOT_EQUAL;
-    extern TokenType BIT_AND;
-    extern TokenType BIT_XOR;
-    extern TokenType BIT_OR;
-    extern TokenType AND;
-    extern TokenType OR;
-    extern TokenType SET;
-    extern TokenType ADD_SET;
-    extern TokenType SUB_SET;
-    extern TokenType MUL_SET;
-    extern TokenType DIV_SET;
-    extern TokenType MOD_SET;
-    extern TokenType LEFT_SHIFT_SET;
-    extern TokenType RIGHT_SHIFT_SET;
-    extern TokenType BIT_AND_SET;
-    extern TokenType BIT_XOR_SET;
-    extern TokenType BIT_OR_SET;
-    extern TokenType COMMA;
-    extern TokenType OPEN_BRACKET;
-    extern TokenType CLOSE_BRACKET;
-    extern TokenType OPEN_SQUARE_BRACKET;
-    extern TokenType CLOSE_SQUARE_BRACKET;
-    extern TokenType OPEN_CURVED_BRACKET;
-    extern TokenType CLOSE_CURVED_BRACKET;
-    extern TokenType SEMICOLON;
+    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 TokenType IF;
-    extern TokenType ELSE_IF;
-    extern TokenType ELSE;
-    extern TokenType FOR;
-    extern TokenType WHILE;
-    extern TokenType FUNCTION;
-    extern TokenType BREAK;
-    extern TokenType CONTINUE;
-    extern TokenType RETURN;
-    extern TokenType TRY;
-    extern TokenType CATCH;
-    extern TokenType END_OF_FILE;
+    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

+ 6 - 3
compiler/Tokenizer.cpp

@@ -18,7 +18,7 @@ Tokenizer::~Tokenizer()
 {
 }
 
-void Tokenizer::tokenize(TokenList& tokens, char c, const TokenTypeClass* type1, const TokenTypeClass* type2)
+void Tokenizer::tokenize(TokenList& tokens, char c, TokenType type1, TokenType type2)
 {
     if(pos + 1 < length && data[pos + 1] == c)
     {
@@ -31,7 +31,7 @@ void Tokenizer::tokenize(TokenList& tokens, char c, const TokenTypeClass* type1,
     }
 }
 
-void Tokenizer::tokenize(TokenList& tokens, const TokenTypeClass* type1, char c2, const TokenTypeClass* type2, char c3, const TokenTypeClass* type3)
+void Tokenizer::tokenize(TokenList& tokens, TokenType type1, char c2, TokenType type2, char c3, TokenType type3)
 {
     if(pos + 1 >= length)
     {
@@ -53,7 +53,7 @@ void Tokenizer::tokenize(TokenList& tokens, const TokenTypeClass* type1, char c2
     }
 }
 
-void Tokenizer::tokenize(TokenList& tokens, const TokenTypeClass* type1, char c2, char c3, const TokenTypeClass* type2, const TokenTypeClass* type3, char c4, const TokenTypeClass* type4)
+void Tokenizer::tokenize(TokenList& tokens, TokenType type1, char c2, char c3, TokenType type2, TokenType type3, char c4, TokenType type4)
 {
     if(pos + 1 >= length)
     {
@@ -111,6 +111,9 @@ void Tokenizer::tokenize(TokenList& tokens)
             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);

+ 3 - 3
compiler/Tokenizer.h

@@ -22,9 +22,9 @@ private:
     int line;
     int length;
     
-    void tokenize(TokenList& tokens, char c, const TokenTypeClass* type1, const TokenTypeClass* type2);
-    void tokenize(TokenList& tokens, const TokenTypeClass* type1, char c2, const TokenTypeClass*, char c3, const TokenTypeClass* type3);
-    void tokenize(TokenList& tokens, const TokenTypeClass* type1, char c2, char c3, const TokenTypeClass* type2, const TokenTypeClass* type3, char c4, const TokenTypeClass* type4);
+    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

+ 10 - 0
data/ArrayList.h

@@ -3,6 +3,7 @@
 
 #include <cstring>
 #include <iostream>
+#include "../Exception.h"
 
 template<class T>
 class ArrayList
@@ -80,6 +81,15 @@ public:
         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++)

+ 91 - 0
data/Stack.h

@@ -0,0 +1,91 @@
+#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
+

+ 1 - 2
tests/vars.snuvi

@@ -1,2 +1 @@
-a = 3.0046;
-b = 3;
+1 + 2 + 3