aboutsummaryrefslogtreecommitdiff
path: root/boot
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-06-03 01:46:34 +0200
committerMel <mel@rnrd.eu>2025-06-03 01:46:34 +0200
commitf4bcdb0373ac34349c6ecdb9a894c561e0cd419c (patch)
treeada9099eec92d0824b1943ff4ec453cc9682c2bd /boot
parenta9b5fef2eb126500974a1cfe9ce4a8f7cc6e0490 (diff)
downloadcatskill-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.c21
-rw-r--r--boot/parse.c39
-rw-r--r--boot/tree.c64
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");