[vm] return statements and start of procedure parsing
This commit is contained in:
parent
dc04c0463b
commit
08769c7a6d
2 changed files with 131 additions and 4 deletions
|
|
@ -21,6 +21,9 @@ strings :: #import "String"; // @future
|
|||
init(*parser, context.allocator);
|
||||
|
||||
ok := parse_string(*parser, #string END
|
||||
fn add(x, y) do return x + y end
|
||||
fn sub(x, y) do return x - y end
|
||||
|
||||
var x = 10.0
|
||||
var y = 20.0
|
||||
var z = x + y * 2.0 / 3.0
|
||||
|
|
|
|||
132
vm/parser.jai
132
vm/parser.jai
|
|
@ -13,6 +13,7 @@ Token :: struct {
|
|||
kw_var;
|
||||
kw_def;
|
||||
kw_type;
|
||||
kw_fn;
|
||||
kw_do;
|
||||
kw_end;
|
||||
kw_if;
|
||||
|
|
@ -61,12 +62,16 @@ Node :: struct {
|
|||
Kind :: enum {
|
||||
invalid;
|
||||
|
||||
block;
|
||||
|
||||
stmt_start;
|
||||
print;
|
||||
return_;
|
||||
stmt_end;
|
||||
|
||||
decl_start;
|
||||
variable;
|
||||
procedure;
|
||||
decl_end;
|
||||
|
||||
expr_start;
|
||||
|
|
@ -184,6 +189,50 @@ Node_Type :: struct {
|
|||
}
|
||||
}
|
||||
|
||||
/*
|
||||
fn add(x int, y int) int do return x + y end
|
||||
*/
|
||||
|
||||
Node_Procedure :: struct {
|
||||
#as using n: Node;
|
||||
n.kind = .procedure;
|
||||
|
||||
header: *Node_Procedure_Header;
|
||||
|
||||
args: [..]Node_Argument;
|
||||
rets: [..]Node_Argument;
|
||||
body: *Node_Block;
|
||||
flags: Flag;
|
||||
|
||||
Flag :: enum_flags {
|
||||
inline_;
|
||||
}
|
||||
}
|
||||
|
||||
Node_Argument :: struct {
|
||||
symbol: *Node_Symbol;
|
||||
type: *Node_Type;
|
||||
value: *Node; // always an expression, can be null
|
||||
}
|
||||
|
||||
Node_Procedure_Header :: struct {
|
||||
args: [..]*Node_Type;
|
||||
rets: [..]*Node_Type;
|
||||
}
|
||||
|
||||
Node_Block :: struct {
|
||||
#as using n: Node;
|
||||
n.kind = .block;
|
||||
body: [..]*Node;
|
||||
}
|
||||
|
||||
Node_Return :: struct {
|
||||
#as using n: Node;
|
||||
n.kind = .return_;
|
||||
|
||||
values: [..]*Node;
|
||||
}
|
||||
|
||||
Parser :: struct {
|
||||
allocator: Allocator;
|
||||
toplevel: [..]*Node;
|
||||
|
|
@ -210,9 +259,7 @@ parse_string :: (p: *Parser, source: string) -> bool {
|
|||
}
|
||||
|
||||
node := parse_toplevel(p);
|
||||
if node == null break;
|
||||
|
||||
array.append(*p.toplevel, node);
|
||||
if node != null array.append(*p.toplevel, node);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -222,7 +269,7 @@ parse_string :: (p: *Parser, source: string) -> bool {
|
|||
#scope_file;
|
||||
|
||||
parse_toplevel :: (p: *Parser) -> *Node {
|
||||
t, ok := expect_token(p, .kw_var, .kw_def, .kw_print);
|
||||
t, ok := expect_token(p, .kw_var, .kw_def, .kw_fn, .kw_print, .kw_do, .kw_return);
|
||||
basic.assert(ok, "var, def, print, found '%'", t.str); // @errors
|
||||
|
||||
if t.kind == {
|
||||
|
|
@ -269,6 +316,22 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
|||
|
||||
return node;
|
||||
|
||||
// return
|
||||
// return expr0, ..exprN
|
||||
case .kw_return;
|
||||
node := make_node(p, Node_Return);
|
||||
array.init(*node.values, p.allocator);
|
||||
|
||||
prev_offset := p.offset;
|
||||
expr := parse_expression(p);
|
||||
if expr == null {
|
||||
p.offset = prev_offset;
|
||||
return node;
|
||||
}
|
||||
|
||||
array.append(*node.values, expr);
|
||||
return node;
|
||||
|
||||
// print(expr)
|
||||
// print expr
|
||||
case .kw_print;
|
||||
|
|
@ -278,11 +341,71 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
|||
node := make_node(p, Node_Print);
|
||||
node.expr = expr;
|
||||
return node;
|
||||
|
||||
// fn symbol(arg0, ..argN) do end
|
||||
case .kw_fn;
|
||||
symbol, ok := expect_token(p, .symbol);
|
||||
basic.assert(ok, "expected name for procedure"); // @errors @todo(judah): lambdas
|
||||
|
||||
t, ok = expect_token(p, .l_paren);
|
||||
basic.assert(ok, "expected '(' but found '%'", t.str); // @errors
|
||||
|
||||
while !at_end(p) {
|
||||
t = peek_token(p);
|
||||
if t.kind == .r_paren break;
|
||||
|
||||
expr := parse_expression(p);
|
||||
basic.assert(expr != null); // @errors
|
||||
|
||||
t = peek_token(p);
|
||||
if t.kind == {
|
||||
case .comma;
|
||||
consume_token(p);
|
||||
continue;
|
||||
case .r_paren;
|
||||
break;
|
||||
case;
|
||||
basic.assert(false, "expected ',' or ')' but found '%'", t.str);
|
||||
}
|
||||
}
|
||||
|
||||
_, ok = expect_token(p, .r_paren);
|
||||
basic.assert(ok, "expected ')'"); // @errors
|
||||
|
||||
block := parse_block(p);
|
||||
basic.assert(block != null, "expected block"); // @errors
|
||||
|
||||
node := make_node(p, Node_Procedure);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
parse_block :: (p: *Parser) -> *Node_Block {
|
||||
t, ok := expect_token(p, .kw_do);
|
||||
basic.assert(ok, "expected 'do' found '%'", t.str); // @errors
|
||||
|
||||
block := make_node(p, Node_Block);
|
||||
array.init(*block.body, p.allocator);
|
||||
|
||||
while !at_end(p) {
|
||||
t = peek_token(p);
|
||||
if t.kind == .kw_end break;
|
||||
|
||||
node := parse_toplevel(p);
|
||||
basic.assert(node != null); // @errors
|
||||
|
||||
array.append(*block.body, node);
|
||||
}
|
||||
|
||||
t, ok = expect_token(p, .kw_end);
|
||||
basic.assert(ok, "expected 'end' found '%'", t.str); // @errors
|
||||
|
||||
return block;
|
||||
}
|
||||
|
||||
parse_type_expression :: (p: *Parser) -> *Node_Type {
|
||||
t, ok := expect_token(p, .symbol, .star, .l_square);
|
||||
basic.assert(ok, "type expression"); // @errors
|
||||
|
|
@ -596,6 +719,7 @@ consume_token :: (p: *Parser) -> Token {
|
|||
case "var"; t.kind = .kw_var;
|
||||
case "def"; t.kind = .kw_def;
|
||||
case "type"; t.kind = .kw_type;
|
||||
case "fn"; t.kind = .kw_fn;
|
||||
case "do"; t.kind = .kw_do;
|
||||
case "end"; t.kind = .kw_end;
|
||||
case "if"; t.kind = .kw_if;
|
||||
|
|
|
|||
Loading…
Reference in a new issue