diff options
| author | Mel <mel@rnrd.eu> | 2025-05-24 14:08:39 +0200 |
|---|---|---|
| committer | Mel <mel@rnrd.eu> | 2025-05-24 14:08:39 +0200 |
| commit | 577c6b4339b7ddc5af011ca06ccae97459f5ec76 (patch) | |
| tree | db2d795b4f6f5ad42939469037dcd872d5a82054 /boot/lex.c | |
| parent | 262592dfd2dcf74f4349cf0b58969f7b977a195c (diff) | |
| download | catskill-577c6b4339b7ddc5af011ca06ccae97459f5ec76.tar.zst catskill-577c6b4339b7ddc5af011ca06ccae97459f5ec76.zip | |
Correctly interpret all assignment operator expression variations
Signed-off-by: Mel <mel@rnrd.eu>
Diffstat (limited to 'boot/lex.c')
| -rw-r--r-- | boot/lex.c | 191 |
1 files changed, 146 insertions, 45 deletions
diff --git a/boot/lex.c b/boot/lex.c index c850534..0fc6ed1 100644 --- a/boot/lex.c +++ b/boot/lex.c @@ -95,10 +95,13 @@ enum Token_Kind TOKEN_SQUARE_CLOSE, TOKEN_COMMA, - TOKEN_ASSIGN, TOKEN_AMPERSAND, TOKEN_DOT, + TOKEN_BANG, + TOKEN_PERCENT, TOKEN_PIPE, + TOKEN_TILDE, + TOKEN_CARET, TOKEN_PLUS, TOKEN_MINUS, @@ -107,13 +110,29 @@ enum Token_Kind TOKEN_AND, TOKEN_OR, - TOKEN_NOT, TOKEN_EQUAL, TOKEN_NOT_EQUAL, TOKEN_LESS, TOKEN_LESS_EQUAL, TOKEN_GREATER, TOKEN_GREATER_EQUAL, + + TOKEN_LEFT_SHIFT, + TOKEN_RIGHT_SHIFT, + + TOKEN_ASSIGN, + TOKEN_ASSIGN_PLUS, + TOKEN_ASSIGN_MINUS, + TOKEN_ASSIGN_STAR, + TOKEN_ASSIGN_SLASH, + TOKEN_ASSIGN_PERCENT, + TOKEN_ASSIGN_AND, + TOKEN_ASSIGN_OR, + TOKEN_ASSIGN_AMPERSAND, + TOKEN_ASSIGN_PIPE, + TOKEN_ASSIGN_CARET, + TOKEN_ASSIGN_LEFT_SHIFT, + TOKEN_ASSIGN_RIGHT_SHIFT, }; const ascii* @@ -182,14 +201,20 @@ token_kind_to_string(enum Token_Kind kind) case TOKEN_COMMA: return "COMMA"; - case TOKEN_ASSIGN: - return "ASSIGN"; case TOKEN_AMPERSAND: return "AMPERSAND"; case TOKEN_DOT: return "DOT"; + case TOKEN_BANG: + return "BANG"; + case TOKEN_PERCENT: + return "PERCENT"; case TOKEN_PIPE: return "PIPE"; + case TOKEN_TILDE: + return "TILDE"; + case TOKEN_CARET: + return "CARET"; case TOKEN_PLUS: return "PLUS"; @@ -204,8 +229,6 @@ token_kind_to_string(enum Token_Kind kind) return "AND"; case TOKEN_OR: return "OR"; - case TOKEN_NOT: - return "NOT"; case TOKEN_EQUAL: return "EQUAL"; case TOKEN_NOT_EQUAL: @@ -218,6 +241,39 @@ token_kind_to_string(enum Token_Kind kind) return "GREATER"; case TOKEN_GREATER_EQUAL: return "GREATER_EQUAL"; + + case TOKEN_LEFT_SHIFT: + return "BITWISE_LEFT_SHIFT"; + case TOKEN_RIGHT_SHIFT: + return "BITWISE_RIGHT_SHIFT"; + + case TOKEN_ASSIGN: + return "ASSIGN"; + case TOKEN_ASSIGN_PLUS: + return "ASSIGN_PLUS"; + case TOKEN_ASSIGN_MINUS: + return "ASSIGN_MINUS"; + case TOKEN_ASSIGN_STAR: + return "ASSIGN_STAR"; + case TOKEN_ASSIGN_SLASH: + return "ASSIGN_SLASH"; + case TOKEN_ASSIGN_PERCENT: + return "ASSIGN_PERCENT"; + case TOKEN_ASSIGN_AND: + return "ASSIGN_AND"; + case TOKEN_ASSIGN_OR: + return "ASSIGN_OR"; + case TOKEN_ASSIGN_AMPERSAND: + return "ASSIGN_AMPERSAND"; + case TOKEN_ASSIGN_PIPE: + return "ASSIGN_PIPE"; + case TOKEN_ASSIGN_CARET: + return "ASSIGN_CARET"; + case TOKEN_ASSIGN_LEFT_SHIFT: + return "ASSIGN_LEFT_SHIFT"; + case TOKEN_ASSIGN_RIGHT_SHIFT: + return "ASSIGN_RIGHT_SHIFT"; + default: return ""; } @@ -390,6 +446,16 @@ lexer_match_char(struct Lexer* l, ascii expected) return (struct Lexer_Char_Match){}; } +void +lexer_match_chars( + struct Lexer* l, ascii a, ascii b, struct Lexer_Char_Match* a_out, + struct Lexer_Char_Match* b_out) +{ + *a_out = lexer_match_char(l, a); + if (!a_out->got_match) return; + *b_out = lexer_match_char(l, b); +} + struct Lexer_Non_Code { bool had_newline; @@ -444,7 +510,7 @@ struct Lexer_Symbol_Token lexer_symbol_token(struct Lexer* l, struct Lexer_Char current) { #define RET return (struct Lexer_Symbol_Token) - struct Lexer_Char_Match next; + struct Lexer_Char_Match a, b; switch (current.character) { case '(': RET{ TOKEN_ROUND_OPEN, 1 }; @@ -459,59 +525,94 @@ lexer_symbol_token(struct Lexer* l, struct Lexer_Char current) case ']': RET{ TOKEN_SQUARE_CLOSE, 1 }; + case ',': RET{ TOKEN_COMMA, 1 }; + case '&': { + lexer_match_chars(l, '&', '=', &a, &b); - case '=': - next = lexer_match_char(l, '='); - if (next.got_match) RET{ TOKEN_EQUAL, 2 }; - - RET{ TOKEN_ASSIGN, 1 }; - - case '&': - next = lexer_match_char(l, '&'); - if (next.got_match) RET{ TOKEN_AND, 2 }; + if (a.got_match && b.got_match) RET{ TOKEN_ASSIGN_AND, 3 }; + if (a.got_match) RET{ TOKEN_AND, 2 }; + a = lexer_match_char(l, '='); + if (a.got_match) RET{ TOKEN_ASSIGN_AMPERSAND, 2 }; RET{ TOKEN_AMPERSAND, 1 }; - + } case '.': RET{ TOKEN_DOT, 1 }; + case '!': { + a = lexer_match_char(l, '='); + if (a.got_match) RET{ TOKEN_NOT_EQUAL, 2 }; + RET{ TOKEN_BANG, 1 }; + } + case '%': { + a = lexer_match_char(l, '='); + if (a.got_match) RET{ TOKEN_ASSIGN_PERCENT, 2 }; + RET{ TOKEN_PERCENT, 1 }; + } + case '|': { + lexer_match_chars(l, '|', '=', &a, &b); - case '|': - next = lexer_match_char(l, '|'); - if (next.got_match) RET{ TOKEN_OR, 2 }; + if (a.got_match && b.got_match) RET{ TOKEN_ASSIGN_OR, 3 }; + if (a.got_match) RET{ TOKEN_OR, 2 }; + a = lexer_match_char(l, '='); + if (a.got_match) RET{ TOKEN_ASSIGN_PIPE, 2 }; RET{ TOKEN_PIPE, 1 }; - - // todo: increment, decrement, +=, -=, *=, etc. - // all the special assignment operations - case '+': + } + case '~': + RET{ TOKEN_TILDE, 1 }; + case '^': { + a = lexer_match_char(l, '='); + 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 }; RET{ TOKEN_PLUS, 1 }; - case '-': + } + case '-': { + a = lexer_match_char(l, '='); + if (a.got_match) RET{ TOKEN_ASSIGN_MINUS, 2 }; RET{ TOKEN_MINUS, 1 }; - case '*': + } + case '*': { + a = lexer_match_char(l, '='); + if (a.got_match) RET{ TOKEN_ASSIGN_STAR, 2 }; RET{ TOKEN_STAR, 1 }; - case '/': + } + case '/': { + a = lexer_match_char(l, '='); + if (a.got_match) RET{ TOKEN_ASSIGN_SLASH, 2 }; RET{ TOKEN_SLASH, 1 }; - - case '!': - next = lexer_match_char(l, '='); - if (next.got_match) RET{ TOKEN_NOT_EQUAL, 2 }; - - RET{ TOKEN_NOT, 1 }; - - case '<': - next = lexer_match_char(l, '='); - if (next.got_match) RET{ TOKEN_LESS_EQUAL, 2 }; - RET{ TOKEN_LESS }; - - case '>': - next = lexer_match_char(l, '='); - if (next.got_match) RET{ TOKEN_GREATER_EQUAL, 2 }; - RET{ TOKEN_GREATER }; - + } + case '<': { + a = lexer_match_char(l, '='); + if (a.got_match) RET{ TOKEN_LESS_EQUAL, 2 }; + + lexer_match_chars(l, '<', '=', &a, &b); + if (a.got_match && b.got_match) RET{ TOKEN_ASSIGN_LEFT_SHIFT, 3 }; + if (a.got_match) RET{ TOKEN_LEFT_SHIFT, 2 }; + RET{ TOKEN_LESS, 1 }; + } + case '>': { + a = lexer_match_char(l, '='); + if (a.got_match) RET{ TOKEN_GREATER_EQUAL, 2 }; + + lexer_match_chars(l, '>', '=', &a, &b); + if (a.got_match && b.got_match) RET{ TOKEN_ASSIGN_RIGHT_SHIFT, 3 }; + if (a.got_match) RET{ TOKEN_RIGHT_SHIFT, 2 }; + RET{ TOKEN_GREATER, 1 }; + } + case '=': { + a = lexer_match_char(l, '='); + if (a.got_match) RET{ TOKEN_EQUAL, 2 }; + RET{ TOKEN_ASSIGN, 1 }; + } default: - RET{ TOKEN_NONE, 0 }; + RET{ TOKEN_NONE, 1 }; } #undef RET } |
