diff --git a/main.c b/main.c index d735d4a..e34a729 100644 --- a/main.c +++ b/main.c @@ -133,13 +133,61 @@ Token lex_token(Lexer *lex) { case '*': t.kind = TOK_STAR; break; case '/': t.kind = TOK_SLASH; break; case '%': t.kind = TOK_PERCENT; break; - case '=': t.kind = TOK_ASSIGN; break; - case '<': t.kind = TOK_LT; break; - case '>': t.kind = TOK_GT; break; - case '!': t.kind = TOK_NOT; break; + case '=': { + if (lex->at < lex->end && *lex->at == '=') { + lex_advance(lex); + t.kind = TOK_EQ; + } else { + t.kind = TOK_ASSIGN; + } + } break; + case '<': { + if (lex->at < lex->end && *lex->at == '=') { + lex_advance(lex); + t.kind = TOK_LEQ; + } else if (lex->at < lex->end && *lex->at == '<') { + lex_advance(lex); + t.kind = TOK_LSHIFT; + } else { + t.kind = TOK_LT; + } + } break; + case '>': { + if (lex->at < lex->end && *lex->at == '=') { + lex_advance(lex); + t.kind = TOK_GEQ; + } else if (lex->at < lex->end && *lex->at == '>') { + lex_advance(lex); + t.kind = TOK_RSHIFT; + } else { + t.kind = TOK_GT; + } + } break; + case '!': { + if (lex->at < lex->end && *lex->at == '=') { + lex_advance(lex); + t.kind = TOK_NEQ; + } else { + t.kind = TOK_NOT; + } + } break; case '~': t.kind = TOK_BITNOT; break; - case '&': t.kind = TOK_BITAND; break; - case '|': t.kind = TOK_BITOR; break; + case '&': { + if (lex->at < lex->end && *lex->at == '&') { + lex_advance(lex); + t.kind = TOK_AND; + } else { + t.kind = TOK_BITAND; + } + } break; + case '|': { + if (lex->at < lex->end && *lex->at == '|') { + lex_advance(lex); + t.kind = TOK_OR; + } else { + t.kind = TOK_BITOR; + } + } break; case '^': t.kind = TOK_BITXOR; break; default: { // @todo: lexer perhaps should have a static buffer of size 1024, error message @@ -357,11 +405,41 @@ void parser_test(void) { TEST_EVAL(32+5-4); TEST_EVAL(16/2/2); + TEST_EVAL(9*4/6); + TEST_EVAL(17%5); TEST_EVAL(5125-42|(4&3)^2|2%1242); TEST_EVAL((45%2)^(23&3)); TEST_EVAL(1<16*2); + TEST_EVAL(16>1+2); + TEST_EVAL(4<=2+2); + TEST_EVAL(5>=2+2); + TEST_EVAL(4==2+2); + TEST_EVAL(5!=2+2); TEST_EVAL(1+1+1+1+2-2-3-4-5); TEST_EVAL(5%2^5&6|3); + TEST_EVAL(6&3); + TEST_EVAL(6|3); + TEST_EVAL(6^3); + TEST_EVAL(1&&2); + TEST_EVAL(0||3); + TEST_EVAL(1||0&&0); + TEST_EVAL(8<<2); + TEST_EVAL(32>>3); + TEST_EVAL((2+3)*(4+5)); + TEST_EVAL(9>3&1); + TEST_EVAL(8|1<4); + + // TEST_EVAL(7<=3+4); + // TEST_EVAL(8>=2*4); + // TEST_EVAL(4==2+2); + // TEST_EVAL(5!=2+2); + // TEST_EVAL(1&&2); + // TEST_EVAL(0||3); + // TEST_EVAL(1||0&&0); + // TEST_EVAL(8<<2); + // TEST_EVAL(32>>3); + // TEST_EVAL(1+2<<3); + // TEST_EVAL(16>>1+1); #pragma clang diagnostic pop @@ -370,7 +448,7 @@ void parser_test(void) { } void lex_test(void) { - char *src = "12 + 34.5 * 6\n- 7 % 2 / 1"; + char *src = "12 + 34.5 * 6\n- 7 % 2 / 1 == 1 != 2 <= 3 >= 4 && 3 || 4 << 1 >> 2"; Lexer lex = make_lexer("test.c", src, (int)strlen(src)); assert_token(lex_token(&lex), TOK_INT, "12", 0, 0); @@ -384,15 +462,31 @@ void lex_test(void) { assert_token(lex_token(&lex), TOK_INT, "2", 1, 6); assert_token(lex_token(&lex), TOK_SLASH, "/", 1, 8); assert_token(lex_token(&lex), TOK_INT, "1", 1, 10); + assert_token(lex_token(&lex), TOK_EQ, "==", 1, 12); + assert_token(lex_token(&lex), TOK_INT, "1", 1, 15); + assert_token(lex_token(&lex), TOK_NEQ, "!=", 1, 17); + assert_token(lex_token(&lex), TOK_INT, "2", 1, 20); + assert_token(lex_token(&lex), TOK_LEQ, "<=", 1, 22); + assert_token(lex_token(&lex), TOK_INT, "3", 1, 25); + assert_token(lex_token(&lex), TOK_GEQ, ">=", 1, 27); + assert_token(lex_token(&lex), TOK_INT, "4", 1, 30); + assert_token(lex_token(&lex), TOK_AND, "&&", 1, 32); + assert_token(lex_token(&lex), TOK_INT, "3", 1, 35); + assert_token(lex_token(&lex), TOK_OR, "||", 1, 37); + assert_token(lex_token(&lex), TOK_INT, "4", 1, 40); + assert_token(lex_token(&lex), TOK_LSHIFT, "<<", 1, 42); + assert_token(lex_token(&lex), TOK_INT, "1", 1, 45); + assert_token(lex_token(&lex), TOK_RSHIFT, ">>", 1, 47); + assert_token(lex_token(&lex), TOK_INT, "2", 1, 50); Token eof = lex_token(&lex); assert(eof.kind == TOK_EOF); assert(eof.len == 0); assert(eof.line == 1); - assert(eof.column == 11); + assert(eof.column == 51); Token_Array array = lex_file("test.c", src, (int)strlen(src)); - assert(array.len == 12); + assert(array.len == 28); printf("lexer tests passed\n"); }