diff options
| author | Mel <mel@rnrd.eu> | 2025-06-03 01:46:34 +0200 |
|---|---|---|
| committer | Mel <mel@rnrd.eu> | 2025-06-03 01:46:34 +0200 |
| commit | f4bcdb0373ac34349c6ecdb9a894c561e0cd419c (patch) | |
| tree | ada9099eec92d0824b1943ff4ec453cc9682c2bd /boot | |
| parent | a9b5fef2eb126500974a1cfe9ce4a8f7cc6e0490 (diff) | |
| download | catskill-f4bcdb0373ac34349c6ecdb9a894c561e0cd419c.tar.zst catskill-f4bcdb0373ac34349c6ecdb9a894c561e0cd419c.zip | |
Parse and lex ++, --, ** operators, with prefix and postfix handling
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot')
| -rw-r--r-- | boot/lex.c | 21 | ||||
| -rw-r--r-- | boot/parse.c | 39 | ||||
| -rw-r--r-- | boot/tree.c | 64 |
3 files changed, 120 insertions, 4 deletions
diff --git a/boot/lex.c b/boot/lex.c index 37eabcd..30f4071 100644 --- a/boot/lex.c +++ b/boot/lex.c @@ -122,6 +122,10 @@ enum Token_Kind TOKEN_STAR, TOKEN_SLASH, + TOKEN_PLUS_PLUS, + TOKEN_MINUS_MINUS, + TOKEN_STAR_STAR, + TOKEN_AND, TOKEN_OR, TOKEN_EQUAL, @@ -239,6 +243,13 @@ token_kind_to_string(enum Token_Kind kind) case TOKEN_SLASH: return "SLASH"; + case TOKEN_PLUS_PLUS: + return "PLUS_PLUS"; + case TOKEN_MINUS_MINUS: + return "MINUS_MINUS"; + case TOKEN_STAR_STAR: + return "STAR_STAR"; + case TOKEN_AND: return "AND"; case TOKEN_OR: @@ -582,20 +593,28 @@ lexer_symbol_token(struct Lexer* l, struct Lexer_Char current) if (a.got_match) RET{ TOKEN_ASSIGN_CARET, 2 }; RET{ TOKEN_CARET, 1 }; } - // todo: increment, decrement, power case '+': { a = lexer_match_char(l, '='); if (a.got_match) RET{ TOKEN_ASSIGN_PLUS, 2 }; + + a = lexer_match_char(l, '+'); + if (a.got_match) RET{ TOKEN_PLUS_PLUS, 2 }; RET{ TOKEN_PLUS, 1 }; } case '-': { a = lexer_match_char(l, '='); if (a.got_match) RET{ TOKEN_ASSIGN_MINUS, 2 }; + + a = lexer_match_char(l, '-'); + if (a.got_match) RET{ TOKEN_MINUS_MINUS, 2 }; RET{ TOKEN_MINUS, 1 }; } case '*': { a = lexer_match_char(l, '='); if (a.got_match) RET{ TOKEN_ASSIGN_STAR, 2 }; + + a = lexer_match_char(l, '*'); + if (a.got_match) RET{ TOKEN_STAR_STAR, 2 }; RET{ TOKEN_STAR, 1 }; } case '/': { diff --git a/boot/parse.c b/boot/parse.c index 07b6e58..1c42352 100644 --- a/boot/parse.c +++ b/boot/parse.c @@ -439,14 +439,31 @@ parser_expression_postfix(struct Parser* p, struct Parser_Error* error) { struct Expression* expression = CHECK(parser_expression_member(p, error)); - switch (parser_peek(p).kind) { + struct Token token = parser_peek(p); + switch (token.kind) { case TOKEN_ROUND_OPEN: return parser_expression_postfix_call(p, expression, error); case TOKEN_SQUARE_OPEN: return parser_expression_postfix_subscript(p, expression, error); - default: - return expression; + default:; + } + + enum Increment_Decrement_Operation inc_dec_op = + increment_decrement_operation_from_token(&token); + if (inc_dec_op) { + parser_next(p); + struct Expression_Increment_Decrement inc_dec = { + .prefix = false, + .subject = expression, + .operation = inc_dec_op, + }; + + struct Span span = span_merge(expression->span, token.span); + union Expression_Value value = { .increment_decrement = inc_dec }; + return expression_new(EXPRESSION_INCREMENT_DECREMENT, value, span, token.location); } + + return expression; } struct Expression* @@ -463,6 +480,22 @@ parser_expression_unary_operation(struct Parser* p, struct Parser_Error* error) return expression_new(EXPRESSION_UNARY_OPERATION, value, span, token.location); } + enum Increment_Decrement_Operation inc_dec_op = + increment_decrement_operation_from_token(&token); + if (inc_dec_op) { + parser_next(p); + struct Expression* subject = CHECK(parser_expression_unary_operation(p, error)); + struct Expression_Increment_Decrement inc_dec = { + .prefix = true, + .subject = subject, + .operation = inc_dec_op, + }; + + struct Span span = span_merge(token.span, inc_dec.subject->span); + union Expression_Value value = { .increment_decrement = inc_dec }; + return expression_new(EXPRESSION_INCREMENT_DECREMENT, value, span, token.location); + } + return parser_expression_postfix(p, error); } diff --git a/boot/tree.c b/boot/tree.c index 3ae90b8..2d49a2c 100644 --- a/boot/tree.c +++ b/boot/tree.c @@ -54,6 +54,7 @@ enum Binary_Operation BINARY_MULTIPLY, BINARY_DIVIDE, BINARY_MODULO, + BINARY_POWER, BINARY_EQUAL, BINARY_NOT_EQUAL, @@ -99,6 +100,8 @@ binary_operation_from_token(const struct Token* token) return BINARY_DIVIDE; case TOKEN_PERCENT: return BINARY_MODULO; + case TOKEN_STAR_STAR: + return BINARY_POWER; case TOKEN_EQUAL: return BINARY_EQUAL; @@ -210,6 +213,8 @@ binary_operation_precedence(enum Binary_Operation operation) case BINARY_DIVIDE: case BINARY_MODULO: return 11; + case BINARY_POWER: + return 12; // strongest default: @@ -241,6 +246,7 @@ binary_operation_associativity(enum Binary_Operation operation) case BINARY_ASSIGN_BITWISE_OR: case BINARY_ASSIGN_BITWISE_XOR: case BINARY_ASSIGN_BITWISE_LEFT_SHIFT: + case BINARY_POWER: return BINARY_ASSOCIATIVITY_RIGHT; default: return BINARY_ASSOCIATIVITY_LEFT; @@ -261,6 +267,8 @@ binary_operation_to_string(enum Binary_Operation operation) return "/"; case BINARY_MODULO: return "%"; + case BINARY_POWER: + return "**"; case BINARY_EQUAL: return "=="; @@ -323,6 +331,43 @@ binary_operation_to_string(enum Binary_Operation operation) } } +enum Increment_Decrement_Operation +{ + INCREMENT_DECREMENT_NONE, + INCREMENT_DECREMENT_INCREMENT, + INCREMENT_DECREMENT_DECREMENT, +}; + +enum Increment_Decrement_Operation +increment_decrement_operation_from_token(const struct Token* token) +{ + switch (token->kind) { + case TOKEN_PLUS_PLUS: + return INCREMENT_DECREMENT_INCREMENT; + case TOKEN_MINUS_MINUS: + return INCREMENT_DECREMENT_DECREMENT; + + default: + return INCREMENT_DECREMENT_NONE; + } +} + +const ascii* +increment_decrement_operation_to_string(enum Increment_Decrement_Operation operation) +{ + switch (operation) { + case INCREMENT_DECREMENT_INCREMENT: + return "++"; + case INCREMENT_DECREMENT_DECREMENT: + return "--"; + + default: + failure("unexpected increment/decrement operation passed to " + "`increment_decrement_operation_to_string`"); + return nil; + } +} + // nodes are parts of the syntax tree that are reused often // and in different places. @@ -372,6 +417,7 @@ enum Expression_Kind EXPRESSION_CALL, EXPRESSION_SUBSCRIPT, EXPRESSION_MEMBER, + EXPRESSION_INCREMENT_DECREMENT, EXPRESSION_FUNCTION, }; @@ -437,6 +483,14 @@ struct Expression_Member struct String name; }; +struct Expression_Increment_Decrement +{ + // whether the increment/decrement is a prefix or postfix operation. + bool prefix; + struct Expression* subject; + enum Increment_Decrement_Operation operation; +}; + #define EXPRESSION_FUNCTION_MAX_PARAMS 32 struct Expression_Function @@ -465,6 +519,7 @@ union Expression_Value struct Expression_Call call; struct Expression_Subscript subscript; struct Expression_Member member; + struct Expression_Increment_Decrement increment_decrement; struct Expression_Function function; }; @@ -563,6 +618,15 @@ expression_print(const struct Expression* expression) expression_print(expression->value.member.subject); printf(")"); break; + case EXPRESSION_INCREMENT_DECREMENT: { + const struct Expression_Increment_Decrement* inc_dec = + &expression->value.increment_decrement; + const ascii* prefix_or_postfix = inc_dec->prefix ? "prefix" : "postfix"; + printf("(increment/decrement %s %s ", + increment_decrement_operation_to_string(inc_dec->operation), prefix_or_postfix); + expression_print(inc_dec->subject); + break; + } case EXPRESSION_FUNCTION: { const struct Expression_Function* fun = &expression->value.function; printf("(function"); |
