[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);
|
init(*parser, context.allocator);
|
||||||
|
|
||||||
ok := parse_string(*parser, #string END
|
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 x = 10.0
|
||||||
var y = 20.0
|
var y = 20.0
|
||||||
var z = x + y * 2.0 / 3.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_var;
|
||||||
kw_def;
|
kw_def;
|
||||||
kw_type;
|
kw_type;
|
||||||
|
kw_fn;
|
||||||
kw_do;
|
kw_do;
|
||||||
kw_end;
|
kw_end;
|
||||||
kw_if;
|
kw_if;
|
||||||
|
|
@ -61,12 +62,16 @@ Node :: struct {
|
||||||
Kind :: enum {
|
Kind :: enum {
|
||||||
invalid;
|
invalid;
|
||||||
|
|
||||||
|
block;
|
||||||
|
|
||||||
stmt_start;
|
stmt_start;
|
||||||
print;
|
print;
|
||||||
|
return_;
|
||||||
stmt_end;
|
stmt_end;
|
||||||
|
|
||||||
decl_start;
|
decl_start;
|
||||||
variable;
|
variable;
|
||||||
|
procedure;
|
||||||
decl_end;
|
decl_end;
|
||||||
|
|
||||||
expr_start;
|
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 {
|
Parser :: struct {
|
||||||
allocator: Allocator;
|
allocator: Allocator;
|
||||||
toplevel: [..]*Node;
|
toplevel: [..]*Node;
|
||||||
|
|
@ -210,9 +259,7 @@ parse_string :: (p: *Parser, source: string) -> bool {
|
||||||
}
|
}
|
||||||
|
|
||||||
node := parse_toplevel(p);
|
node := parse_toplevel(p);
|
||||||
if node == null break;
|
if node != null array.append(*p.toplevel, node);
|
||||||
|
|
||||||
array.append(*p.toplevel, node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
@ -222,7 +269,7 @@ parse_string :: (p: *Parser, source: string) -> bool {
|
||||||
#scope_file;
|
#scope_file;
|
||||||
|
|
||||||
parse_toplevel :: (p: *Parser) -> *Node {
|
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
|
basic.assert(ok, "var, def, print, found '%'", t.str); // @errors
|
||||||
|
|
||||||
if t.kind == {
|
if t.kind == {
|
||||||
|
|
@ -269,6 +316,22 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
||||||
|
|
||||||
return 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)
|
||||||
// print expr
|
// print expr
|
||||||
case .kw_print;
|
case .kw_print;
|
||||||
|
|
@ -278,11 +341,71 @@ parse_toplevel :: (p: *Parser) -> *Node {
|
||||||
node := make_node(p, Node_Print);
|
node := make_node(p, Node_Print);
|
||||||
node.expr = expr;
|
node.expr = expr;
|
||||||
return node;
|
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;
|
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 {
|
parse_type_expression :: (p: *Parser) -> *Node_Type {
|
||||||
t, ok := expect_token(p, .symbol, .star, .l_square);
|
t, ok := expect_token(p, .symbol, .star, .l_square);
|
||||||
basic.assert(ok, "type expression"); // @errors
|
basic.assert(ok, "type expression"); // @errors
|
||||||
|
|
@ -596,6 +719,7 @@ consume_token :: (p: *Parser) -> Token {
|
||||||
case "var"; t.kind = .kw_var;
|
case "var"; t.kind = .kw_var;
|
||||||
case "def"; t.kind = .kw_def;
|
case "def"; t.kind = .kw_def;
|
||||||
case "type"; t.kind = .kw_type;
|
case "type"; t.kind = .kw_type;
|
||||||
|
case "fn"; t.kind = .kw_fn;
|
||||||
case "do"; t.kind = .kw_do;
|
case "do"; t.kind = .kw_do;
|
||||||
case "end"; t.kind = .kw_end;
|
case "end"; t.kind = .kw_end;
|
||||||
case "if"; t.kind = .kw_if;
|
case "if"; t.kind = .kw_if;
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue