✨ syntaxic sugar for function declaration.
parent
603dc6f53a
commit
06b379c99c
|
@ -8,6 +8,9 @@ EXPR ::=
|
|||
| BLOCK
|
||||
| IF
|
||||
| return EXPR
|
||||
| FUN_DECL
|
||||
FUN_DECL ::=
|
||||
| fun ident opar PARAMS cpar EXPR* end
|
||||
IF ::= if EXPR BLOCK (else (BLOCK | IF))?
|
||||
BLOCK ::= begin EXPR* end
|
||||
ASSIGN ::= ident assign EXPR
|
||||
|
|
|
@ -80,3 +80,8 @@ assert k() eq 39
|
|||
assert k() eq 40
|
||||
assert k() eq 41
|
||||
|
||||
fun l(x)
|
||||
3 * x
|
||||
end
|
||||
|
||||
assert l(7) eq 21
|
||||
|
|
|
@ -19,6 +19,7 @@ struct node* parser_try(struct parser* self,
|
|||
struct node* parser_try_parse(struct parser* self);
|
||||
struct node* parser_try_root(struct parser* self);
|
||||
struct node* parser_try_expr(struct parser* self);
|
||||
struct node* parser_try_fun_decl(struct parser* self);
|
||||
struct node* parser_try_block(struct parser* self);
|
||||
struct node* parser_try_inner_block(struct parser* self);
|
||||
struct node* parser_try_if(struct parser* self);
|
||||
|
|
|
@ -137,9 +137,73 @@ struct node* parser_try_expr(struct parser* self)
|
|||
return SK_TRY(parser_try_if);
|
||||
}
|
||||
|
||||
if (lexer_next_is(&self->lexer, TOKEN_FUN)
|
||||
&& lexer_next_nth_is(&self->lexer, TOKEN_IDENT, 1))
|
||||
{
|
||||
return SK_TRY(parser_try_fun_decl);
|
||||
}
|
||||
|
||||
return SK_TRY(parser_try_or);
|
||||
}
|
||||
|
||||
struct node* parser_try_fun_decl(struct parser* self)
|
||||
{
|
||||
if (!lexer_next_is(&self->lexer, TOKEN_FUN))
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct node* fun = malloc(sizeof(struct node));
|
||||
node_init(fun, NODE_FUN, lexer_try_new_next(&self->lexer));
|
||||
|
||||
if (!lexer_next_is(&self->lexer, TOKEN_IDENT))
|
||||
{
|
||||
node_free(fun);
|
||||
free(fun);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct node* ident = malloc(sizeof(struct node));
|
||||
node_init(ident, NODE_IDENT,
|
||||
lexer_try_new_next(&self->lexer));
|
||||
|
||||
if (!lexer_next_is(&self->lexer, TOKEN_OPAR))
|
||||
{
|
||||
node_free(fun); free(fun);
|
||||
node_free(ident); free(ident);
|
||||
return NULL;
|
||||
}
|
||||
lexer_consume_next(&self->lexer);
|
||||
|
||||
struct node* params = SK_TRY(parser_try_params);
|
||||
node_push_new_child(fun, params);
|
||||
|
||||
if (!lexer_next_is(&self->lexer, TOKEN_CPAR))
|
||||
{
|
||||
node_free(fun); free(fun);
|
||||
node_free(ident); free(ident);
|
||||
return NULL;
|
||||
}
|
||||
lexer_consume_next(&self->lexer);
|
||||
|
||||
struct node* body = SK_TRY(parser_try_inner_block);
|
||||
node_push_new_child(fun, body);
|
||||
|
||||
if (!lexer_next_is(&self->lexer, TOKEN_END))
|
||||
{
|
||||
node_free(fun); free(fun);
|
||||
node_free(ident); free(ident);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct node* node = malloc(sizeof(struct node));
|
||||
node_init(node, NODE_CONST_DECL, lexer_try_new_next(&self->lexer));
|
||||
|
||||
node_push_new_child(node, ident);
|
||||
node_push_new_child(node, fun);
|
||||
return node;
|
||||
}
|
||||
|
||||
struct node* parser_try_block(struct parser* self)
|
||||
{
|
||||
assert(self);
|
||||
|
|
|
@ -140,6 +140,11 @@ static void test_parser_function()
|
|||
test_parser("ROOT(FUN(PARAMS,BLOCK))",
|
||||
"fun () end");
|
||||
|
||||
test_parser("ROOT(CONST_DECL(IDENT[hello]"
|
||||
",FUN(PARAMS(IDENT[x],IDENT[y]),"
|
||||
"BLOCK(INT[0],INT[1]))))",
|
||||
"fun hello (x, y) 0 1 end");
|
||||
|
||||
test_parser("ROOT(CALL(IDENT[hello],ARGS))",
|
||||
"hello()");
|
||||
|
||||
|
|
Loading…
Reference in New Issue