diff options
author | Himbeer <himbeer@disroot.org> | 2025-05-08 15:09:21 +0200 |
---|---|---|
committer | Himbeer <himbeer@disroot.org> | 2025-05-08 15:09:21 +0200 |
commit | b5d9a8384ecdfd4abc915f6f650a60ab7e046e8e (patch) | |
tree | 4fb57d9c48cd6cc1c6425066fd6f0ad7ba8db62c | |
parent | ad48ab727e474cb3f2fc39e57caf84ee228cb699 (diff) |
Implement type and expression parsing
-rw-r--r-- | src/parse.c | 562 |
1 files changed, 562 insertions, 0 deletions
diff --git a/src/parse.c b/src/parse.c index de3f910..99f0597 100644 --- a/src/parse.c +++ b/src/parse.c @@ -8,6 +8,568 @@ static int parse_expr(struct lexer *lexer, struct expr *e); static int parse_if(struct lexer *lexer, struct ast_if *cnd); static int parse_stmt(struct lexer *lexer, struct ast_stmt *stmt, int nosemi); +static int +parse_type(struct lexer *lexer, struct type *type) +{ + if (match(lexer, T_INT8)) { + type->kind = TK_INT; + type->desc.i = cer_int8_t; + } else if (match(lexer, T_UINT8)) { + type->kind = TK_INT; + type->desc.i = cer_uint8_t; + } else if (match(lexer, T_INT16)) { + type->kind = TK_INT; + type->desc.i = cer_int16_t; + } else if (match(lexer, T_UINT16)) { + type->kind = TK_INT; + type->desc.i = cer_uint16_t; + } else if (match(lexer, T_INT32)) { + type->kind = TK_INT; + type->desc.i = cer_int32_t; + } else if (match(lexer, T_UINT32)) { + type->kind = TK_INT; + type->desc.i = cer_uint32_t; + } else if (match(lexer, T_INT64)) { + type->kind = TK_INT; + type->desc.i = cer_int64_t; + } else if (match(lexer, T_UINT64)) { + type->kind = TK_INT; + type->desc.i = cer_uint64_t; + } else if (match(lexer, T_INT)) { + type->kind = TK_INT; + type->desc.i = cer_int_t; + } else if (match(lexer, T_UINT)) { + type->kind = TK_INT; + type->desc.i = cer_uint_t; + } else if (match(lexer, T_FLOAT32)) { + type->kind = TK_FLOAT; + type->desc.fp = cer_float32_t; + } else if (match(lexer, T_FLOAT64)) { + type->kind = TK_FLOAT; + type->desc.fp = cer_float64_t; + } else if (match(lexer, T_BOOL)) { + type->kind = TK_BOOL; + } else { + return 0; + } + + return 1; +} + +static int +parse_literal(struct lexer *lexer, struct literal *l) +{ + struct token littok; + enum lexical_token kind = lex(lexer, &littok); + switch (kind) { + case T_NUMBER: + l->kind = littok.info.num.isfloat ? LIT_FLOAT : LIT_INT; + if (littok.info.num.isfloat) { + l->v.n = littok.info.num.value.integer; + } else { + l->v.x = littok.info.num.value.floatingpt; + } + + break; + case T_CHAR: + l->kind = LIT_CHR; + l->v.c = littok.info.chr; + + break; + case T_STRING: + l->kind = LIT_STR; + l->v.s = littok.info.str; + + break; + default: + unlex(lexer, &littok); + return 0; + } + + return 1; + + return 1; +} + +static int +parse_value_e(struct lexer *lexer, struct value_e *e) +{ + e->loc = lex_loc(lexer); + + if (parse_literal(lexer, &e->v.lit)) { + e->kind = V_LITERAL; + return 1; + } + + e->kind = V_NAME; + + struct token nametok; + if (lex(lexer, &nametok) != T_NAME) { + unlex(lexer, &nametok); + return 0; + } + e->v.name = nametok.info.str; + + return 1; +} + +static int +parse_grp_e(struct lexer *lexer, struct grp_e *e) +{ + e->loc = lex_loc(lexer); + + e->isgrouped = match(lexer, T_LPAREN); + if (e->isgrouped) { + e->inner.grouped = must_malloc(sizeof(struct expr)); + if (!parse_expr(lexer, e->inner.grouped)) { + error(lex_loc(lexer), "expected expression inside grouping"); + } + + if (!match(lexer, T_RPAREN)) { + error(lex_loc(lexer), "expected closing ')' for grouping"); + } + + return 1; + } + + return parse_value_e(lexer, &e->inner.value); +} + +static int +parse_call_e(struct lexer *lexer, struct call_e *e) +{ + e->loc = lex_loc(lexer); + + e->args = must_calloc(1, sizeof(struct expr)); + e->argsz = 1; + e->arglen = 0; + + struct expr arg; + while (parse_expr(lexer, &arg)) { + if (e->arglen >= e->argsz) { + e->argsz *= 2; + size_t newsz = e->argsz * sizeof(struct expr); + e->args = must_realloc(e->args, newsz); + } + e->args[e->arglen++] = arg; + + if (!match(lexer, T_COMMA)) { + break; + } + } + + return 1; +} + +static int +parse_access_e(struct lexer *lexer, struct access_e *e) +{ + e->loc = lex_loc(lexer); + + if (match(lexer, T_DOT)) { + e->kind = AC_FIELD; + } else if (match(lexer, T_LBRACKET)) { + e->kind = AC_INDEX; + } else if (match(lexer, T_LPAREN)) { + e->kind = AC_CALL; + } else { + return 0; + } + + switch (e->kind) { + case AC_FIELD: + struct token nametok; + if (lex(lexer, &nametok) != T_NAME) { + error(nametok.loc, "expected field name after '.'"); + } + e->ac.field = nametok.info.str; + + break; + case AC_INDEX: + e->ac.index = must_malloc(sizeof(struct expr)); + if (!parse_expr(lexer, e->ac.index)) { + error(lex_loc(lexer), "expected index (expression)"); + } + + if (!match(lexer, T_RBRACKET)) { + error(lex_loc(lexer), "expected closing ']' for indexing operation"); + } + + break; + case AC_CALL: + if (!parse_call_e(lexer, &e->ac.call)) { + error(lex_loc(lexer), "expected call arguments"); + } + + if (!match(lexer, T_RPAREN)) { + error(lex_loc(lexer), "expected closing ')' after argument list"); + } + + break; + } + + e->next = must_malloc(sizeof(struct access_e)); + if (!parse_access_e(lexer, e->next)) { + free(e->next); + e->next = NULL; + } + + return 1; +} + +static int +parse_tag_e(struct lexer *lexer, struct tag_e *e) +{ + e->loc = lex_loc(lexer); + + e->dotagof = match(lexer, T_TAGOF); + + if (!parse_grp_e(lexer, &e->grp)) { + if (e->dotagof) { + error(lex_loc(lexer), "expected grouping or value"); + } + + return 0; + } + + e->access = must_malloc(sizeof(struct access_e)); + if (!parse_access_e(lexer, e->access)) { + free(e->access); + e->access = NULL; + } + + return 1; +} + +static int +parse_sign_e(struct lexer *lexer, struct sign_e *e) +{ + e->loc = lex_loc(lexer); + + if (match(lexer, T_ADD)) { + e->op = SIGN_POS; + } else if (match(lexer, T_MINUS)) { + e->op = SIGN_NEG; + } else { + e->op = SIGN_NONE; + } + + if (!parse_tag_e(lexer, &e->tag)) { + if (e->op != SIGN_NONE) { + error(lex_loc(lexer), "expected operand to sign"); + } + + return 0; + } + + return 1; +} + +static int +parse_inv_e(struct lexer *lexer, struct inv_e *e) +{ + e->loc = lex_loc(lexer); + + if (match(lexer, T_BNOT)) { + e->op = INV_BITS; + } else if (match(lexer, T_BANG)) { + e->op = INV_BOOL; + } else { + e->op = INV_NONE; + } + + if (e->op == INV_NONE) { + return parse_sign_e(lexer, &e->oper.sign); + } + + e->oper.inv = must_malloc(sizeof(struct inv_e)); + if (!parse_inv_e(lexer, e->oper.inv)) { + error(lex_loc(lexer), "expected operand to inversion operator"); + } + + return 1; +} + +static int +parse_deref_e(struct lexer *lexer, struct deref_e *e) +{ + e->loc = lex_loc(lexer); + + e->doderef = match(lexer, T_STAR); + if (e->doderef) { + e->inner.deref = must_malloc(sizeof(struct deref_e)); + if (!parse_deref_e(lexer, e->inner.deref)) { + error(lex_loc(lexer), "expected operand to dereference operator"); + } + + return 1; + } + + return parse_inv_e(lexer, &e->inner.inv); +} + +static int +parse_ref_e(struct lexer *lexer, struct ref_e *e) +{ + e->loc = lex_loc(lexer); + + e->doref = match(lexer, T_BAND); + + if (!parse_deref_e(lexer, &e->inner)) { + if (e->doref) { + error(lex_loc(lexer), "expected operand to reference operator"); + } + + return 0; + } + + return 1; +} + +static int +parse_as_e(struct lexer *lexer, struct as_e *e) +{ + e->loc = lex_loc(lexer); + + if (!parse_ref_e(lexer, &e->lhs)) { + return 0; + } + + e->cast = NULL; + if (!match(lexer, T_AS)) { + return 1; + } + + e->cast = must_malloc(sizeof(struct type)); + if (!parse_type(lexer, e->cast)) { + error(lex_loc(lexer), "expected type after 'as'"); + } + + return 1; +} + +static int +parse_bitand_e(struct lexer *lexer, struct bitand_e *e) +{ + e->loc = lex_loc(lexer); + + if (!parse_as_e(lexer, &e->lhs)) { + return 0; + } + + e->rhs = NULL; + if (!match(lexer, T_BAND)) { + return 1; + } + + e->rhs = must_malloc(sizeof(struct bitand_e)); + if (!parse_bitand_e(lexer, e->rhs)) { + error(lex_loc(lexer), "expected right-hand side operand to &"); + } + + return 1; +} + +static int +parse_bitxor_e(struct lexer *lexer, struct bitxor_e *e) +{ + e->loc = lex_loc(lexer); + + if (!parse_bitand_e(lexer, &e->lhs)) { + return 0; + } + + e->rhs = NULL; + if (!match(lexer, T_BXOR)) { + return 1; + } + + e->rhs = must_malloc(sizeof(struct bitxor_e)); + if (!parse_bitxor_e(lexer, e->rhs)) { + error(lex_loc(lexer), "expected right-hand side operand to ^"); + } + + return 1; +} + +static int +parse_bitor_e(struct lexer *lexer, struct bitor_e *e) +{ + e->loc = lex_loc(lexer); + + if (!parse_bitxor_e(lexer, &e->lhs)) { + return 0; + } + + e->rhs = NULL; + if (!match(lexer, T_BOR)) { + return 1; + } + + e->rhs = must_malloc(sizeof(struct bitor_e)); + if (!parse_bitor_e(lexer, e->rhs)) { + error(lex_loc(lexer), "expected right-hand side operand to |"); + } + + return 1; +} + +static int +parse_product_e(struct lexer *lexer, struct product_e *e) +{ + e->loc = lex_loc(lexer); + + if (!parse_bitor_e(lexer, &e->lhs)) { + return 0; + } + + if (match(lexer, T_STAR)) { + e->op = PRODUCT_MUL; + } else if (match(lexer, T_DIV)) { + e->op = PRODUCT_DIV; + } else if (match(lexer, T_MODULO)) { + e->op = PRODUCT_REM; + } else { + e->op = PRODUCT_NONE; + return 1; + } + + e->rhs = must_malloc(sizeof(struct product_e)); + if (!parse_product_e(lexer, e->rhs)) { + error(lex_loc(lexer), "expected right-hand side operand to product operator"); + } + + return 1; +} + +static int +parse_sum_e(struct lexer *lexer, struct sum_e *e) +{ + e->loc = lex_loc(lexer); + + if (!parse_product_e(lexer, &e->lhs)) { + return 0; + } + + if (match(lexer, T_ADD)) { + e->op = SUM_ADD; + } else if (match(lexer, T_MINUS)) { + e->op = SUM_SUB; + } else { + e->op = SUM_NONE; + return 1; + } + + e->rhs = must_malloc(sizeof(struct sum_e)); + if (!parse_sum_e(lexer, e->rhs)) { + error(lex_loc(lexer), "expected right-hand side operand to sum operator"); + } + + return 1; +} + +static int +parse_shift_e(struct lexer *lexer, struct shift_e *e) +{ + e->loc = lex_loc(lexer); + + if (!parse_sum_e(lexer, &e->lhs)) { + return 0; + } + + if (match(lexer, T_BSHL)) { + e->op = SHIFT_LEFT; + } else if (match(lexer, T_BSHR)) { + e->op = SHIFT_RIGHT; + } else { + e->op = SHIFT_NONE; + return 1; + } + + e->rhs = must_malloc(sizeof(struct shift_e)); + if (!parse_shift_e(lexer, e->rhs)) { + error(lex_loc(lexer), "expected right-hand side operand to bit shift"); + } + + return 1; +} + +static int +parse_cmp_e(struct lexer *lexer, struct cmp_e *e) +{ + e->loc = lex_loc(lexer); + + if (!parse_shift_e(lexer, &e->lhs)) { + return 0; + } + + if (match(lexer, T_LT)) { + e->op = CMP_LESS; + } else if (match(lexer, T_LE)) { + e->op = CMP_LESS_EQ; + } else if (match(lexer, T_EQ)) { + e->op = CMP_EQ; + } else if (match(lexer, T_NEQ)) { + e->op = CMP_NEQ; + } else if (match(lexer, T_GE)) { + e->op = CMP_GREATER_EQ; + } else if (match(lexer, T_GT)) { + e->op = CMP_GREATER; + } else { + e->op = CMP_NONE; + return 1; + } + + if (!parse_shift_e(lexer, &e->rhs)) { + error(lex_loc(lexer), "expected right-hand side operand to comparison"); + } + + return 1; +} + +static int +parse_conjunction_e(struct lexer *lexer, struct conjunction_e *e) +{ + e->loc = lex_loc(lexer); + + if (!parse_cmp_e(lexer, &e->lhs)) { + return 0; + } + + e->rhs = NULL; + if (!match(lexer, T_AND)) { + return 1; + } + + e->rhs = must_malloc(sizeof(struct expr)); + if (!parse_conjunction_e(lexer, e->rhs)) { + error(lex_loc(lexer), "expected right-hand side operand to &&"); + } + + return 1; +} + +static int +parse_expr(struct lexer *lexer, struct expr *e) +{ + e->loc = lex_loc(lexer); + + if (!parse_conjunction_e(lexer, &e->lhs)) { + return 0; + } + + e->rhs = NULL; + if (!match(lexer, T_OR)) { + return 1; + } + + e->rhs = must_malloc(sizeof(struct expr)); + if (!parse_expr(lexer, e->rhs)) { + error(lex_loc(lexer), "expected right-hand side operand to ||"); + } + + return 1; +} static int parse_include(struct lexer *lexer, struct ast_include *inc) |