aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHimbeer <himbeer@disroot.org>2025-05-08 15:09:21 +0200
committerHimbeer <himbeer@disroot.org>2025-05-08 15:09:21 +0200
commitb5d9a8384ecdfd4abc915f6f650a60ab7e046e8e (patch)
tree4fb57d9c48cd6cc1c6425066fd6f0ad7ba8db62c
parentad48ab727e474cb3f2fc39e57caf84ee228cb699 (diff)
Implement type and expression parsing
-rw-r--r--src/parse.c562
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)