diff --git a/compiler.lua b/compiler.lua new file mode 100644 index 0000000..d471cfa --- /dev/null +++ b/compiler.lua @@ -0,0 +1,166 @@ +--~ t = debug.getmetatable ("") +--~ t.__index = function(self,k) +--~ if type(k)=="number" then +--~ return string.sub(self,k,k) +--~ end +--~ end +Token = {} +Token.__index = Token +local INTEGER, PLUS, EOF, MINUS, MUL, DIV, LPAREN, RPAREN = "INT","+","EOF", "-", "*", "/", "(", ")" +function Token.__tostring(self) + return string.format("Token(%s, %s)",self.type,self.value) +end +function Token:new(tp,val) + local c = {} + setmetatable(c,self) + c.type = tp + c.value = val + print("Token:"..tp) + return c +end + +Lexer = {} +Lexer.__index = Lexer +function Lexer:new(text) + local c = {} + setmetatable(c,self) + self.text = text + self.pos = 1 + self.current_char = self.text:sub(1,1) + self.stop = false + return c +end +function Lexer:advance() + self.pos = self.pos + 1 + if self.pos > #self.text then + self.current_char = false + else + self.current_char = self.text:sub(self.pos,self.pos) + end +end +function Lexer:error() + error("Invalid character") +end +function Lexer:skip_whitespace() + while self.current_char and self.current_char:match("%s") do + self:advance() + end +end +function Lexer:integer() + local result = {} + while self.current_char and self.current_char:match("%d") do + table.insert(result,self.current_char) + self:advance() + end + return tonumber(table.concat(result)) +end +function Lexer:get_next_token() + while self.current_char do + ::continue:: + if self.current_char:match("%s") then + self:skip_whitespace() + goto continue + end + if self.current_char:match("%d") then + return Token:new(INTEGER,self:integer()) + end + if self.current_char == "+" then + self:advance() + return Token:new(PLUS,"+") + end + if self.current_char == "-" then--55+77 + self:advance() + return Token:new(MINUS,"-") + end + if self.current_char == "*" then + self:advance() + return Token:new(MUL,"*") + end + if self.current_char == "/" then + self:advance() + return Token:new(DIV,"/") + end + if self.current_char == "(" then + self:advance() + return Token:new(LPAREN,"(") + end + if self.current_char == ")" then + self:advance() + return Token:new(RPAREN,")") + end + self:error("Invalid Symbol!") + end + return Token:new(EOF, nil) +end + +Interpreter = {} +Interpreter.__index = Interpreter +function Interpreter:new(lexer) + local c = {} + setmetatable(c,self) + c.lexer = lexer + c.current_token = c.lexer:get_next_token() + return c +end +function Interpreter:error() + error('Error Invalid Syntax') +end +function Interpreter:eat(token_type) + if self.current_token.type == token_type then + self.current_token = self.lexer:get_next_token() + else + self:error() + end +end +function Interpreter:factor() + local token = self.current_token + if token.type == INTEGER then + self:eat(INTEGER) + return token.value + elseif token.type == LPAREN then + self:eat(LPAREN) + local result = self:expr() + self:eat(RPAREN) + return result + end +end +function Interpreter:term() + local result = self:factor() + local token + while self.current_token.type == MUL or self.current_token.type == DIV do + token = self.current_token + if token.type == MUL then + self:eat(MUL) + result = result * self:factor() + elseif token.type == DIV then + self:eat(DIV) + result = result / self:factor() + end + end + return result +end +function Interpreter:expr() + local result = self:term() + local token + while self.current_token.type == PLUS or self.current_token.type == MINUS do + token = self.current_token + if token.type == PLUS then + self:eat(PLUS) + result = result + self:term() + elseif token.type == MINUS then + self:eat(MINUS) + result = result - self:term() + end + end + return result +end +while true do + io.write("calc> ") + local text = io.read() + if text then + l = Lexer:new(text) + i = Interpreter:new(l) + result = i:expr() + print(result) + end +end diff --git a/test.lua b/test.lua deleted file mode 100644 index 7124891..0000000 --- a/test.lua +++ /dev/null @@ -1,5 +0,0 @@ -package.path = "./?/init.lua;"..package.path -local pm = require("parseManager") -state = pm:load("test.dms") -print(state:dump()) -state:think() \ No newline at end of file