about summary refs log tree commit diff
path: root/boot/lex.c
diff options
context:
space:
mode:
authorMel <mel@rnrd.eu>2025-05-24 14:08:39 +0200
committerMel <mel@rnrd.eu>2025-05-24 14:08:39 +0200
commit577c6b4339b7ddc5af011ca06ccae97459f5ec76 (patch)
treedb2d795b4f6f5ad42939469037dcd872d5a82054 /boot/lex.c
parent262592dfd2dcf74f4349cf0b58969f7b977a195c (diff)
downloadcatskill-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.c191
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
 }