├── Error.h ├── VM.cpp ├── Error.cpp ├── Parser.h ├── Scanner.h ├── Value.cpp ├── CodeWriter.h ├── Function.cpp ├── Function.h ├── Parser.cpp ├── Scanner.cpp ├── CodeGenerate.cpp ├── GramTreeNode.cpp ├── State.h ├── CodeWriter.cpp ├── libs ├── BaseLib.h └── BaseLib.cpp ├── mlua.cpp ├── test.lua ├── Instruction.cpp ├── State.cpp ├── Stack.h ├── Visitor.h ├── VM.h ├── CodeGenerate.h ├── Stack.cpp ├── README.md ├── Visitor.cpp ├── Instruction.h ├── mlua.vcxproj ├── Value.h └── GramTreeNode.h /Error.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/Error.h -------------------------------------------------------------------------------- /VM.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/VM.cpp -------------------------------------------------------------------------------- /Error.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/Error.cpp -------------------------------------------------------------------------------- /Parser.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/Parser.h -------------------------------------------------------------------------------- /Scanner.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/Scanner.h -------------------------------------------------------------------------------- /Value.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/Value.cpp -------------------------------------------------------------------------------- /CodeWriter.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/CodeWriter.h -------------------------------------------------------------------------------- /Function.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/Function.cpp -------------------------------------------------------------------------------- /Function.h: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/Function.h -------------------------------------------------------------------------------- /Parser.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/Parser.cpp -------------------------------------------------------------------------------- /Scanner.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/Scanner.cpp -------------------------------------------------------------------------------- /CodeGenerate.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/CodeGenerate.cpp -------------------------------------------------------------------------------- /GramTreeNode.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/shonm520/mlua/HEAD/GramTreeNode.cpp -------------------------------------------------------------------------------- /State.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Value.h" 4 | #include "VM.h" 5 | 6 | 7 | 8 | 9 | class Stack; 10 | 11 | class State 12 | { 13 | public: 14 | friend class VM; 15 | friend class CodeGenerateVisitor; 16 | 17 | State(); 18 | ~State(); 19 | 20 | VM* getVM() { return _vm; } 21 | void setVM(VM* vm) { _vm = vm; } 22 | Stack* getStack() { return _stack; } 23 | Table* getGlobalTable() { return _global_table; } 24 | 25 | typedef int(*Fun)(State*, void*); 26 | void registerFunc(std::string name, Fun); 27 | void registerTable(std::string name, Table* table); 28 | void openLibs(); 29 | 30 | private: 31 | Stack* _stack; 32 | Table* _global_table; 33 | VM* _vm; 34 | }; 35 | 36 | -------------------------------------------------------------------------------- /CodeWriter.cpp: -------------------------------------------------------------------------------- 1 | #include "CodeWriter.h" 2 | #include "Function.h" 3 | 4 | 5 | CodeWrite::CodeWrite() : 6 | _insSet(new InstructionSet(InstructionSet::Medium)) 7 | { 8 | 9 | } 10 | 11 | 12 | CodeWrite::~CodeWrite() 13 | { 14 | if (_insSet) { 15 | _insSet->clearInstructions(); 16 | } 17 | } 18 | 19 | Instruction* CodeWrite::newInstruction() { 20 | return _insSet->newInstruction(); 21 | } 22 | 23 | InstructionSet* CodeWrite::fetchInstructionSet() 24 | { 25 | InstructionSet* temp = _insSet; 26 | _insSet = nullptr; 27 | return temp; 28 | } 29 | 30 | InstructionValue* CodeWrite::fetchInstructionVal() 31 | { 32 | InstructionValue* val = new InstructionValue(); 33 | val->setInstructionSet(_insSet); 34 | _insSet = nullptr; 35 | return val; 36 | } 37 | -------------------------------------------------------------------------------- /libs/BaseLib.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | struct Value; 4 | 5 | class BaseLib { 6 | public: 7 | static void PrintType(Value* val); 8 | static int Print(State* state, void* num_); 9 | static int generatePairs(State* state, void*); 10 | static int generateIPairs(State* state, void*); 11 | static int next(State* state, void*); 12 | static int type(State* state, void*); 13 | static int len(State* state, void*); 14 | static int setmeta(State* state, void*); 15 | 16 | 17 | struct StringLib { 18 | static int upper(State* state, void*); 19 | static int substr(State* state, void*); 20 | static int byte(State* state, void*); 21 | static int _char(State* state, void*); 22 | static Table* generateStringTable(); 23 | }; 24 | 25 | 26 | 27 | struct MathLib { 28 | static int _pow(State*, void*); 29 | static int _random(State*, void*); 30 | static Table* generateMathTable(); 31 | }; 32 | 33 | 34 | }; 35 | -------------------------------------------------------------------------------- /mlua.cpp: -------------------------------------------------------------------------------- 1 | #include "Scanner.h" 2 | #include "Parser.h" 3 | #include "State.h" 4 | #include "CodeGenerate.h" 5 | #include 6 | #include 7 | #include 8 | 9 | 10 | int main(int argc, char *argv[]) 11 | { 12 | if (argc < 2) { 13 | cerr << "usage: " << argv[0] << " " << endl; 14 | exit(-1); 15 | } 16 | ifstream fin; 17 | vector filenames; 18 | for (int i = 1; i < argc; i++) { 19 | fin.open(argv[i]); 20 | if (fin.fail()) { 21 | cerr << "file '" << argv[i] << "' not exist!"; 22 | exit(-1); 23 | } 24 | filenames.push_back(argv[i]); 25 | fin.close(); 26 | } 27 | 28 | Parser parser(filenames); 29 | parser.parse_program(); 30 | if (!hasError()) { 31 | State state; 32 | state.openLibs(); 33 | CodeGenerate(parser.getSyntaxTree(), &state); 34 | } 35 | 36 | getchar(); 37 | return 0; 38 | } 39 | -------------------------------------------------------------------------------- /test.lua: -------------------------------------------------------------------------------- 1 | //local a, b = 159, 236 2 | //a = 96 3 | //print(a, 78, 89 ,b) 4 | 5 | 6 | //local b = 10 + 2 * 3 7 | //local a = 1 + b 8 | //print(a) 9 | 10 | 11 | f = function(a) 12 | return function() a = a + 1 return a end 13 | end 14 | 15 | 16 | local up = f(12) 17 | local n1 = up() 18 | local n2 = up() 19 | print(n1, n2) 20 | 21 | up = f(34) 22 | local n1 = up() 23 | local n2 = up() 24 | print(n1, n2) 25 | 26 | /*function f(a, b) 27 | a = a + 1 28 | b = b * 11 29 | print(a, b) 30 | return b / 9 31 | end 32 | local a, b = 159, 7 33 | print(f(a, b, 666)) 34 | print(a, b)*/ 35 | 36 | /*local f = function(a) 37 | print(a) 38 | end 39 | 40 | f(123)*/ 41 | 42 | 43 | 44 | //local c = 15 45 | //print(a, b, c) 46 | //local n2 = ff() 47 | //print(n2) 48 | 49 | 50 | 51 | //local a = f() 52 | //print(a) 53 | //local b = f() 54 | //print(b) 55 | 56 | 57 | //local a, b = f() 58 | //local a, b = f() + 5 59 | //a, b = f() 60 | //a = f() 61 | //a, b = f() + 2 62 | //a = 2 + f() 63 | 64 | 65 | -------------------------------------------------------------------------------- /Instruction.cpp: -------------------------------------------------------------------------------- 1 | #include "Instruction.h" 2 | #include //for memset in linux 3 | 4 | Instruction::Instruction() 5 | { 6 | 7 | } 8 | 9 | 10 | 11 | InstructionSet::InstructionSet(Volum v) : 12 | _num(0), 13 | _instructions(nullptr) 14 | { 15 | if (v == Large) { 16 | _instructions = new Instruction[1000]; 17 | } 18 | else if (v == Medium) { 19 | _instructions = new Instruction[500]; 20 | } 21 | else if (v == Small) { 22 | _instructions = new Instruction[100]; 23 | } 24 | else if (v == None) { 25 | _instructions = 0; 26 | } 27 | } 28 | 29 | 30 | std::vector InstructionSet::toVtInstructions() { 31 | _opcodes.clear(); 32 | for (int i = 0; i < _num; i++) { 33 | _opcodes.push_back(&_instructions[i]); 34 | } 35 | return _opcodes; 36 | } 37 | 38 | 39 | Instruction* InstructionSet::newInstruction() 40 | { 41 | Instruction* ins = &_instructions[_num++]; 42 | memset(ins, 0, sizeof(Instruction)); 43 | return ins; 44 | } 45 | 46 | 47 | void InstructionSet::clearInstructions() 48 | { 49 | delete[] _instructions; 50 | _num = 0; 51 | } -------------------------------------------------------------------------------- /State.cpp: -------------------------------------------------------------------------------- 1 | #include "State.h" 2 | #include "Value.h" 3 | #include "Function.h" 4 | #include "Stack.h" 5 | #include "libs/BaseLib.h" 6 | 7 | 8 | 9 | State::State(): 10 | _vm(nullptr) 11 | { 12 | _stack = new Stack(1000); 13 | _global_table = new Table(); 14 | } 15 | 16 | 17 | State::~State() 18 | { 19 | } 20 | 21 | 22 | 23 | 24 | void State::registerFunc(std::string name, Fun fun) 25 | { 26 | _global_table->Assign(new String(name.c_str()), new NativeFunc(fun)); 27 | } 28 | 29 | 30 | void State::registerTable(std::string name, Table* table) 31 | { 32 | _global_table->Assign(new String(name.c_str()), table); 33 | } 34 | 35 | void State::openLibs() 36 | { 37 | registerFunc("print", BaseLib::Print); 38 | registerFunc("pairs", BaseLib::generatePairs); 39 | registerFunc("ipairs", BaseLib::generateIPairs); 40 | registerFunc("next", BaseLib::next); 41 | registerFunc("type", BaseLib::type); 42 | registerFunc("setmetatable", BaseLib::setmeta); 43 | 44 | registerTable("string", BaseLib::StringLib::generateStringTable()); 45 | registerTable("math", BaseLib::MathLib::generateMathTable()); 46 | } -------------------------------------------------------------------------------- /Stack.h: -------------------------------------------------------------------------------- 1 | #pragma 2 | #include 3 | #include "Value.h" 4 | 5 | 6 | enum StackValueType 7 | { 8 | StackValueType_Value, 9 | StackValueType_Counter, 10 | }; 11 | 12 | struct StackValue 13 | { 14 | StackValueType type; 15 | 16 | union { 17 | Value *value; 18 | struct { 19 | int total; 20 | int current; 21 | } counter; 22 | } param; 23 | }; 24 | 25 | class Stack 26 | { 27 | public: 28 | static const int kBaseStackSize = 1000; 29 | 30 | explicit Stack(int base_stack_size = kBaseStackSize); 31 | 32 | std::size_t Size() const; 33 | 34 | // If index >= 0, then return the stack value of index which from bottom to top, 35 | // else return the stack value of (-index) which from top to bottom. 36 | // If index is out of bound, then return 0. 37 | StackValue * GetStackValue(int index); 38 | const StackValue * GetStackValue(int index) const; 39 | 40 | // Get stack top value 41 | StackValue * Top(); 42 | const StackValue * Top() const; 43 | 44 | // Pop count values from stack top 45 | void Pop(int count = 1); 46 | 47 | Value* popValue(); 48 | 49 | // Clear stack 50 | void Clear(); 51 | 52 | // Push new value to stack and return the new value pointer 53 | StackValue * Push(); 54 | 55 | // Push a value to stack 56 | void Push(Value *value); 57 | 58 | // Push counter to stack 59 | void Push(int total, int current); 60 | 61 | void MarkStackValues(); 62 | 63 | private: 64 | std::vector stack_; 65 | }; -------------------------------------------------------------------------------- /Visitor.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GramTreeNode.h" 3 | 4 | class Visitor { 5 | public: 6 | ~Visitor(){} 7 | virtual void visit(ChunkNode *, void *) = 0; 8 | virtual void visit(BlockNode *, void *) = 0; 9 | virtual void visit(SyntaxTreeNodeBase*, void*) = 0; 10 | virtual void visit(AssignStatement* stm, void* data) = 0; 11 | virtual void visit(LocalNameListStatement* nls, void* data) = 0; 12 | virtual void visit(UnaryExpression* uexp, void* data) = 0; 13 | virtual void visit(Terminator* ter, void* data) = 0; 14 | virtual void visit(IdentifierNode* idt, void* data) = 0; 15 | virtual void visit(NormalCallFunciton* callFun, void* data) = 0; 16 | virtual void visit(OperateStatement* ops, void* data) = 0; 17 | virtual void visit(FunctionStatement* fsm, void* data) = 0; 18 | virtual void visit(ReturnStatement* rtSmt, void* data) = 0; 19 | virtual void visit(IfStatement* ifSmt, void* data) = 0; 20 | virtual void visit(CompareStatement* cmpSmt, void* data) = 0; 21 | virtual void visit(TableDefine* tbdSmt, void* data) = 0; 22 | virtual void visit(TableNameField* tbdSmt, void* data) = 0; 23 | virtual void visit(TableArrayFiled* taSmt, void* data) = 0; 24 | virtual void visit(TableIndexField* taSmt, void* data) = 0; 25 | virtual void visit(TabMemberAccessor* tmsSmt, void* data) = 0; 26 | virtual void visit(TabIndexAccessor* tmsSmt, void* data) = 0; 27 | virtual void visit(NumericForStatement* nforSmt, void* data) = 0; 28 | virtual void visit(GenericForStatement* gforSmt, void* data) = 0; 29 | virtual void visit(BreakStatement* brkSmt, void* data) = 0; 30 | }; -------------------------------------------------------------------------------- /VM.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Instruction.h" 4 | 5 | class State; 6 | class Stack; 7 | class InstructionValue; 8 | 9 | class VM 10 | { 11 | public: 12 | VM(State* state); 13 | ~VM(); 14 | 15 | //friend class BaseLib; 16 | 17 | private: 18 | State* _state; 19 | Stack* _stack; 20 | Stack* _stackClosure; 21 | 22 | InstructionValue* _curInsVal; 23 | 24 | public: 25 | void execute(); 26 | void execute_frame(); 27 | typedef std::vector VtIns; 28 | int runCode(InstructionValue*); 29 | 30 | private: 31 | void generateClosure(Instruction* ins); 32 | 33 | void add_global_table(); 34 | void enterClosure(); 35 | void quitClosure(); 36 | 37 | void call(Instruction* ins); 38 | void passFunParam(Instruction* ins); 39 | void initLocalVar(Instruction* ins); 40 | void assignOperate(Instruction* ins); 41 | void assignVals(int, int, int type); 42 | void assignSimple(int type); 43 | void pushValue(Instruction* ins); 44 | void setLoacalVar(Instruction* ins); 45 | void getLoacalVar(Instruction* ins); 46 | void funcionRet(Instruction* ins); 47 | void operateNum(Instruction* ins); 48 | void operateLogic(Instruction* ins); 49 | Closure* getCurrentClosure(); 50 | 51 | void ifCompare(Instruction* ins); 52 | void numericFor(Instruction* ins); 53 | void genericFor(Instruction* ins); 54 | void breakFor(Instruction* ins); 55 | void enterBlock(Instruction* ins); 56 | void quitBlock(Instruction* ins); 57 | 58 | void generateBlock(Instruction* ins); 59 | 60 | void runBlockCode(Value* val); 61 | 62 | void tableDefine(Instruction* ins); 63 | void tableAccess(Instruction* ins); 64 | void tableArrIndex(Instruction* ins); 65 | 66 | void negNumber(Instruction* ins); 67 | void lenOfVale(Instruction* ins); 68 | }; 69 | 70 | -------------------------------------------------------------------------------- /CodeGenerate.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include "GramTreeNode.h" 3 | #include "Visitor.h" 4 | 5 | 6 | class CodeWrite; 7 | 8 | class CodeGenerateVisitor : public Visitor 9 | { 10 | public: 11 | CodeGenerateVisitor(); 12 | ~CodeGenerateVisitor(); 13 | 14 | private: 15 | 16 | struct ExpVarData { 17 | enum Oprate_Type{ 18 | VAR_GET, 19 | VAR_SET 20 | } ; 21 | Oprate_Type type; 22 | }; 23 | 24 | 25 | struct TableArrayIndex { 26 | int num; 27 | }; 28 | 29 | 30 | public: 31 | 32 | void visit(ChunkNode* block, void* data) override; 33 | void visit(BlockNode* block, void* data) override; 34 | void visit(SyntaxTreeNodeBase* block, void* data) override; 35 | void visit(LocalNameListStatement* stm, void* data) override; 36 | void visit(AssignStatement* stm, void* data) override; 37 | void visit(UnaryExpression* uexp, void* data) override; 38 | void visit(Terminator* uexp, void* data) override; 39 | void visit(IdentifierNode* idt, void* data) override; 40 | void visit(NormalCallFunciton* block, void* data) override; 41 | void visit(OperateStatement* ops, void* data) override; 42 | void visit(FunctionStatement* fsm, void* data) override; 43 | void visit(ReturnStatement* rtSmt, void* data) override; 44 | void visit(IfStatement* ifSmt, void* data) override; 45 | void visit(CompareStatement* cmpSmt, void* data); 46 | void visit(TableDefine* tbdSmt, void* data); 47 | void visit(TableNameField* tnfSmt, void* data); 48 | void visit(TabMemberAccessor* tmsSmt, void* data); 49 | void visit(TabIndexAccessor* tiSmt, void* data); 50 | void visit(TableArrayFiled* taSmt, void* data); 51 | void visit(TableIndexField* tifSmt, void* data); 52 | void visit(NumericForStatement* nforSmt, void* data); 53 | void visit(GenericForStatement* gforSmt, void* data); 54 | void visit(BreakStatement* brkSmt, void* data); 55 | 56 | void generateChunkCode(ChunkNode*, CodeWrite*); 57 | void generateFuncCode(bool bGlobal, SyntaxTreeNodeBase* name, SyntaxTreeNodeBase* params, SyntaxTreeNodeBase* body, CodeWrite*); 58 | void generateFuncBodyCode(SyntaxTreeNodeBase*, CodeWrite*); 59 | void generateClosureCode(InstructionSet*, CodeWrite*); 60 | void generateNodeListCode(SyntaxTreeNodeBase* exp_list, CodeWrite*, ExpVarData::Oprate_Type type); 61 | }; 62 | 63 | 64 | void CodeGenerate(SyntaxTreeNodeBase* root, State* state); 65 | 66 | -------------------------------------------------------------------------------- /Stack.cpp: -------------------------------------------------------------------------------- 1 | 2 | 3 | #include "Stack.h" 4 | #include 5 | 6 | Stack::Stack(int base_stack_size) 7 | { 8 | stack_.reserve(base_stack_size); 9 | } 10 | 11 | std::size_t Stack::Size() const 12 | { 13 | return stack_.size(); 14 | } 15 | 16 | StackValue * Stack::GetStackValue(int index) 17 | { 18 | int size = stack_.size(); 19 | if (index >= 0) 20 | { 21 | if (index < size) 22 | return &stack_[index]; 23 | } 24 | else 25 | { 26 | index += size; 27 | if (index >= 0) 28 | return &stack_[index]; 29 | } 30 | 31 | return 0; 32 | } 33 | 34 | const StackValue * Stack::GetStackValue(int index) const 35 | { 36 | int size = stack_.size(); 37 | if (index >= 0) 38 | { 39 | if (index < size) 40 | return &stack_[index]; 41 | } 42 | else 43 | { 44 | index += size; 45 | if (index >= 0) 46 | return &stack_[index]; 47 | } 48 | 49 | return 0; 50 | } 51 | 52 | StackValue * Stack::Top() 53 | { 54 | if (stack_.empty()) 55 | return 0; 56 | return &stack_.back(); 57 | } 58 | 59 | const StackValue * Stack::Top() const 60 | { 61 | if (stack_.empty()) 62 | return 0; 63 | return &stack_.back(); 64 | } 65 | 66 | void Stack::Pop(int count) 67 | { 68 | assert(count > 0); 69 | int remain = static_cast(stack_.size()) - count; 70 | remain = remain < 0 ? 0 : remain; 71 | stack_.resize(remain); 72 | } 73 | 74 | Value* Stack::popValue() 75 | { 76 | if (stack_.empty()) 77 | return nullptr; 78 | StackValue* val = &stack_.back(); 79 | Pop(); 80 | return val->param.value; 81 | } 82 | 83 | void Stack::Clear() 84 | { 85 | stack_.clear(); 86 | } 87 | 88 | StackValue * Stack::Push() 89 | { 90 | stack_.resize(stack_.size() + 1); 91 | return Top(); 92 | } 93 | 94 | void Stack::Push(Value *value) 95 | { 96 | StackValue *sv = Push(); 97 | sv->type = StackValueType_Value; 98 | sv->param.value = value; 99 | } 100 | 101 | void Stack::Push(int total, int current) 102 | { 103 | StackValue *sv = Push(); 104 | sv->type = StackValueType_Counter; 105 | sv->param.counter.total = total; 106 | sv->param.counter.current = current; 107 | } 108 | 109 | void Stack::MarkStackValues() 110 | { 111 | for (auto it = stack_.begin(); it != stack_.end(); ++it) 112 | { 113 | StackValue *sv = &(*it); 114 | if (sv->type == StackValueType_Value) { 115 | //sv->param.value->Mark(); 116 | } 117 | } 118 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # mlua 2 | An interpreter of lua-like language written in C++ 3 | 4 | 技术细节详细讲解博客: 5 | 6 | https://blog.csdn.net/column/details/25937.html 7 | 8 | ### 安装: 9 | git clone https://github.com/shonm520/mlua.git 10 | 11 | windows: 用vs2013以上版本直接打开mlua.vcxproj文件即可。因为使用到了c++11语法,所以需要vs2013及以上版本。 12 | 13 | Linux : g++ \*.cpp libs/\*.cpp -o mlua -std=c++11 14 | 15 | 目前已实现了lua的大部分语句,包括if语句,函数,闭包,table,for循环等。 虚拟机目前是基于栈的。 16 | 17 | ### 函数与闭包的例子: 18 | 19 | ``` 20 | local f = function(a) 21 | return function() a = a + 1 return a end 22 | end 23 | 24 | local up = f(12) 25 | local n1 = up() 26 | local n2 = up() 27 | print(n1, n2) 28 | up = f(34) 29 | local n1 = up() 30 | local n2 = up() 31 | print(n1, n2) 32 | ``` 33 | 能正确的打印出 34 | ``` 35 | 13 14 36 | 35 36 37 | ``` 38 | 39 | ### if语句,函数递归调用的例子: 40 | ``` 41 | function fib(n) 42 | if n == 0 then return 1 43 | elseif n == 1 then return 1 44 | else 45 | return fib(n - 1) + fib(n - 2) 46 | end 47 | end 48 | 49 | local ret = fib(15) 50 | print(ret) 51 | ``` 52 | 能正确打印出987 53 | 54 | ### 泛型for循环: 55 | ``` 56 | local ipairsIter = function(t, i) 57 | i = i + 1 58 | local v = t[i] 59 | if v then 60 | return i, v, 10 61 | end 62 | end 63 | local tt = {12, 78} 64 | for k, v, m in ipairsIter, tt, 0 do 65 | print(k, v, m) 66 | end 67 | ``` 68 | 能正确打印出: 69 | ``` 70 | 1 12 10 71 | 2 78 10 72 | ``` 73 | 74 | ### table的例子 75 | ``` 76 | t = {name = 'shonm', 28, sex = 'male', game = {name = 'Glory of the king'}} 77 | 78 | t.func = function(str) 79 | print(str, t.name, 'age is ', t[1], 'sex is ', t.sex, 'he plays', t.game.name) 80 | end 81 | t.func('hello') 82 | ``` 83 | 84 | ### 部分内置函数和类库的例子 85 | ``` 86 | print(string.len('hello world')) 87 | print(string.upper('world')) 88 | print(math.pow(2, 6)) 89 | print(type({})) 90 | ``` 91 | 92 | ### 元表的例子: 93 | ``` 94 | fa = {house = 3} 95 | son = {car = 2} 96 | fa.__index = fa 97 | setmetatable(son, fa) 98 | print(son.house) 99 | ``` 100 | 能打印出预期结果3 101 | 102 | 103 | ### 面向对象多态特性 104 | ``` 105 | cat = {} 106 | function cat.call() 107 | print('cat call maomao~~~') 108 | end 109 | 110 | dog = {} 111 | dog.call = function () 112 | print('dog call wangwang~~~') 113 | end 114 | 115 | function test_duck(duck) 116 | duck.call() 117 | end 118 | 119 | test_duck(cat) 120 | test_duck(dog) 121 | ``` 122 | 结果为: 123 | ``` 124 | cat call maomao~~~ 125 | dog call wangwang~~~ 126 | ``` 127 | 128 | 129 | 130 | ### 下一步: 131 | 132 | + 注释还是C++格式的,单行//,多行 /* */,要改成lua的-- 133 | + 为了快速出结果,堆变量没有释放,有内存泄露,这个要处理好 134 | + 实现协程 135 | + 还没有垃圾回收GC,这个以后要加上去 136 | + 有时间把基于栈的虚拟机改为基于寄存器的 137 | 138 | ### 交流QQ群 858791125 139 | 140 | -------------------------------------------------------------------------------- /Visitor.cpp: -------------------------------------------------------------------------------- 1 | #include "Visitor.h" 2 | #include "GramTreeNode.h" 3 | 4 | 5 | void NormalCallFunciton::accept(Visitor* visitor, void* data) 6 | { 7 | visitor->visit(this, data); 8 | } 9 | 10 | void SyntaxTreeNodeBase::accept(Visitor* visitor, void* data) 11 | { 12 | visitor->visit(this, data); 13 | } 14 | 15 | void ChunkNode::accept(Visitor* visitor, void* data) 16 | { 17 | visitor->visit(this, data); 18 | } 19 | 20 | void BlockNode::accept(Visitor* visitor, void* data) 21 | { 22 | visitor->visit(this, data); 23 | } 24 | 25 | void LocalNameListStatement::accept(Visitor* visitor, void* data) 26 | { 27 | visitor->visit(this, data); 28 | } 29 | 30 | void AssignStatement::accept(Visitor* visitor, void* data) 31 | { 32 | visitor->visit(this, data); 33 | } 34 | 35 | void UnaryExpression::accept(Visitor* visitor, void* data) 36 | { 37 | visitor->visit(this, data); 38 | } 39 | 40 | void Terminator::accept(Visitor* visitor, void* data) 41 | { 42 | visitor->visit(this, data); 43 | } 44 | 45 | void IdentifierNode::accept(Visitor* visitor, void* data) 46 | { 47 | visitor->visit(this, data); 48 | } 49 | 50 | void OperateStatement::accept(Visitor* visitor, void* data) 51 | { 52 | visitor->visit(this, data); 53 | } 54 | 55 | void FunctionStatement::accept(Visitor* visitor, void* data) 56 | { 57 | visitor->visit(this, data); 58 | } 59 | 60 | void ReturnStatement::accept(Visitor* visitor, void* data) 61 | { 62 | visitor->visit(this, data); 63 | } 64 | 65 | void IfStatement::accept(Visitor* visitor, void* data) 66 | { 67 | visitor->visit(this, data); 68 | } 69 | 70 | void CompareStatement::accept(Visitor* visitor, void* data) 71 | { 72 | visitor->visit(this, data); 73 | } 74 | 75 | void TableDefine::accept(Visitor* visitor, void* data) 76 | { 77 | visitor->visit(this, data); 78 | } 79 | 80 | void TableNameField::accept(Visitor* visitor, void* data) 81 | { 82 | visitor->visit(this, data); 83 | } 84 | 85 | void TableArrayFiled::accept(Visitor* visitor, void* data) 86 | { 87 | visitor->visit(this, data); 88 | } 89 | 90 | void TableIndexField::accept(Visitor* visitor, void* data) 91 | { 92 | visitor->visit(this, data); 93 | } 94 | 95 | void TabMemberAccessor::accept(Visitor* visitor, void* data) 96 | { 97 | visitor->visit(this, data); 98 | } 99 | 100 | void TabIndexAccessor::accept(Visitor* visitor, void* data) 101 | { 102 | visitor->visit(this, data); 103 | } 104 | 105 | void NumericForStatement::accept(Visitor* visitor, void* data) 106 | { 107 | visitor->visit(this, data); 108 | } 109 | 110 | void GenericForStatement::accept(Visitor* visitor, void* data) 111 | { 112 | visitor->visit(this, data); 113 | } 114 | 115 | void BreakStatement::accept(Visitor* visitor, void* data) 116 | { 117 | visitor->visit(this, data); 118 | } 119 | 120 | 121 | 122 | -------------------------------------------------------------------------------- /Instruction.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include "Value.h" 4 | 5 | 6 | 7 | struct Instruction; 8 | class InstructionSet 9 | { 10 | public: 11 | enum Volum { 12 | None, 13 | Small, 14 | Medium, 15 | Large 16 | }; 17 | InstructionSet(Volum v); 18 | std::vector toVtInstructions(); 19 | 20 | Instruction* getInstructions(int& num) { num = _num; return _instructions; }; 21 | void pushInstruct(Instruction* ins) { 22 | _opcodes.push_back(ins); 23 | } 24 | Instruction* newInstruction(); 25 | 26 | void clearInstructions(); 27 | 28 | private: 29 | std::vector _opcodes; 30 | Instruction* _instructions; 31 | int _num; 32 | }; 33 | 34 | 35 | 36 | struct InstructionParam 37 | { 38 | enum InstructionParamType 39 | { 40 | InstructionParamType_None, 41 | InstructionParamType_Value, 42 | InstructionParamType_Name, 43 | InstructionParamType_Counter, 44 | InstructionParamType_CounterIndex, 45 | InstructionParamType_OpCodeIndex, 46 | InstructionParamType_ArrayIndex, 47 | }; 48 | 49 | InstructionParamType type; 50 | // struct Param{ 51 | // union { 52 | // Value *value; 53 | // String* name; 54 | // }; 55 | // //int array_index; 56 | // struct Counter { 57 | // int counter1; 58 | // int counter2; 59 | // }; 60 | // }; 61 | 62 | //Param param; 63 | 64 | struct Counter { 65 | int counter1; 66 | int counter2; 67 | }; 68 | 69 | union { 70 | Value *value; 71 | String* name; 72 | }; 73 | Counter counter; 74 | }; 75 | 76 | 77 | 78 | struct Instruction 79 | { 80 | enum OpCode 81 | { 82 | OpCode_UnKown, 83 | OpCode_Assign, 84 | OpCode_CleanStack, 85 | OpCode_GetLocalTable, 86 | OpCode_GetTable, 87 | OpCode_GetTableValue, 88 | OpCode_InitLocalVar, 89 | OpCode_GetLocalVar, 90 | OpCode_SetLocalVar, 91 | OpCode_Push, 92 | OpCode_Pop, 93 | OpCode_GenerateClosure, 94 | OpCode_GenerateBlock, 95 | OpCode_Ret, 96 | OpCode_GenerateArgTable, 97 | OpCode_MergeCounter, 98 | OpCode_ResetCounter, 99 | OpCode_DuplicateCounter, 100 | OpCode_Call, 101 | OpCode_EnterClosure, 102 | OpCode_QuitClosure, 103 | OpCode_EnterBlock, 104 | OpCode_QuitBlock, 105 | OpCode_AddGlobalTable, 106 | OpCode_DelGlobalTable, 107 | OpCode_Plus, 108 | OpCode_Minus, 109 | OpCode_Multiply, 110 | OpCode_Divide, 111 | OpCode_Mod, 112 | OpCode_Power, 113 | OpCode_Concat, 114 | OpCode_Less, 115 | OpCode_Greater, 116 | OpCode_LessEqual, 117 | OpCode_GreaterEqual, 118 | OpCode_NotEqual, 119 | OpCode_Equal, 120 | OpCode_Not, 121 | OpCode_Length, 122 | OpCode_Negative, 123 | OpCode_JmpTrue, 124 | OpCode_JmpFalse, 125 | OpCode_JmpNil, 126 | OpCode_Jmp, 127 | OpCode_NewTable, 128 | OpCode_SetTableArrayValue, 129 | 130 | OpCode_If, 131 | OpCode_NumericFor, 132 | OpCode_GenericFor, 133 | OpCode_Break, 134 | OpCode_TableDefine, 135 | OpCode_TableArrIndex, 136 | OpCode_TableMemAccess, 137 | OpCode_PassFunParam, 138 | }; 139 | OpCode op_code; 140 | int type; 141 | InstructionParam param; 142 | Instruction(); 143 | }; 144 | 145 | -------------------------------------------------------------------------------- /mlua.vcxproj: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {5AEFCDB7-51DA-4CE8-B228-3D1D07F75C87} 15 | mlua 16 | 17 | 18 | 19 | Application 20 | true 21 | v120 22 | MultiByte 23 | 24 | 25 | Application 26 | false 27 | v120 28 | true 29 | MultiByte 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | Level3 45 | Disabled 46 | true 47 | 48 | 49 | true 50 | 51 | 52 | 53 | 54 | Level3 55 | MaxSpeed 56 | true 57 | true 58 | true 59 | 60 | 61 | true 62 | true 63 | true 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /Value.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | 7 | class Closure; 8 | class String; 9 | class Function; 10 | struct Value 11 | { 12 | enum ValueT { 13 | TYPE_NIL, 14 | TYPE_BOOL, 15 | TYPE_NUMBER, 16 | TYPE_STRING, 17 | TYPE_TABLE, 18 | TYPE_TABLEVAL, 19 | TYPE_FUNCTION, 20 | TYPE_CLOSURE, 21 | TYPE_NATIVE_FUNCTION, 22 | TYPE_INSTRUCTVAL 23 | }; 24 | 25 | virtual int Type() const = 0; 26 | virtual std::string Name() const = 0; 27 | virtual bool IsEqual(const Value *other) const = 0; 28 | virtual std::size_t GetHash() const = 0; 29 | 30 | 31 | struct ValueHasher : public std::unary_function { 32 | std::size_t operator() (const Value *value) const { 33 | return value->GetHash(); 34 | } 35 | }; 36 | 37 | struct ValueEqualer : public std::binary_function { 38 | bool operator() (const Value *left, const Value *right) const { 39 | return left->IsEqual(right); 40 | } 41 | }; 42 | }; 43 | 44 | 45 | class Nil : public Value 46 | { 47 | public: 48 | Nil(){} 49 | virtual std::string Name() const { return "nil"; } 50 | virtual int Type() const { return TYPE_NIL; } 51 | virtual bool IsEqual(const Value *other) const; 52 | virtual std::size_t GetHash() const { return 0; } 53 | }; 54 | 55 | 56 | class BoolValue : public Value 57 | { 58 | public: 59 | BoolValue() : _valLogic(false){} 60 | BoolValue(bool b) : _valLogic(b){} 61 | virtual std::string Name() const { return "bool"; } 62 | virtual int Type() const { return TYPE_BOOL; } 63 | virtual bool IsEqual(const Value *other) const; 64 | virtual std::size_t GetHash() const { return 0; } 65 | 66 | void setLogicVal(bool b) { _valLogic = b; } 67 | bool getLogicVal() { return _valLogic; } 68 | 69 | private: 70 | bool _valLogic; 71 | }; 72 | 73 | 74 | 75 | 76 | class String : public Value 77 | { 78 | public: 79 | explicit String(const std::string& v) : _value(v) {} 80 | 81 | virtual std::string Name() const { return "string";} 82 | virtual int Type() const { return TYPE_STRING; } 83 | virtual bool IsEqual(const Value *other) const; 84 | std::string Get() { return _value; } 85 | const std::string& Get() const { return _value; } 86 | 87 | std::size_t GetHash() const { return std::hash()(_value); } 88 | 89 | String* concat(String* other); 90 | int getLen() { return _value.length(); } 91 | 92 | private: 93 | std::string _value; 94 | }; 95 | 96 | 97 | class Number : public Value 98 | { 99 | public: 100 | explicit Number(double v) : _value(v) {} 101 | 102 | virtual std::string Name() const { return "number"; } 103 | virtual int Type() const { return TYPE_NUMBER; } 104 | virtual bool IsEqual(const Value *other) const; 105 | const double Get() const { return _value; } 106 | 107 | std::size_t GetHash() const { return std::hash()(_value); } 108 | 109 | int GetInteger() const { return static_cast(floor(_value)); } 110 | bool IsInteger() const { return floor(_value) == _value; } 111 | void SetNumber(double d) { _value = d; } 112 | 113 | private: 114 | double _value; 115 | }; 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | class TableValue : public Value 125 | { 126 | public: 127 | friend class Table; 128 | explicit TableValue(Value *value) : _value(value){} 129 | 130 | virtual int Type() const { return TYPE_TABLEVAL; } 131 | virtual bool IsEqual(const Value *other) const { return _value->IsEqual(other); }; 132 | virtual std::string Name() const { return _value->Name(); } 133 | 134 | virtual std::size_t GetHash() const { return _value->GetHash(); } 135 | Value * GetValue() { return _value; } 136 | void SetValue(Value *value) { _value = value; } 137 | 138 | private: 139 | Value *_value; 140 | }; 141 | 142 | class Table : public Value 143 | { 144 | public: 145 | Table(); 146 | virtual std::string Name() const { return "table"; } 147 | virtual int Type() const { return TYPE_TABLE; } 148 | bool IsEqual(const Value *other) const { return this == other; } 149 | std::size_t GetHash() const { return std::hash()(this); } 150 | 151 | std::size_t GetArraySize() const; 152 | bool HaveKey(const Value *key) const; 153 | 154 | Value * GetValue(const Value *key); 155 | TableValue * GetTableValue(const Value *key); 156 | 157 | void ArrayAssign(std::size_t array_index, Value *value); 158 | void ArrayAssign(std::size_t array_index, TableValue *table_value); 159 | void Assign(const Value *key, Value *value); 160 | void Assign(const Value *key, TableValue *table_value); 161 | 162 | Table* clone(); 163 | int getLen(); 164 | Value* getNextValue(int i, Value** key); 165 | void setMeta(Table* t) { _meta = t; } 166 | 167 | private: 168 | typedef std::vector ArrayType; 169 | typedef std::unordered_map HashTableType; 170 | 171 | bool HashTableHasKey(const Value *key) const; 172 | bool ArrayHasKey(const Value *key) const; 173 | 174 | ArrayType* _array; 175 | HashTableType* _hash_table; 176 | Table* _meta; 177 | Table* __index; 178 | }; 179 | 180 | -------------------------------------------------------------------------------- /libs/BaseLib.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include "../Value.h" 3 | #include "../State.h" 4 | #include "../Function.h" 5 | #include "../Stack.h" 6 | #include "../Parser.h" 7 | #include "../Visitor.h" 8 | #include "../CodeWriter.h" 9 | #include "../CodeGenerate.h" 10 | #include "../VM.h" 11 | #include "BaseLib.h" 12 | #include 13 | #include 14 | #include 15 | 16 | 17 | void BaseLib::PrintType(Value* val) 18 | { 19 | if (val->Type() == Value::TYPE_STRING) { 20 | printf("%s", ((String*)val)->Get().c_str()); 21 | } 22 | else if (val->Type() == Value::TYPE_NUMBER) { 23 | if (((Number*)val)->IsInteger()) { 24 | printf("%d", ((Number*)val)->GetInteger()); 25 | } 26 | else { 27 | printf("%.14lg", ((Number*)val)->Get()); //这里可以四舍五入,也可以省略后面的0,完美输出,最多输出后面14位小数 28 | } 29 | } 30 | else if (val->Type() == Value::TYPE_NIL) { 31 | printf("nil"); 32 | } 33 | else if (val->Type() == Value::TYPE_CLOSURE) { 34 | printf("funciont: 0x%08x", val); 35 | } 36 | else if (val->Type() == Value::TYPE_TABLE) { 37 | printf("table: 0x%08x", val); 38 | } 39 | else if (val->Type() == Value::TYPE_TABLEVAL){ 40 | PrintType(((TableValue*)val)->GetValue()); 41 | } 42 | } 43 | 44 | 45 | int BaseLib::Print(State* state, void* num_) 46 | { 47 | std::vector vtVals; 48 | int num = state->getStack()->Size(); 49 | for (int i = (int)num - 1; i >= 0; i--) { 50 | Value* val = state->getStack()->popValue(); 51 | vtVals.push_back(val); 52 | } 53 | 54 | for (int i = (int)num - 1; i >= 0; i--) { 55 | Value* val = vtVals[i]; 56 | if (val) { 57 | PrintType(val); 58 | } 59 | printf("\t"); 60 | } 61 | printf("\n"); 62 | return 0; 63 | } 64 | 65 | int BaseLib::generatePairs(State* state, void*) 66 | { 67 | std::string strPairs = 68 | "local ipairsIter = function(t, i) \ 69 | i = i + 1\ 70 | local k, v = next(t, i) \ 71 | if v then return k, v end \ 72 | end\ 73 | return ipairsIter"; 74 | Parser parse(strPairs); 75 | TreeNode* root = parse.parse_block(); 76 | 77 | CodeGenerateVisitor codeGen; 78 | CodeWrite pairs; 79 | root->accept(&codeGen, &pairs); 80 | 81 | InstructionValue* func = pairs.fetchInstructionVal(); 82 | Value* t = state->getStack()->popValue(); 83 | state->getVM()->runCode(func); 84 | state->getStack()->Push(t); 85 | state->getStack()->Push(new Number(-1)); 86 | return 0; 87 | } 88 | 89 | int BaseLib::generateIPairs(State* state, void*) 90 | { 91 | std::string strPairs = 92 | "local ipairsIter = function(t, i) \ 93 | i = i + 1 \ 94 | local v = t[i] \ 95 | if v then return i, v end \ 96 | end\ 97 | return ipairsIter"; 98 | Parser parse(strPairs); 99 | TreeNode* root = parse.parse_block(); 100 | 101 | CodeGenerateVisitor codeGen; 102 | CodeWrite pairs; 103 | root->accept(&codeGen, &pairs); 104 | 105 | InstructionValue* func = pairs.fetchInstructionVal(); 106 | Value* t = state->getStack()->popValue(); 107 | state->getVM()->runCode(func); 108 | state->getStack()->Push(t); 109 | state->getStack()->Push(new Number(0)); 110 | return 0; 111 | } 112 | 113 | 114 | int BaseLib::next(State* state, void*) 115 | { 116 | Number* num = (Number*)state->getStack()->popValue(); 117 | int i = num->GetInteger(); 118 | Table* tab = (Table*)state->getStack()->popValue(); 119 | Value* key; 120 | Value* val = tab->getNextValue(i, &key); 121 | if (i < tab->GetArraySize()) { 122 | key = new Number(i); 123 | } 124 | if (val) { 125 | state->getStack()->Push(key); 126 | state->getStack()->Push(val); 127 | } 128 | else { 129 | state->getStack()->Push(new Nil()); 130 | state->getStack()->Push(new Nil()); 131 | //printf("invalid key to \'next\'\n"); 132 | } 133 | return 0; 134 | } 135 | 136 | int BaseLib::type(State* state, void*) 137 | { 138 | Value* val = state->getStack()->popValue(); 139 | if (val->Type() == Value::TYPE_NUMBER) { 140 | printf("number\n"); 141 | } 142 | else if (val->Type() == Value::TYPE_STRING) { 143 | printf("string\n"); 144 | } 145 | else if (val->Type() == Value::TYPE_FUNCTION) { 146 | printf("funciton\n"); 147 | } 148 | else if (val->Type() == Value::TYPE_CLOSURE) { 149 | printf("funciton\n"); 150 | } 151 | else if (val->Type() == Value::TYPE_NATIVE_FUNCTION) { 152 | printf("native function\n"); 153 | } 154 | else if (val->Type() == Value::TYPE_BOOL) { 155 | printf("bool\n"); 156 | } 157 | else if (val->Type() == Value::TYPE_TABLE) { 158 | printf("table\n"); 159 | } 160 | else if (val->Type() == Value::TYPE_NIL) { 161 | printf("nil\n"); 162 | } 163 | return 0; 164 | } 165 | 166 | int BaseLib::len(State* state, void*) 167 | { 168 | Value* val = state->getStack()->popValue(); 169 | Number* len = new Number(0); 170 | if (val->Type() == Value::TYPE_STRING) { 171 | int l = ((String*)val)->getLen(); 172 | len->SetNumber(l); 173 | } 174 | else if (val->Type() == Value::TYPE_TABLE) { 175 | int l = ((Table*)val)->getLen(); 176 | len->SetNumber(l); 177 | } 178 | state->getStack()->Push(len); 179 | return 0; 180 | } 181 | 182 | int BaseLib::setmeta(State* state, void*) 183 | { 184 | Table* tab2 = (Table*)state->getStack()->popValue(); 185 | Table* tab1 = (Table*)state->getStack()->popValue(); 186 | tab1->setMeta(tab2); 187 | return 0; 188 | } 189 | 190 | 191 | 192 | 193 | int BaseLib::StringLib::upper(State* state, void*) 194 | { 195 | String* str = (String*)state->getStack()->popValue(); 196 | int len = str->getLen(); 197 | char* bytes = new char[len + 1]; 198 | bytes[len] = 0; 199 | for (int i = 0; i < len; i++) { 200 | char c = str->Get().at(i); 201 | if (c >= 'a' && c <= 'z') { 202 | c = c - 0x20; 203 | } 204 | bytes[i] = c; 205 | } 206 | String* up = new String(std::string(bytes)); 207 | delete bytes; 208 | state->getStack()->Push(up); 209 | return 0; 210 | } 211 | 212 | int BaseLib::StringLib::substr(State* state, void* num) 213 | { 214 | std::list listVals; 215 | long n = (long)num; 216 | for (int i = 0; i < n; i++) { 217 | listVals.push_back(state->getStack()->popValue()); 218 | } 219 | int start = 0; 220 | int cnt = 0; 221 | Value* val[3] = {0}; 222 | for (int i = 0; i < n; i++) { 223 | val[i] = listVals.back(); 224 | listVals.pop_back(); 225 | } 226 | std::string strRaw; 227 | if (val[0]) { 228 | strRaw = ((String*)val[0])->Get(); 229 | } 230 | if (val[1]) { 231 | start = ((Number*)val[1])->GetInteger(); 232 | } 233 | if (val[2]) { 234 | cnt = ((Number*)val[2])->GetInteger(); 235 | } 236 | if (cnt < 0 || cnt > strRaw.length()) { 237 | cnt = strRaw.length(); 238 | } 239 | if (start >= strRaw.length()) { 240 | state->getStack()->Push(new Nil()); 241 | return 0; 242 | } 243 | std::string sub = strRaw.substr(start, cnt); 244 | state->getStack()->Push(new String(sub)); 245 | return 0; 246 | } 247 | 248 | int BaseLib::StringLib::byte(State* state, void* num) 249 | { 250 | std::list listVals; 251 | long n = (long)num; 252 | for (int i = 0; i < n; i++) { 253 | listVals.push_back(state->getStack()->popValue()); 254 | } 255 | int start = 0; 256 | int end = 0; 257 | Value* val[3] = { 0 }; 258 | for (int i = 0; i < n; i++) { 259 | val[i] = listVals.back(); 260 | listVals.pop_back(); 261 | } 262 | std::string strRaw; 263 | if (val[0]) { 264 | strRaw = ((String*)val[0])->Get(); 265 | } 266 | if (val[1]) { 267 | start = ((Number*)val[1])->GetInteger() - 1; 268 | } 269 | if (val[2]) { 270 | end = ((Number*)val[2])->GetInteger() - 1; 271 | } 272 | if (end < 0 || end >= strRaw.length()) { 273 | end = strRaw.length() - 1; 274 | } 275 | if (start >= strRaw.length()) { 276 | state->getStack()->Push(new Nil()); 277 | return 0; 278 | } 279 | for (int i = start; i <= end; i++) { 280 | char c = strRaw.at(i); 281 | state->getStack()->Push(new Number(c)); 282 | } 283 | 284 | return 0; 285 | } 286 | 287 | int BaseLib::StringLib::_char(State* state, void* num) 288 | { 289 | std::list listVals; 290 | long n = (long)num; 291 | for (int i = 0; i < n; i++) { 292 | listVals.push_back(state->getStack()->popValue()); 293 | } 294 | char* bytes = new char[n + 1]; 295 | bytes[n] = 0; 296 | for (int i = 0; i < n; i++) { 297 | Number* val = (Number*)listVals.back(); 298 | listVals.pop_back(); 299 | bytes[i] = val->GetInteger(); 300 | } 301 | std::string strRaw(bytes); 302 | delete bytes; 303 | state->getStack()->Push(new String(strRaw)); 304 | return 0; 305 | } 306 | 307 | Table* BaseLib::StringLib::generateStringTable() 308 | { 309 | Table* tab = new Table(); 310 | tab->Assign(new String("len"), new NativeFunc(BaseLib::len)); 311 | tab->Assign(new String("upper"), new NativeFunc(StringLib::upper)); 312 | tab->Assign(new String("substr"), new NativeFunc(StringLib::substr)); 313 | tab->Assign(new String("byte"), new NativeFunc(StringLib::byte)); 314 | tab->Assign(new String("char"), new NativeFunc(StringLib::_char)); 315 | return tab; 316 | } 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | int BaseLib::MathLib::_pow(State* state, void* num) 325 | { 326 | long n = (long)num; 327 | if (n != 2) { 328 | printf("error, params num error!\n"); 329 | } 330 | Number* index = (Number*)state->getStack()->popValue(); 331 | Number* base = (Number*)state->getStack()->popValue(); 332 | double ret = pow(base->Get(), index->Get()); 333 | state->getStack()->Push(new Number(ret)); 334 | return 0; 335 | } 336 | 337 | int BaseLib::MathLib::_random(State* state, void* num) 338 | { 339 | long n = (long)num; 340 | while (n > 0) { 341 | state->getStack()->popValue(); 342 | n--; 343 | } 344 | srand((unsigned int)time(0)); 345 | int rd = rand() % 10 ; 346 | state->getStack()->Push(new Number(rd)); 347 | return 0; 348 | } 349 | 350 | Table* BaseLib::MathLib::generateMathTable() 351 | { 352 | Table* tab = new Table(); 353 | tab->Assign(new String("pow"), new NativeFunc(MathLib::_pow)); 354 | tab->Assign(new String("rand"), new NativeFunc(MathLib::_random)); 355 | return tab; 356 | } -------------------------------------------------------------------------------- /GramTreeNode.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | using std::string; 10 | using std::stack; 11 | using std::vector; 12 | using std::list; 13 | 14 | #include "Scanner.h" 15 | #include "Value.h" 16 | #include "Function.h" 17 | 18 | 19 | 20 | class SubroutineBodyNode; 21 | class SubroutineDecNode; 22 | class CompondStatement; 23 | class ClassTreeNode; 24 | 25 | 26 | class Visitor; 27 | 28 | 29 | 30 | 31 | class SyntaxTreeNodeBase 32 | { 33 | public: 34 | static const int Child_Num_Const = 5; 35 | enum NodeKind { 36 | None, 37 | SUBROUTINE_DEC_K, 38 | BASIC_TYPE_K, 39 | CLASS_TYPE_K, 40 | NULL_K, 41 | PARAM_K, 42 | VAR_DEC_K, 43 | ARRAY_K, 44 | VAR_K, 45 | IF_STATEMENT_K, 46 | WHILE_STATEMENT_K, 47 | CALL_EXPRESSION_K, 48 | RETURN_STATEMENT_K, 49 | CALL_STATEMENT_K, 50 | BOOL_EXPRESSION_K, 51 | FUNCTION_CALL_K, 52 | COMPARE_K, 53 | OPERATION_K, 54 | BOOL_K, 55 | NAMELIST_K, //声明变量 56 | ASSIGN_K, 57 | SUBROUTINE_BODY_K, 58 | BOOL_CONST_K, 59 | NEGATIVE_K, 60 | INT_CONST_K, 61 | CHAR_CONST_K, 62 | STRING_CONST_K, 63 | KEY_WORD_CONST, 64 | THIS_K, 65 | TABLE_DEFINE_K, 66 | TABLE_NAME_FIELD_K, 67 | TABLE_INDEX_FIELD_K, 68 | TABLE_ARRAY_FIELD_K, 69 | FUNCTION_STM_K, 70 | BLOCK_K, 71 | CHUNK_K, 72 | FOR_K 73 | }; 74 | 75 | public: 76 | SyntaxTreeNodeBase(int nK = None); 77 | SyntaxTreeNodeBase(Scanner::Token t) { 78 | _token = t; 79 | } 80 | ~SyntaxTreeNodeBase(){} 81 | 82 | protected: 83 | SyntaxTreeNodeBase* _child[Child_Num_Const]; 84 | SyntaxTreeNodeBase* _pParent; 85 | SyntaxTreeNodeBase* _pNext; 86 | NodeKind _nodeKind; 87 | short _childIndex; //子类的索引 88 | short _siblings; //同等节点的个数 89 | 90 | Scanner::Token _token; 91 | 92 | public: 93 | void setToken(Scanner::Token& t) { 94 | _token = t; 95 | } 96 | Scanner::Token getToken() { 97 | return _token; 98 | } 99 | const string getLexeme() { 100 | return _token.lexeme; 101 | } 102 | void setLexeme(string& str) { 103 | _token.lexeme = str; 104 | } 105 | unsigned int getRow() { 106 | return _token.row; 107 | } 108 | void setNodeKind(int kind) { 109 | _nodeKind = (NodeKind)kind; 110 | } 111 | NodeKind getNodeKind() { 112 | return _nodeKind; 113 | } 114 | short getChildIndex() { 115 | return _childIndex; 116 | } 117 | 118 | void setNextNode(SyntaxTreeNodeBase* node) { 119 | if (node) { 120 | node->_childIndex = _childIndex; //这么理解,父亲有多个老婆,每个老婆有0到多个儿子,生母是同一个的孩子编号一样 121 | } 122 | _pNext = node; 123 | } 124 | short getSiblings() { 125 | return _siblings; 126 | } 127 | SyntaxTreeNodeBase* getNextNode() { 128 | return _pNext; 129 | } 130 | SyntaxTreeNodeBase* getParentNode() { 131 | return _pParent; 132 | } 133 | void setParentNode(SyntaxTreeNodeBase* node) { //也要把亲兄弟指定父类 134 | auto cur = this; 135 | while (cur) { 136 | cur->_pParent = node; 137 | cur = cur->getNextNode(); 138 | } 139 | } 140 | 141 | void addChild(SyntaxTreeNodeBase* pChild, int ind); 142 | 143 | SyntaxTreeNodeBase* getChildByIndex(int ind) { 144 | if (ind >= 0 && ind < Child_Num_Const) { 145 | return _child[ind]; 146 | } 147 | return nullptr; 148 | } 149 | 150 | virtual void accept(Visitor* visitor, void* data ); 151 | 152 | virtual string getName() { return ""; } 153 | virtual string getSignName() { return ""; } 154 | virtual SyntaxTreeNodeBase* getChildByTag(string name) { return nullptr; } 155 | 156 | virtual SyntaxTreeNodeBase* clone(); 157 | 158 | virtual void clear(bool next); 159 | }; 160 | 161 | 162 | 163 | 164 | typedef SyntaxTreeNodeBase TreeNode; 165 | 166 | class TreeNodeList 167 | { 168 | TreeNode* _head; 169 | TreeNode* _cur; 170 | public: 171 | TreeNodeList() { 172 | _head = _cur = nullptr; 173 | } 174 | void Push(TreeNode* node); 175 | TreeNode* getHeadNode() { 176 | return _head; 177 | } 178 | TreeNode* getCurNode() { 179 | return _cur; 180 | } 181 | TreeNode* joinBy(TreeNodeList* node2); //合并,第二个接上第一个,返回第一个的头 182 | static TreeNode* getCurNode(TreeNode* node); 183 | }; 184 | 185 | 186 | 187 | class ChunkNode : public SyntaxTreeNodeBase { 188 | public: 189 | ChunkNode() : SyntaxTreeNodeBase() { 190 | _nodeKind = CHUNK_K; 191 | } 192 | virtual ~ChunkNode(){} 193 | void accept(Visitor* visitor, void* data); 194 | }; 195 | 196 | 197 | class BlockNode : public SyntaxTreeNodeBase { 198 | public: 199 | BlockNode() : SyntaxTreeNodeBase() { 200 | _nodeKind = BLOCK_K; 201 | } 202 | virtual ~BlockNode(){} 203 | 204 | void accept(Visitor* visitor, void* data); 205 | }; 206 | 207 | class IdentifierNode : public SyntaxTreeNodeBase { 208 | public: 209 | IdentifierNode(Scanner::Token& t) : SyntaxTreeNodeBase() { 210 | _token = t; 211 | _val = nullptr; 212 | } 213 | virtual ~IdentifierNode(){} 214 | 215 | void accept(Visitor* visitor, void* data); 216 | 217 | Value* getVal(); 218 | private: 219 | Value* _val; 220 | 221 | }; 222 | 223 | class Terminator : public SyntaxTreeNodeBase { 224 | public: 225 | enum TermType { 226 | TERM_NIL, 227 | TERM_FALSE, 228 | TERM_TRUE, 229 | TERM_NUMBER, 230 | TERM_STRING, 231 | }; 232 | 233 | Terminator(Scanner::Token& t, TermType tt) : SyntaxTreeNodeBase() { 234 | _token = t; 235 | _type = tt; 236 | _val = nullptr; 237 | } 238 | virtual ~Terminator(){} 239 | 240 | void accept(Visitor* visitor, void* data); 241 | 242 | Value* getVal(); 243 | 244 | private: 245 | TermType _type; 246 | Value* _val; 247 | }; 248 | 249 | 250 | class UnaryExpression : public SyntaxTreeNodeBase { 251 | public: 252 | UnaryExpression(Scanner::Token& t) : SyntaxTreeNodeBase() { 253 | _token = t; 254 | } 255 | virtual ~UnaryExpression(){} 256 | 257 | void accept(Visitor* visitor, void* data); 258 | 259 | }; 260 | 261 | 262 | class VarDecNode : public SyntaxTreeNodeBase { //变量声明节点 263 | public: 264 | VarDecNode() : SyntaxTreeNodeBase() { 265 | _nodeKind = VAR_DEC_K; 266 | } 267 | enum EVarDec { 268 | VarDec_Type = 0, 269 | VarDec_Name 270 | }; 271 | virtual ~VarDecNode(){} 272 | SyntaxTreeNodeBase* getVarDecType() { return _child[VarDecNode::VarDec_Type]; } //变量的声明 273 | SyntaxTreeNodeBase* getVarDecName() { return _child[VarDecNode::VarDec_Name]; } //变量的名字 274 | 275 | }; 276 | 277 | 278 | class ParamNode : public VarDecNode { //形参节点 279 | public: 280 | ParamNode() : VarDecNode() { 281 | _nodeKind = PARAM_K; 282 | } 283 | virtual ~ParamNode(){} 284 | }; 285 | 286 | class LocalNameListStatement : public SyntaxTreeNodeBase { //声明语句 287 | public: 288 | LocalNameListStatement() : SyntaxTreeNodeBase() { 289 | _nodeKind = NAMELIST_K; 290 | } 291 | virtual ~LocalNameListStatement() {} 292 | 293 | enum LocalStatement { 294 | NameList = 0, 295 | ExpList 296 | }; 297 | 298 | SyntaxTreeNodeBase* getNameList() { return getChildByIndex(NameList); }; 299 | SyntaxTreeNodeBase* getExpList() { return getChildByIndex(ExpList); }; 300 | 301 | void accept(Visitor* visitor, void* data); 302 | }; 303 | 304 | class AssignStatement : public SyntaxTreeNodeBase { 305 | public: 306 | AssignStatement() : SyntaxTreeNodeBase() { 307 | _nodeKind = ASSIGN_K; 308 | } 309 | virtual ~AssignStatement(){} 310 | enum AStatement { 311 | AssignLetf = 0, 312 | AssignRight 313 | }; 314 | 315 | virtual SyntaxTreeNodeBase* getChildByTag(string name) override; 316 | SyntaxTreeNodeBase* getAssginLeft() { return _child[AssignLetf]; } 317 | SyntaxTreeNodeBase* getAssginRight() { return _child[AssignRight]; } 318 | 319 | void accept(Visitor* visitor, void* data); 320 | }; 321 | 322 | class OperateStatement : public SyntaxTreeNodeBase { 323 | public: 324 | enum OperateType { 325 | Plus, 326 | Minus, 327 | Multi, 328 | Div 329 | }; 330 | OperateStatement(OperateType type) : SyntaxTreeNodeBase() { 331 | _nodeKind = OPERATION_K; 332 | _opType = type; 333 | } 334 | virtual ~OperateStatement(){} 335 | 336 | SyntaxTreeNodeBase* getTermLeft() { return _child[0]; } 337 | SyntaxTreeNodeBase* getTermRight() { return _child[1]; } 338 | 339 | void accept(Visitor* visitor, void* data); 340 | 341 | OperateType _opType; 342 | }; 343 | 344 | class TableDefine : public SyntaxTreeNodeBase { //talbe节点 345 | public: 346 | TableDefine() : SyntaxTreeNodeBase() { 347 | _nodeKind = TABLE_DEFINE_K; 348 | } 349 | virtual ~TableDefine(){} 350 | 351 | void accept(Visitor* visitor, void* data); 352 | 353 | private: 354 | TreeNodeList _fieldList; 355 | 356 | public: 357 | void push_filed(TreeNode* node) { 358 | _fieldList.Push(node); 359 | } 360 | TreeNode* getField() { 361 | return _fieldList.getHeadNode(); 362 | } 363 | }; 364 | 365 | 366 | class TabMemberAccessor : public SyntaxTreeNodeBase { //table.member 367 | public: 368 | TabMemberAccessor() : SyntaxTreeNodeBase() { 369 | 370 | } 371 | virtual ~TabMemberAccessor(){} 372 | 373 | void accept(Visitor* visitor, void* data); 374 | 375 | }; 376 | 377 | 378 | class TabIndexAccessor : public SyntaxTreeNodeBase { //table[index] 379 | public: 380 | TabIndexAccessor() : SyntaxTreeNodeBase() { 381 | } 382 | virtual ~TabIndexAccessor(){} 383 | 384 | void accept(Visitor* visitor, void* data); 385 | 386 | }; 387 | 388 | 389 | //t = {1,2,[3]=3, d=5} 1,2是TableArrayFiled,[3]=7是TableIndexField,d=5是TableNameField 390 | 391 | class TableIndexField : public SyntaxTreeNodeBase { 392 | public: 393 | TableIndexField() : SyntaxTreeNodeBase() { 394 | _nodeKind = TABLE_INDEX_FIELD_K; 395 | } 396 | virtual ~TableIndexField(){} 397 | 398 | void accept(Visitor* visitor, void* data); 399 | }; 400 | 401 | class TableNameField : public SyntaxTreeNodeBase { 402 | public: 403 | TableNameField() : SyntaxTreeNodeBase() { 404 | _nodeKind = TABLE_NAME_FIELD_K; 405 | } 406 | virtual ~TableNameField(){} 407 | 408 | void accept(Visitor* visitor, void* data); 409 | }; 410 | 411 | class TableArrayFiled : public SyntaxTreeNodeBase { 412 | public: 413 | TableArrayFiled() : SyntaxTreeNodeBase() { 414 | _nodeKind = TABLE_ARRAY_FIELD_K; 415 | } 416 | virtual ~TableArrayFiled(){} 417 | 418 | void accept(Visitor* visitor, void* data); 419 | }; 420 | 421 | 422 | class NormalCallFunciton : public SyntaxTreeNodeBase { 423 | public: 424 | NormalCallFunciton() : SyntaxTreeNodeBase() { 425 | _nodeKind = FUNCTION_CALL_K; 426 | _needRetNum = 1; //一般需要的返回值是1个 427 | } 428 | virtual ~NormalCallFunciton(){} 429 | 430 | SyntaxTreeNodeBase* getCaller() { return _child[0]; } 431 | SyntaxTreeNodeBase* getParamList() { return _child[1]; } 432 | 433 | virtual void accept(Visitor* visitor, void* data); 434 | 435 | int _needRetNum; //需要返回值的个数 436 | }; 437 | 438 | 439 | class FunctionStatement : public SyntaxTreeNodeBase { 440 | public: 441 | FunctionStatement() : SyntaxTreeNodeBase() { 442 | _nodeKind = FUNCTION_STM_K; 443 | } 444 | virtual ~FunctionStatement(){} 445 | 446 | enum FuncStmt { 447 | EFuncName, 448 | EFuncParams, 449 | EFuncBody, 450 | EFunRet 451 | }; 452 | 453 | virtual void accept(Visitor* visitor, void* data); 454 | SyntaxTreeNodeBase* getFuncName() { return _child[EFuncName]; } 455 | SyntaxTreeNodeBase* getFuncParams() { return _child[EFuncParams]; } 456 | SyntaxTreeNodeBase* getFuncBody() { return _child[EFuncBody]; } 457 | SyntaxTreeNodeBase* getFuncRet() { return _child[EFunRet]; } 458 | 459 | void setGlobal(bool b) { _bGlobal = b; } 460 | bool getGlobal(){ return _bGlobal; } 461 | 462 | private: 463 | bool _bGlobal; 464 | }; 465 | 466 | 467 | class ReturnStatement : public SyntaxTreeNodeBase { 468 | public: 469 | ReturnStatement() : SyntaxTreeNodeBase() { 470 | _nodeKind = RETURN_STATEMENT_K; 471 | } 472 | ~ReturnStatement(){} 473 | 474 | virtual void accept(Visitor* visitor, void* data); 475 | }; 476 | 477 | 478 | 479 | class IfStatement : public SyntaxTreeNodeBase { 480 | public: 481 | IfStatement() : SyntaxTreeNodeBase() { 482 | _nodeKind = IF_STATEMENT_K; 483 | } 484 | enum eIfStmt { 485 | ECompare, 486 | EIf, 487 | EElseOrEnd 488 | }; 489 | 490 | virtual void accept(Visitor* visitor, void* data); 491 | }; 492 | 493 | class CompareStatement : public SyntaxTreeNodeBase { 494 | public: 495 | CompareStatement() : SyntaxTreeNodeBase() { 496 | _nodeKind = COMPARE_K; 497 | } 498 | enum eCmp { 499 | ECmpLef, 500 | ECmpRight 501 | }; 502 | 503 | virtual void accept(Visitor* visitor, void* data); 504 | }; 505 | 506 | 507 | class NumericForStatement : public SyntaxTreeNodeBase 508 | { 509 | public: 510 | NumericForStatement() : SyntaxTreeNodeBase() { 511 | _nodeKind = SyntaxTreeNodeBase::FOR_K; 512 | } 513 | void accept(Visitor* visitor, void* data); 514 | 515 | enum eFor { 516 | EStart, EEnd, EStep, EBlock 517 | }; 518 | private: 519 | }; 520 | 521 | class GenericForStatement : public SyntaxTreeNodeBase 522 | { 523 | public: 524 | GenericForStatement() : SyntaxTreeNodeBase() { 525 | _nodeKind = SyntaxTreeNodeBase::FOR_K; 526 | } 527 | void accept(Visitor* visitor, void* data); 528 | private: 529 | }; 530 | 531 | class BreakStatement : public SyntaxTreeNodeBase 532 | { 533 | public: 534 | BreakStatement() :SyntaxTreeNodeBase() { 535 | 536 | } 537 | void accept(Visitor* visitor, void* data); 538 | }; 539 | --------------------------------------------------------------------------------