Add lexer and tests for <= and >=
This commit is contained in:
112
main.c
112
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");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user