Author | Jakob Wakeling <[email protected]> |
Date | 2022-03-28 02:26:44 |
Commit | d47751def35f23c73f6722584cf0cf4934db9e36 |
Parent | af7cced8bd1c8b0e4115d10b679876174792068f |
parse: Implement if and for statement parsing
Diffstat
M | src/parse.c | | | 40 | ++++++++++++++++++++++++++++++---------- |
M | src/parse.h | | | 3 | +-- |
2 files changed, 31 insertions, 12 deletions
diff --git a/src/parse.c b/src/parse.c index 313d6e2..3555ea4 100644 --- a/src/parse.c +++ b/src/parse.c @@ -43,14 +43,14 @@ ast *ast_init(void) { ast *a = calloc(1, sizeof (ast)); if (!a) { error(1, SERR); } return a; } -// void ast_free(ast *a) {} /* Push a child AST node to an AST node. */ -s32 ast_push(ast *a, ast *c) { +void ast_push(ast *a, ast *c) { ast **ca = realloc(a->c.a, (a->c.al += 1) * sizeof (ast *)); if (!ca) { error(1, SERR); } else { a->c.a = ca; ca = NULL; } - a->c.a[a->c.al - 1] = c; return 0; + /* Store pointer from parent to child and vice versa */ + c->p = a; a->c.a[a->c.al - 1] = c; } #define T (l->t) /* lex_peek equivalent */ @@ -124,9 +124,6 @@ static ast *parse_stmt_decl(lex *l, syt *st) { if (T.k == TK_COLON || T.k == TK_ASSIGN) { lex_next(l); ast_push(sm.a, parse_expr(l, st)); } else { error(1, "%s:%zu:%zu: error: expected ':' or '='", l->n, T.ln + 1, T.cl + 1); } - /* Store the parent AST node in the child */ - sm.a->c.a[0]->p = sm.a; - /* Parse a semicolon if one is required */ if (sm.a->c.a[0]->k != AK_PROC) { lex_kind(l, TK_SCOLON); } @@ -136,7 +133,7 @@ static ast *parse_stmt_decl(lex *l, syt *st) { /* Parse an expression statement. */ static ast *parse_stmt_expr(lex *l, syt *st) { - ast *a; if (T.k != TK_SCOLON) { a = parse_expr(l, st); } + ast *a = NULL; if (T.k != TK_SCOLON) { a = parse_expr(l, st); } lex_kind(l, TK_SCOLON); return a; } @@ -151,10 +148,30 @@ static ast *parse_stmt_return(lex *l, syt *st) { } /* Parse an if statement. */ -static ast *parse_stmt_if(lex *l, syt *st) { /* TODO */ } +static ast *parse_stmt_if(lex *l, syt *st) { + lex_kind(l, TK_IF); lex_kind(l, TK_LPAREN); + ast *a = ast_init(); a->k = AK_IF; + + /* Parse expression and closing parenthesis */ + ast_push(a, parse_expr(l, st)); lex_kind(l, TK_RPAREN); + + /* Parse the if statement body */ + ast_push(a, parse_stmt(l, st)); return a; +} /* Parse a for statement. */ -static ast *parse_stmt_for(lex *l, syt *st) { /* TODO */ } +static ast *parse_stmt_for(lex *l, syt *st) { + lex_kind(l, TK_FOR); lex_kind(l, TK_LPAREN); + ast *a = ast_init(); a->k = AK_FOR; + + /* Parse one to three expressions and a closing parenthesis */ + ast_push(a, parse_stmt_expr(l, st)); + ast_push(a, parse_stmt_expr(l, st)); + ast_push(a, parse_expr(l, st)); lex_kind(l, TK_RPAREN); + + /* Parse the for statement body */ + ast_push(a, parse_stmt(l, st)); return a; +} /* Parse an expression. */ static ast *parse_expr(lex *l, syt *st) { @@ -206,7 +223,7 @@ static ast *parse_int(lex *l) { /* Recursively print an AST. */ void ast_print(ast *a, UINT i) { for (UINT j = 0; j != i; ++j) { printf(" "); } - printf("%zu:%zu: %s: %s", a->ln, a->cl, ast_ks[a->k], a->s); + printf("%zu:%zu: %s: %s", a->ln + 1, a->cl + 1, ast_ks[a->k], a->s); if (a->k == AK_PROC) { printf(" -> %s", a->t->s); } fputc('\n', stdout); diff --git a/src/parse.h b/src/parse.h index 11fe029..67eaab7 100644 --- a/src/parse.h +++ b/src/parse.h @@ -32,8 +32,7 @@ typedef struct ast_s { extern char *ast_ks[]; extern ast *ast_init(void); -extern void ast_free(ast *a); -extern s32 ast_push(ast *a, ast *c); +extern void ast_push(ast *a, ast *c); extern ast *parse(lex *l);