Author | Jakob Wakeling <[email protected]> |
Date | 2022-01-25 12:42:02 |
Commit | 44d040093e5e4e9f401d0f1e676fd4802ecd2109 |
Parent | 092464359b4127320fbed1380200df5f90c3f8b9 |
parse: Add type parsing for decl's and proc's
Diffstat
M | src/parse.c | | | 143 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------------- |
1 files changed, 102 insertions, 41 deletions
diff --git a/src/parse.c b/src/parse.c index a577c95..81d8f1f 100644 --- a/src/parse.c +++ b/src/parse.c @@ -28,12 +28,12 @@ char *ast_ks[] = { static ast *parse_decl(lex *l, syt *st); -static ast *parse_stmt(lex *l); -static ast *parse_stmt_compound(lex *l); +static ast *parse_stmt(lex *l, syt *st); +static ast *parse_stmt_compound(lex *l, syt *st); -static ast *parse_expr(lex *l); +static ast *parse_expr(lex *l, syt *st); -static ast *parse_proc(lex *l); +static ast *parse_proc(lex *l, syt *st); static ast *parse_int(lex *l); @@ -73,63 +73,88 @@ ast *parse(lex *l) { /* Parse a declaration. */ static ast *parse_decl(lex *l, syt *st) { + /* Store the declaration's line, column, hash, and identifier */ sym sm = { SK_NULL, T.ln, T.cl, T.h, T.s }; lex_kind(l, LK_ID); lex_kind(l, LK_COLON); - if (T.k == LK_ID) { /* TODO lookup and store type */ } - if (T.k == LK_SCOLON) { error(1, "LK_SCOLON (parse_decl)"); } - - switch (T.k) { - case LK_COLON: { lex_kind(l, LK_COLON); } goto decl_expr; - case LK_ASSIGN: { lex_kind(l, LK_ASSIGN); } goto decl_expr; - decl_expr: { - sm.a = ast_aloc(); sm.a->k = AK_DECL; sm.a->s = strdup(sm.s); - ast_push(sm.a, parse_expr(l)); - } break; - default: { error( - 1, "%s:%zu:%zu: error: Unexpected: \"%s\" (parse_decl)", - l->n, lex_peek(l).ln + 1, lex_peek(l).cl + 1, tok_ks[lex_peek(l).k] - ); } break; + /* Search for a store the declaration's type if specified */ + if (T.k == LK_ID) { + sym s = syt_search_h(st, T.h, T.s); + + if (s.k == SK_NULL) { error( /* ERROR */ + 1, "%s:%zu:%zu: error: use of undeclared identifier \"%s\"", + l->n, T.ln + 1, T.cl + 1, T.s + ); } + if (s.k != SK_TYPE) { error( /* ERROR */ + 1, "%s:%zu:%zu: error: expected type identifier", + l->n, T.ln + 1, T.cl + 1 + ); } + + sm.t = s.t; lex_next(l); + + if (T.k == LK_SCOLON) { + /* Allocate the AST and skip ahead */ + lex_next(l); sm.a = ast_aloc(); sm.a->k = AK_DECL; + sm.a->s = strdup(sm.s); sm.k = SK_NASS; goto decl; + } + } + else if (T.k == LK_SCOLON) { error( /* ERROR */ + 1, "%s:%zu:%zu: error: a declaration without a type is invalid", + l->n, T.ln + 1, T.cl + 1 + ); } + + /* Assign a constant or variable value */ + if (T.k == LK_COLON || T.k == LK_ASSIGN) { + lex_next(l); sm.a = ast_aloc(); sm.a->k = AK_DECL; + sm.a->s = strdup(sm.s); ast_push(sm.a, parse_expr(l, st)); + } + else { error( /* ERROR */ + 1, "%s:%zu:%zu: error: expected ':' or '='", + l->n, T.ln + 1, T.cl + 1 + ); } + + switch (sm.a->c.a[0]->k) { + case AK_PROC: { sm.k = SK_PROC; } break; + // if (sm.a->c.a[0]->k == AK_PROC) { sm.a->c.a[0]->s = sm.a->s; } + default: { sm.k = SK_NASS; } break; /* TODO */ + // default: { error( /* ERROR */ + // 1, "%s:%zu:%zu: error: unhandled AST kind \"%s\"", + // l->n, T.ln + 1, T.cl + 1, ast_ks[sm.a->k] + // ); } break; } - if (sm.a->c.a[0]->k == AK_PROC) { sm.a->c.a[0]->s = sm.a->s; } - - assert(sm.h != 0); + decl:; assert(sm.h != 0); /* Confirm that the identifier is not a keyword */ - if (syt_lookup_h(&kwt, sm.h, sm.s).h != 0) { - error( - 1, "%s:%zu:%zu: error: keyword '%s' (parse_decl)", - l->n, sm.ln + 1, sm.cl + 1, sm.s - ); - } + if (syt_lookup_h(&kwt, sm.h, sm.s).k != SK_NULL) { error( /* ERROR */ + 1, "%s:%zu:%zu: error: redefinition of keyword \"%s\"", + l->n, sm.ln + 1, sm.cl + 1, sm.s + ); } /* Confirm that the identifier is not being reused */ - if (syt_lookup_h(st, sm.h, sm.s).h != 0) { - error( - 1, "%s:%zu:%zu: error: redefinition of '%s' (parse_decl)", - l->n, sm.ln + 1, sm.cl + 1, sm.s - ); - } + if (syt_lookup_h(st, sm.h, sm.s).k != SK_NULL) { error( /* ERROR */ + 1, "%s:%zu:%zu: error: redefinition of identifier \"%s\"", + l->n, sm.ln + 1, sm.cl + 1, sm.s + ); } /* Otherwise insert the new symbol and return */ syt_insert_h(st, sm.h, sm.s, sm); return sm.a; } /* Parse a statement. */ -static ast *parse_stmt(lex *l) { - if (lex_peek(l).k == LK_LBRACE) { return parse_stmt_compound(l); } +static ast *parse_stmt(lex *l, syt *st) { + if (T.k == LK_LBRACE) { return parse_stmt_compound(l, st); } ast *a = ast_aloc(); - switch (lex_peek(l).k) { + switch (T.k) { case LK_RETURN: { - lex_kind(l, LK_RETURN); a->k = AK_RETURN; ast_push(a, parse_expr(l)); + lex_kind(l, LK_RETURN); a->k = AK_RETURN; ast_push(a, parse_expr(l, st)); } break; default: { error( - 1, "%zu:%zu: Unexpected: \"%s\" (parse_stmt)", - lex_peek(l).ln + 1, lex_peek(l).cl + 1, tok_ks[lex_peek(l).k] + 1, "%s:%zu:%zu: Unexpected: \"%s\" (parse_stmt)", + l->n, T.ln + 1, T.cl + 1, tok_ks[T.k] ); } break; } @@ -137,58 +162,62 @@ static ast *parse_stmt(lex *l) { } /* Parse a compound statement. */ -static ast *parse_stmt_compound(lex *l) { +static ast *parse_stmt_compound(lex *l, syt *st) { lex_kind(l, LK_LBRACE); ast *a = ast_aloc(); a->k = AK_COMP; syt_init(&a->st); /* Parse statements until EOF or closing brace */ - for (; lex_peek(l).k != LK_EOF && lex_peek(l).k != LK_RBRACE;) { - ast_push(a, parse_stmt(l)); + for (; T.k != LK_EOF && T.k != LK_RBRACE;) { + ast_push(a, parse_stmt(l, &a->st)); } lex_kind(l, LK_RBRACE); return a; } /* Parse an expression. */ -static ast *parse_expr(lex *l) { - ast *a = ast_aloc(); - - switch (lex_peek(l).k) { - case LK_PROC: { return parse_proc(l); } break; +static ast *parse_expr(lex *l, syt *st) { + switch (T.k) { + case LK_PROC: { return parse_proc(l, st); } break; case LK_INT: { return parse_int(l); } break; default: { error( - 1, "%zu:%zu: Unexpected: \"%s\" (parse_expr)", - lex_peek(l).ln + 1, lex_peek(l).cl + 1, tok_ks[lex_peek(l).k] + 1, "%s:%zu:%zu: Unexpected: \"%s\" (parse_expr)", + l->n, T.ln + 1, T.cl + 1, tok_ks[T.k] ); } break; } - - return a; } /* Parse a procedure. */ -static ast *parse_proc(lex *l) { +static ast *parse_proc(lex *l, syt *st) { lex_kind(l, LK_PROC); lex_kind(l, LK_LPAREN); ast *a = ast_aloc(); a->k = AK_PROC; /* Parse optional procedure parameter(s) */ /* TODO parse parameters(s) */ - if (lex_peek(l).k != LK_RPAREN) { - error(1, "UNIMPLEMENTED (parse_proc)"); - } - lex_kind(l, LK_RPAREN); /* Parse optional procedure return type(s) */ /* TODO parse more than one unnamed return type */ - if (lex_peek(l).k == LK_RARROW) { - lex_kind(l, LK_RARROW); + if (T.k == LK_RARROW) { + lex_next(l); tok t = lex_kind(l, LK_ID); + sym s = syt_search_h(st, t.h, t.s); + + /* Confirm that the return type exists */ + if (s.k == SK_NULL) { error( /* ERROR */ + 1, "%s:%zu:%zu: error: undefined identifier \"%s\"", + l->n, T.ln + 1, T.cl + 1, t.s + ); } + + /* Confirm that the return type is a type */ + if (s.k != SK_TYPE) { error( /* ERROR */ + 1, "%s:%zu:%zu: error: expected a type", + l->n, T.ln + 1, T.cl + 1 + ); } - /* TODO dont hardcode return type */ - lex_kind(l, LK_ID); a->t = &TYPE(TY_S64); + a->t = s.t; } - ast_push(a, parse_stmt_compound(l)); return a; + ast_push(a, parse_stmt_compound(l, st)); return a; } static ast *parse_int(lex *l) { @@ -199,7 +228,9 @@ static ast *parse_int(lex *l) { void ast_print(ast *a, UINT i) { for (UINT j = 0; j != i; ++j) { printf(" "); } - printf("%zu:%zu: %s: %s\n", a->ln, a->cl, ast_ks[a->k], a->s); + printf("%zu:%zu: %s: %s", a->ln, a->cl, ast_ks[a->k], a->s); + if (a->k == AK_PROC) { printf(" -> %s", a->t->s); } + fputc('\n', stdout); if (a->c.a != NULL) for (UINT ci = 0; ci != a->c.al; ci += 1) { ast_print(a->c.a[ci], i + 1);