From: momoyon Date: Mon, 12 May 2025 19:28:53 +0000 (+0500) Subject: [main.c] WIP: parse_subscript()... X-Git-Url: https://www.git.momoyon.org/?a=commitdiff_plain;h=7434b74510f6194c45e55181dab6ab9fbf39bea4;p=lang.git [main.c] WIP: parse_subscript()... - [tests] Add expected output files of previous tests. --- diff --git a/main.c b/main.c index 39459dd..3c8db1b 100644 --- a/main.c +++ b/main.c @@ -33,7 +33,9 @@ static bool DEBUG_PRINT = false; // factor -> unary ( ( "/" | "*" ) unary )* ; // unary -> ( "!" | "-" ) unary // | primary ; -// array subscript -> IDENT "[" NUMBER "]" +// // TODO: Ig there could be a funcall here aswell? +// V +// array subscript -> IDENT "[" ( IDENT | NUMBER ) "]" // funcalls -> IDENT "(" ( ast "," )* ")" // | IDENT "(" IDENT ")" // suffix -> IDENT ( "++" | "--" ) @@ -281,6 +283,7 @@ typedef struct Literal Literal; typedef enum Literal_kind Literal_kind; typedef struct Binary_expr Binary_expr; typedef struct Funcall_AST Funcall_AST; +typedef struct Subscript_AST Subscript_AST; typedef struct Unary_expr Unary_expr; typedef struct Primary_expr Primary_expr; typedef struct AST AST; @@ -309,6 +312,7 @@ struct Literal { }; void print_literal(FILE *f, Literal value); + struct Unary_expr { Token operator; AST *operand; @@ -326,6 +330,11 @@ struct Funcall_AST { ASTs arguments; }; +struct Subscript_AST { + String_view identifier_key; + Primary_expr *index_expr; +}; + struct Binary_expr { Token operator; AST *lhs; @@ -352,6 +361,7 @@ typedef enum { AST_UNARY, AST_PRIMARY, AST_FUNCALL, + AST_SUBSCRIPT, AST_COUNT, } AST_kind; @@ -359,10 +369,11 @@ const char *ast_kind_as_str(AST_kind k); struct AST { AST_kind kind; - Binary_expr *bin_ast; + Binary_expr *bin_expr; Primary_expr *prim_expr; - Unary_expr *unary_ast; + Unary_expr *unary_expr; Funcall_AST *funcall; + Subscript_AST *subscript; Location loc; }; @@ -470,6 +481,7 @@ const char *expr_kind_as_str(AST_kind k) { case AST_UNARY: return "UNARY"; case AST_PRIMARY: return "PRIMARY"; case AST_FUNCALL: return "FUNCALL"; + case AST_SUBSCRIPT: return "SUBSCRIPT"; case AST_COUNT: default: ASSERT(false, "UNREACHABLE!"); } @@ -535,6 +547,19 @@ void print_ast_as_value(FILE *f, AST e) { } fprintf(f, ")"); } break; + case AST_SUBSCRIPT: { + fprintf(f, SV_FMT, SV_ARG(e.subscript->identifier_key)); + fprintf(f, "["); + print_primary_expr(f, e.subscript->index_expr); + // if (e.subscript->index_expr->kind == PRIMARY_VALUE) { + // print_literal(f, e.subscript->index_expr->value); + // } else if (e.subscript->index_expr->kind == PRIMARY_IDENT) { + // print_loc(f, e.subscript->index_expr->value); + // } else { + // ASSERT(false, "This shouldnt happen"); + // } + fprintf(f, "]"); + } break; case AST_COUNT: default: ASSERT(false, "UNREACHABLE!"); } @@ -735,7 +760,7 @@ bool parser_eof(Parser *p) { AST *parse_primary(Arena *arena, Parser *p); AST *parse_suffix(Arena *arena, Parser *p); AST *parse_funcall(Arena *arena, Parser *p); -AST *parse_array_subscript(Arena *arena, Parser *p); +AST *parse_subscript(Arena *arena, Parser *p); AST *parse_unary(Arena *arena, Parser *p); AST *parse_factor(Arena *arena, Parser *p); AST *parse_comparision(Arena *arena, Parser *p); @@ -905,7 +930,37 @@ AST *parse_funcall(Arena *arena, Parser *p) { return parse_suffix(arena, p); } -AST *parse_array_subscript(Arena *arena, Parser *p) { +AST *parse_subscript(Arena *arena, Parser *p) { + Token t = parser_peek(p); + + if (t.type == TK_IDENT && parser_peek_by(p, 1).type == TK_LEFT_SQUARE_BRACE) { + AST *ast = (AST *)arena_alloc(arena, sizeof(AST)); + ast->loc = t.loc; + ast->subscript = (Subscript_AST *)arena_alloc(arena, sizeof(Subscript_AST)); + ast->kind = AST_SUBSCRIPT; + + ast->subscript->identifier_key = parser_advance(p).lexeme; // Eat IDENT + parser_advance(p); // Skip [ + + Token next = parser_peek(p); + if (next.type != TK_INT && + next.type != TK_IDENT) { + error_pretty(next.loc, (*p->lexer), "Expected a positive integer literal or variable but got `%s`", token_type_as_str(next.type)); + return NULL; + } + AST *index_ast = parse_primary(arena, p); + if (index_ast == NULL) return NULL; + ASSERT(index_ast->prim_expr->value.kind == LIT_INT || + index_ast->prim_expr->kind == PRIMARY_IDENT, + "parse_primary() error; should be either integer primary or ident primary!"); + ast->subscript->index_expr = index_ast->prim_expr; + + if (!parser_match(p, TK_RIGHT_SQUARE_BRACE)) { + error_pretty(parser_peek(p).loc, (*p->lexer), "Expected ] but got `%s`", token_type_as_str(parser_peek(p).type)); + } + return ast; + } + return parse_funcall(arena, p); } @@ -923,7 +978,7 @@ AST *parse_unary(Arena *arena, Parser *p) { return ast; } - return parse_array_subscript(arena, p); + return parse_subscript(arena, p); } AST *parse_factor(Arena *arena, Parser *p) { diff --git a/tests/.parse_comparision.build.code.expected b/tests/.parse_comparision.build.code.expected new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/tests/.parse_comparision.build.code.expected @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/tests/.parse_comparision.build.err.expected b/tests/.parse_comparision.build.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_comparision.build.in.expected b/tests/.parse_comparision.build.in.expected new file mode 100644 index 0000000..c4d955f --- /dev/null +++ b/tests/.parse_comparision.build.in.expected @@ -0,0 +1 @@ +dump_ast \ No newline at end of file diff --git a/tests/.parse_comparision.build.out.expected b/tests/.parse_comparision.build.out.expected new file mode 100644 index 0000000..a808229 --- /dev/null +++ b/tests/.parse_comparision.build.out.expected @@ -0,0 +1,4 @@ +parse_comparision.momo:1:0 [BINARY] '(123 > 2)' +parse_comparision.momo:2:0 [BINARY] '(5.000000 <= 'foo': ???)' +parse_comparision.momo:3:0 [BINARY] '('bar': ??? < 'baz': ???)' +parse_comparision.momo:4:0 [BINARY] '('two': ??? >= ('a': ??? * 'b': ???))' diff --git a/tests/.parse_comparision.code.expected b/tests/.parse_comparision.code.expected new file mode 100644 index 0000000..d7d17fc --- /dev/null +++ b/tests/.parse_comparision.code.expected @@ -0,0 +1 @@ +-1 \ No newline at end of file diff --git a/tests/.parse_comparision.err.expected b/tests/.parse_comparision.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_comparision.in.expected b/tests/.parse_comparision.in.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_comparision.out.expected b/tests/.parse_comparision.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_equality.build.code.expected b/tests/.parse_equality.build.code.expected new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/tests/.parse_equality.build.code.expected @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/tests/.parse_equality.build.err.expected b/tests/.parse_equality.build.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_equality.build.in.expected b/tests/.parse_equality.build.in.expected new file mode 100644 index 0000000..c4d955f --- /dev/null +++ b/tests/.parse_equality.build.in.expected @@ -0,0 +1 @@ +dump_ast \ No newline at end of file diff --git a/tests/.parse_equality.build.out.expected b/tests/.parse_equality.build.out.expected new file mode 100644 index 0000000..539700f --- /dev/null +++ b/tests/.parse_equality.build.out.expected @@ -0,0 +1,4 @@ +parse_equality.momo:1:0 [BINARY] '(123 == 2)' +parse_equality.momo:2:0 [BINARY] '(5.000000 != 'foo': ???)' +parse_equality.momo:3:0 [BINARY] '('bar': ??? == 'baz': ???)' +parse_equality.momo:4:0 [BINARY] '('two': ??? != ('a': ??? * 'b': ???))' diff --git a/tests/.parse_equality.code.expected b/tests/.parse_equality.code.expected new file mode 100644 index 0000000..d7d17fc --- /dev/null +++ b/tests/.parse_equality.code.expected @@ -0,0 +1 @@ +-1 \ No newline at end of file diff --git a/tests/.parse_equality.err.expected b/tests/.parse_equality.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_equality.in.expected b/tests/.parse_equality.in.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_equality.out.expected b/tests/.parse_equality.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_factor.build.code.expected b/tests/.parse_factor.build.code.expected new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/tests/.parse_factor.build.code.expected @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/tests/.parse_factor.build.err.expected b/tests/.parse_factor.build.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_factor.build.in.expected b/tests/.parse_factor.build.in.expected new file mode 100644 index 0000000..c4d955f --- /dev/null +++ b/tests/.parse_factor.build.in.expected @@ -0,0 +1 @@ +dump_ast \ No newline at end of file diff --git a/tests/.parse_factor.build.out.expected b/tests/.parse_factor.build.out.expected new file mode 100644 index 0000000..73e1ab4 --- /dev/null +++ b/tests/.parse_factor.build.out.expected @@ -0,0 +1,4 @@ +parse_factor.momo:1:0 [BINARY] '(8 * 1024)' +parse_factor.momo:2:0 [BINARY] '(40.000000 / 1.555500)' +parse_factor.momo:3:0 [BINARY] '('foo': ??? * 2)' +parse_factor.momo:4:0 [BINARY] '('bar': ??? / 'baz': ???)' diff --git a/tests/.parse_factor.code.expected b/tests/.parse_factor.code.expected new file mode 100644 index 0000000..d7d17fc --- /dev/null +++ b/tests/.parse_factor.code.expected @@ -0,0 +1 @@ +-1 \ No newline at end of file diff --git a/tests/.parse_factor.err.expected b/tests/.parse_factor.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_factor.in.expected b/tests/.parse_factor.in.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_factor.out.expected b/tests/.parse_factor.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_primary.build.code.expected b/tests/.parse_primary.build.code.expected new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/tests/.parse_primary.build.code.expected @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/tests/.parse_primary.build.err.expected b/tests/.parse_primary.build.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_primary.build.in.expected b/tests/.parse_primary.build.in.expected new file mode 100644 index 0000000..c4d955f --- /dev/null +++ b/tests/.parse_primary.build.in.expected @@ -0,0 +1 @@ +dump_ast \ No newline at end of file diff --git a/tests/.parse_primary.build.out.expected b/tests/.parse_primary.build.out.expected new file mode 100644 index 0000000..2354fbe --- /dev/null +++ b/tests/.parse_primary.build.out.expected @@ -0,0 +1,7 @@ +parse_primary.momo:1:0 [PRIMARY] '123' +parse_primary.momo:2:1 [PRIMARY] '"string"' +parse_primary.momo:3:0 [PRIMARY] ''identifier': ???' +parse_primary.momo:4:0 [PRIMARY] 'true' +parse_primary.momo:5:0 [PRIMARY] 'false' +parse_primary.momo:6:0 [PRIMARY] '0' +parse_primary.momo:7:1 [PRIMARY] ''expression_inside_parenthesis': ???' diff --git a/tests/.parse_primary.code.expected b/tests/.parse_primary.code.expected new file mode 100644 index 0000000..d7d17fc --- /dev/null +++ b/tests/.parse_primary.code.expected @@ -0,0 +1 @@ +-1 \ No newline at end of file diff --git a/tests/.parse_primary.err.expected b/tests/.parse_primary.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_primary.in.expected b/tests/.parse_primary.in.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_primary.out.expected b/tests/.parse_primary.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_term.build.code.expected b/tests/.parse_term.build.code.expected new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/tests/.parse_term.build.code.expected @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/tests/.parse_term.build.err.expected b/tests/.parse_term.build.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_term.build.in.expected b/tests/.parse_term.build.in.expected new file mode 100644 index 0000000..c4d955f --- /dev/null +++ b/tests/.parse_term.build.in.expected @@ -0,0 +1 @@ +dump_ast \ No newline at end of file diff --git a/tests/.parse_term.build.out.expected b/tests/.parse_term.build.out.expected new file mode 100644 index 0000000..ea835f4 --- /dev/null +++ b/tests/.parse_term.build.out.expected @@ -0,0 +1,4 @@ +parse_term.momo:1:0 [BINARY] '(123 + 2)' +parse_term.momo:2:0 [BINARY] '(5.000000 + 'foo': ???)' +parse_term.momo:3:0 [BINARY] '('bar': ??? - 'baz': ???)' +parse_term.momo:4:0 [BINARY] '('two': ??? - ('a': ??? * 'b': ???))' diff --git a/tests/.parse_term.code.expected b/tests/.parse_term.code.expected new file mode 100644 index 0000000..d7d17fc --- /dev/null +++ b/tests/.parse_term.code.expected @@ -0,0 +1 @@ +-1 \ No newline at end of file diff --git a/tests/.parse_term.err.expected b/tests/.parse_term.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_term.in.expected b/tests/.parse_term.in.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_term.out.expected b/tests/.parse_term.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_unary.build.code.expected b/tests/.parse_unary.build.code.expected new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/tests/.parse_unary.build.code.expected @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/tests/.parse_unary.build.err.expected b/tests/.parse_unary.build.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_unary.build.in.expected b/tests/.parse_unary.build.in.expected new file mode 100644 index 0000000..c4d955f --- /dev/null +++ b/tests/.parse_unary.build.in.expected @@ -0,0 +1 @@ +dump_ast \ No newline at end of file diff --git a/tests/.parse_unary.build.out.expected b/tests/.parse_unary.build.out.expected new file mode 100644 index 0000000..75dff12 --- /dev/null +++ b/tests/.parse_unary.build.out.expected @@ -0,0 +1,7 @@ +parse_unary.momo:1:0 [UNARY] ' ! (1)' +parse_unary.momo:2:0 [UNARY] ' ! (true)' +parse_unary.momo:3:0 [UNARY] ' ! ( ! (true))' +parse_unary.momo:4:0 [UNARY] ' - (1)' +parse_unary.momo:5:0 [UNARY] ' - ('number': ???)' +parse_unary.momo:6:0 [UNARY] ' ! ('bar': ???)' +parse_unary.momo:7:0 [UNARY] ' - ('baz': ???)' diff --git a/tests/.parse_unary.code.expected b/tests/.parse_unary.code.expected new file mode 100644 index 0000000..d7d17fc --- /dev/null +++ b/tests/.parse_unary.code.expected @@ -0,0 +1 @@ +-1 \ No newline at end of file diff --git a/tests/.parse_unary.err.expected b/tests/.parse_unary.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_unary.in.expected b/tests/.parse_unary.in.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_unary.out.expected b/tests/.parse_unary.out.expected new file mode 100644 index 0000000..e69de29