mighty

The mighty programming language, compiler and tools (WIP)
Log | Files | Refs

commit 64c941a864332e2fa9813345b8885636ff124b5f
parent f27e8eb9a680a1d1d70e3ef0e95fa91662d374fa
Author: citbl <citbl@citbl.org>
Date:   Tue, 26 May 2026 20:48:40 +1000

parser wip

Diffstat:
Mmtcl/ast.lua | 14++++++++++++++
Mmtcl/parser.lua | 98++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------------
2 files changed, 96 insertions(+), 16 deletions(-)

diff --git a/mtcl/ast.lua b/mtcl/ast.lua @@ -14,6 +14,20 @@ function AST:use(lib) } end +function AST:binary(op, lhs, rhs) + return { + op = op, + lhs = lhs, + rhs = rhs, + } +end + +-- note the name/callee etc. usually carries the token so we have file/line/col +-- access via lexeme +function AST:call(callee, args) + return { callee = callee, args = args } +end + function AST:func(name, params, ret, body) return { kind = "func", diff --git a/mtcl/parser.lua b/mtcl/parser.lua @@ -1,6 +1,5 @@ local parser = { pos = 1, nodes = {} } local ast = require("ast") -local node = {} function parser:peek() return self.tokens[self.pos] or 0 @@ -36,32 +35,98 @@ function parser:add(ast) self.nodes[#self.nodes + 1] = ast end -function parser:parse_var() print("todo parse_var") end -function parser:parse_while() print("todo parse_while") end -function parser:parse_for() print("todo parse_for") end -function parser:parse_return() print("todo parse_return") end -function parser:parse_as_cast() print("todo parse_as_cast") end -function parser:parse_call() print("todo parse_call") end +function parser:parse_relational() end + +function parser:parse_equality() + local node = parser:parse_relational() + + while true do + if parser:peek().kind == TK.EQEQ then + local rhs = parser:parse_relational() + node = ast.binary(OP.EQUALITY, node, rhs) + -- elseif next == TK.BANGEQ then + -- todo inequality + else + break + end + end + return node +end + +function parser:parse_assignment_expr() + local left = parser:parse_equality() + + if parser:peek().kind == TK.EQ then + local right = parser:parse_assignment_expr() + -- todo check fail assignment target + -- todo make binary node + end + + return left +end + +function parser:parse_expr() + return parser:parse_assignment_expr() +end + +function parser:parse_var() + print("todo parse_var") +end +function parser:parse_while() + print("todo parse_while") +end +function parser:parse_for() + print("todo parse_for") +end +function parser:parse_return() + print("todo parse_return") +end +function parser:parse_as_cast() + print("todo parse_as_cast") +end +function parser:parse_call() + -- parse ident, parse parameters + local callee = parser:expect(TK.IDENT) + print("parse_call") + parser:expect(TK.L_PAREN) -- swallow ( + local args = {} + while parser:peek().kind ~= TK.R_PAREN do -- call parameters + local expr = parser:parse_expr() + args[#args + 1] = expr + if parser:peek().kind == TK.COMMA then + parser:advance() + else + break + end + end + return ast.call(callee, args) +end function parser:parse_statement() local first = parser:peek().kind local second = parser:nextpeek().kind - print("todo parse statement: " .. first) if first == TK.IDENT then if second == TK.L_PAREN then - parser:parse_call() + return parser:parse_call() elseif second == TK.IDENT then - parser:parse_var() + return parser:parse_var() + else + print("parse_statement unhandled ident start with: " .. second) end elseif first == TK.KEYWORD then local kw = parser:peek() - if kw.lexeme == "while" then parse:parse_while() - elseif kw.lexeme == "for" then parse:parse_for() - elseif kw.lexeme == "return" then parse:parse_return() - elseif kw.lexeme == "as" then parse:parse_as_cast() + if kw.lexeme == "while" then + return parser:parse_while() + elseif kw.lexeme == "for" then + return parser:parse_for() + elseif kw.lexeme == "return" then + return parser:parse_return() + elseif kw.lexeme == "as" then + return parser:parse_as_cast() + else + print("parse_statement unhandled keyword yet: " .. kw.lexeme) end end - parser:advance() end function parser:parse_function(is_exported) @@ -99,8 +164,9 @@ function parser:parse_function(is_exported) -- function body statements local stmt = parser:parse_statement() statements[#statements + 1] = stmt + parser:advance() end - local node = ast.func(name, params, ret, statements) + local node = ast.func(name, parameters, ret, statements) parser:add(node) end