Add lexer and tests for <= and >=

This commit is contained in:
Krzosa Karol
2026-05-10 14:35:15 +02:00
parent f0e5b6a273
commit c2c0b351b8

112
main.c
View File

@@ -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");
}