From: momoyon Date: Sat, 17 May 2025 07:14:54 +0000 (+0500) Subject: [main.c] Can parse_cast()... X-Git-Url: https://www.git.momoyon.org/?a=commitdiff_plain;h=c738740b651889b7a2fa9f25b807d1a21f7178ed;p=lang.git [main.c] Can parse_cast()... - [main.c] Handle `();` and `type;` - [tests] Add new test parse_cast.momo --- diff --git a/main.c b/main.c index 92600b1..084b755 100644 --- a/main.c +++ b/main.c @@ -31,6 +31,7 @@ static bool DEBUG_PRINT = false; // comparison -> term ( ( ">" | ">=" | "<" | "<=" ) term )* ; // term -> factor ( ( "-" | "+" ) factor )* ; // factor -> unary ( ( "/" | "*" ) unary )* ; +// cast -> "(" TYPE ")" ast ; // unary_not -> ( "!" | "~" ) ( unary | primary ) ; // unary_term -> ( "-" | "+" ) ( unary | primary ) ; // prefix -> ( "++" | "--" ) IDENT ; @@ -93,7 +94,7 @@ static bool DEBUG_PRINT = false; * --------------------+-------------------------------------+-----------+----- * Cast | (type) | Right | * --------------------+-------------------------------------+-----------+----- - * L/B NOT | ! ~ | Right | + * L/B NOT | ! ~ | Right | X * --------------------+-------------------------------------+-----------+----- * Unary Plus/Minus | + - | Right | X * --------------------+-------------------------------------+-----------+----- @@ -287,6 +288,7 @@ typedef struct Subscript_AST Subscript_AST; typedef struct Access_AST Access_AST; typedef struct Unary_term_AST Unary_term_AST; typedef struct Unary_not_AST Unary_not_AST; +typedef struct Cast_AST Cast_AST; typedef struct Suffix_AST Suffix_AST; typedef struct Prefix_AST Prefix_AST; typedef struct Primary_expr Primary_expr; @@ -327,6 +329,11 @@ struct Unary_not_AST { AST *operand; }; +struct Cast_AST { + Token type; // Type we are casting to + AST *ast; // Ast we are casting +}; + typedef struct { AST **items; size_t count; @@ -398,6 +405,7 @@ typedef enum { AST_PREFIX, AST_UNARY_TERM, AST_UNARY_NOT, + AST_CAST, AST_BINARY, AST_COUNT, } AST_kind; @@ -414,6 +422,7 @@ struct AST { Prefix_AST *prefix; Unary_term_AST *unary_term; Unary_not_AST *unary_not; + Cast_AST *cast; Binary_expr *bin_expr; Location loc; }; @@ -526,6 +535,7 @@ const char *expr_kind_as_str(AST_kind k) { case AST_PREFIX: return "PREFIX"; case AST_UNARY_TERM: return "UNARY_TERM"; case AST_UNARY_NOT: return "UNARY_NOT"; + case AST_CAST: return "CAST"; case AST_BINARY: return "BINARY"; case AST_COUNT: default: ASSERT(false, "UNREACHABLE!"); @@ -574,6 +584,10 @@ void print_ast_as_value(FILE *f, AST e) { fprintf(f, " %s ", token_type_as_str(e.unary_not->operator.type)); print_ast_as_value(f, *e.unary_not->operand); } break; + case AST_CAST: { + fprintf(f, "( "SV_FMT" ) ", SV_ARG(e.cast->type.lexeme)); + print_ast_as_value(f, *e.cast->ast); + } break; case AST_PRIMARY: { print_primary_expr(f, e.prim_expr); } break; @@ -841,6 +855,7 @@ AST *parse_access(Arena *arena, Parser *p); AST *parse_prefix(Arena *arena, Parser *p); AST *parse_unary_term(Arena *arena, Parser *p); AST *parse_unary_not(Arena *arena, Parser *p); +AST *parse_cast(Arena *arena, Parser *p); AST *parse_factor(Arena *arena, Parser *p); AST *parse_comparision(Arena *arena, Parser *p); AST *parse_term(Arena *arena, Parser *p); @@ -917,12 +932,19 @@ AST *parse_primary(Arena *arena, Parser *p) { ast->prim_expr->value.kind = LIT_INT; // TODO: Should we introduce a LIT_NULL? ast->prim_expr->value.as.i = 0; return ast; + } else if (t.type == TK_TYPE) { + error_pretty(t.loc, (*p->lexer), "We didn't expect a type here"); + return NULL; } else { printf("Unexpected Token: "), print_token(stdout, t); printf("\n"); ASSERT(false, "^"); } } else { parser_advance(p); // Skip ( + if (parser_match(p, TK_RIGHT_PAREN)) { + error_pretty(parser_previous(p).loc, (*p->lexer), "Expected expression before )"); + return NULL; + } AST *ast = parse(arena, p); if (parser_peek(p).type != TK_RIGHT_PAREN) { Token t = parser_peek(p); @@ -1119,13 +1141,40 @@ AST *parse_unary_not(Arena *arena, Parser *p) { return parse_unary_term(arena, p); } +AST *parse_cast(Arena *arena, Parser *p) { + Token t = parser_peek(p); + + if (t.type == TK_LEFT_PAREN && parser_peek_by(p, 1).type == TK_TYPE) { + parser_advance(p); // Skip ( + AST *ast = (AST *)arena_alloc(arena, sizeof(AST)); + ast->loc = t.loc; + ast->cast = (Cast_AST *)arena_alloc(arena, sizeof(Cast_AST)); + ast->kind = AST_CAST; + ast->cast->type = parser_advance(p); + + if (!parser_match(p, TK_RIGHT_PAREN)) { + error_pretty(parser_peek(p).loc, (*p->lexer), "Expected ) after `"SV_FMT"` but got `%s`", + SV_ARG(ast->cast->type.lexeme), + token_type_as_str(parser_peek(p).type)); + return NULL; + } + + ast->cast->ast = parse(arena, p); + + + return ast; + } + + return parse_unary_not(arena, p); +} + AST *parse_factor(Arena *arena, Parser *p) { - AST *ast = parse_unary_not(arena, p); + AST *ast = parse_cast(arena, p); if (ast == NULL) return NULL; while (parser_match(p, TK_DIVIDE) || parser_match(p, TK_MULTIPLY)) { Token op = parser_previous(p); - AST *rhs = parse_unary_not(arena, p); + AST *rhs = parse_cast(arena, p); if (rhs == NULL) return rhs; AST *new_ast = (AST *)arena_alloc(arena, sizeof(AST)); @@ -1944,7 +1993,8 @@ int main(int argc, char **argv) { Parser p = make_parser(&l, tokens); - Arena arena = arena_make(0); + // TODO: Reallocing arena is causing memory issues + Arena arena = arena_make(32*1024); AST_refs ast_refs = {0}; diff --git a/tests/.parse_cast.build.code.expected b/tests/.parse_cast.build.code.expected new file mode 100644 index 0000000..c227083 --- /dev/null +++ b/tests/.parse_cast.build.code.expected @@ -0,0 +1 @@ +0 \ No newline at end of file diff --git a/tests/.parse_cast.build.err.expected b/tests/.parse_cast.build.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_cast.build.in.expected b/tests/.parse_cast.build.in.expected new file mode 100644 index 0000000..c4d955f --- /dev/null +++ b/tests/.parse_cast.build.in.expected @@ -0,0 +1 @@ +dump_ast \ No newline at end of file diff --git a/tests/.parse_cast.build.out.expected b/tests/.parse_cast.build.out.expected new file mode 100644 index 0000000..52b4321 --- /dev/null +++ b/tests/.parse_cast.build.out.expected @@ -0,0 +1,10 @@ +parse_cast.momo:1:0 [CAST] '( int ) 42' +parse_cast.momo:2:0 [CAST] '( string ) "Hello, World!"' +parse_cast.momo:3:0 [CAST] '( bool ) true' +parse_cast.momo:4:0 [CAST] '( uint ) 'myVariable': ???' +parse_cast.momo:5:0 [CAST] '( float ) ((5 + 3) * 2)' +parse_cast.momo:6:0 [CAST] '( bool ) myFunction('arg1': ???, 'arg2': ???)' +parse_cast.momo:7:0 [CAST] '( int ) - 'myVariable': ???' +parse_cast.momo:8:0 [CAST] '( char ) array['index': ???]' +parse_cast.momo:9:0 [CAST] '( string ) (myFunction() + " appended string")' +parse_cast.momo:10:0 [CAST] '( int64 ) ++'myVariable': ???' diff --git a/tests/.parse_cast.code.expected b/tests/.parse_cast.code.expected new file mode 100644 index 0000000..d7d17fc --- /dev/null +++ b/tests/.parse_cast.code.expected @@ -0,0 +1 @@ +-1 \ No newline at end of file diff --git a/tests/.parse_cast.err.expected b/tests/.parse_cast.err.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_cast.in.expected b/tests/.parse_cast.in.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/.parse_cast.out.expected b/tests/.parse_cast.out.expected new file mode 100644 index 0000000..e69de29 diff --git a/tests/parse_cast.momo b/tests/parse_cast.momo new file mode 100644 index 0000000..f30ca35 --- /dev/null +++ b/tests/parse_cast.momo @@ -0,0 +1,10 @@ +(int) 42; +(string) "Hello, World!"; +(bool) true; +(uint) myVariable; +(float) (5 + 3) * 2; +(bool) myFunction(arg1, arg2); +(int) -myVariable; +(char) array[index]; +(string) (myFunction() + " appended string"); +(int64) myVariable++;