From 7e3eefda5711c4274348435fbe888f185c0b3c62 Mon Sep 17 00:00:00 2001 From: Krzosa Karol Date: Fri, 6 May 2022 12:52:33 +0200 Subject: [PATCH] Added almost all expr operators --- build.bat | 2 +- main.c | 1 - new_ast.c | 155 +++++++++++------------------------ new_parse.c | 222 ++++++++++++++++++++++++++++++++++++++++++++++++-- os_win32.c | 2 +- token_array.c | 1 + 6 files changed, 266 insertions(+), 117 deletions(-) diff --git a/build.bat b/build.bat index a498933..2a2f90a 100644 --- a/build.bat +++ b/build.bat @@ -2,5 +2,5 @@ rem clang generate.c -fdiagnostics-absolute-paths -std=c99 -g -o generate.exe -Wl,user32.lib rem generate.exe -clang main.c -fdiagnostics-absolute-paths -std=c99 -g -o main.exe -Wl,user32.lib +clang main.c -Wall -Wno-unused-function -fdiagnostics-absolute-paths -std=c99 -g -o main.exe -Wl,user32.lib rem cl main.c -std:c17 diff --git a/main.c b/main.c index 17af699..b346c70 100644 --- a/main.c +++ b/main.c @@ -17,6 +17,5 @@ int main(){ lex_test(); - test_ast(); parse_test(); } \ No newline at end of file diff --git a/new_ast.c b/new_ast.c index db6ef36..4900fc3 100644 --- a/new_ast.c +++ b/new_ast.c @@ -41,11 +41,13 @@ typedef enum Expr_Kind{ EK_Int, EK_String, EK_Identifier, + EK_Paren, + EK_PostfixUnary, EK_Unary, EK_Binary, EK_Ternary, EK_Cast, - EK_List, + EK_Field, EK_Call, EK_Index, EK_Sizeof, @@ -59,18 +61,24 @@ struct Expr { U64 int_val; Intern_String intern_val; double float_val; + struct { + Expr *expr; + } paren; struct { Typespec *type; Expr* expr; } cast; - struct { - Expr *first; - Expr *last; - } list; + + struct{ + Intern_String name; + Expr *expr; + }field; + struct { Expr *atom; - Expr *list; + Expr *first; + Expr *last; } call; struct { Expr *atom; @@ -80,6 +88,10 @@ struct Expr { Token_Kind op; Expr* expr; } unary; + struct { + Token_Kind op; + Expr *expr; + } postfix_unary; struct { Token_Kind op; Expr* left; @@ -90,6 +102,7 @@ struct Expr { Expr* on_true; Expr* on_false; } ternary; + struct{ Expr_Sizeof_Kind kind; union{ @@ -128,13 +141,37 @@ expr_str(Arena *p, Token *token){ } function Expr * -expr_name(Arena *p, Token *token){ +expr_identifier(Arena *p, Token *token){ assert(token->kind == TK_Identifier); Expr *expr = expr_new(p, EK_Identifier, token); expr->intern_val = token->intern_val; return expr; } +function Expr * +expr_field(Arena *p, Token *token, Expr *inexpr){ + assert(token->kind == TK_Identifier); + Expr *expr = expr_new(p, EK_Field, token); + expr->field.expr = inexpr; + expr->field.name = token->intern_val; + return expr; +} + +function Expr * +expr_paren(Arena *p, Token *token, Expr *inexpr){ + Expr *expr = expr_new(p, EK_Paren, token); + expr->paren.expr = inexpr; + return expr; +} + +function Expr * +expr_postfix_unary(Arena *p, Token *op, Expr *exp){ + Expr *expr = expr_new(p, EK_PostfixUnary, op); + expr->unary.op = op->kind; + expr->unary.expr = exp; + return expr; +} + function Expr * expr_unary(Arena *p, Token *op, Expr *exp){ Expr *expr = expr_new(p, EK_Unary, op); @@ -162,10 +199,9 @@ expr_ternary(Arena *p, Token *op, Expr *cond, Expr *on_true, Expr *on_false){ } function Expr * -expr_call(Arena *p, Token *token, Expr *atom, Expr *list){ +expr_call(Arena *p, Token *token, Expr *atom){ Expr *expr = expr_new(p, EK_Call, token); expr->call.atom = atom; - expr->call.list = list; return expr; } @@ -201,104 +237,7 @@ expr_sizeof_expr(Arena *p, Token *token, Expr *in_expr){ return expr; } -function Expr * -expr_list(Arena *p, Token *token){ - Expr *expr = expr_new(p, EK_List, token); - return expr; -} - function void -expr_list_push(Expr *list, Expr *expr){ - SLLQueuePush(list->list.first, list->list.last, expr); +expr_call_push(Expr *list, Expr *expr){ + SLLQueuePush(list->call.first, list->call.last, expr); } - -//----------------------------------------------------------------------------- -// -//----------------------------------------------------------------------------- -function void -token_print(Token *token){ - printf("%.*s", (S32)token->len, token->str); -} - -function void -expr_print(Expr *expr){ - switch(expr->kind) { - case EK_Int: - case EK_String: { - token_print(expr->token); - } break; - - case EK_Sizeof:{ - printf("sizeof("); - if(expr->size_of.kind == SIZEOF_Expr){ - expr_print(expr->size_of.expr); - } - else{ - assert(expr->size_of.kind == SIZEOF_Type); - //print_typespec(expr->size_of.type); - } - printf(")"); - }break; - - case EK_Binary:{ - printf("("); - expr_print(expr->binary.left); - token_print(expr->token); - expr_print(expr->binary.right); - printf(")"); - } break; - case EK_Unary:{ - printf("("); - token_print(expr->token); - expr_print(expr->unary.expr); - printf(")"); - } break; - - case EK_Ternary:{ - printf("("); - expr_print(expr->ternary.cond); - printf("?"); - expr_print(expr->ternary.on_true); - printf(":"); - expr_print(expr->ternary.on_false); - printf(")"); - } break; - case EK_List:{ - printf("("); - for(Expr *n = expr->list.first; n; n=n->next){ - expr_print(n); - if(n!=expr->list.last) printf(","); - } - printf(")"); - }break; - - case EK_Cast:{ - printf("("); - printf("("); - //print_typespec(expr->cast.type); - printf(")"); - expr_print(expr->cast.expr); - printf(")"); - } break; - - case EK_Index:{ - expr_print(expr->index.atom); - printf("["); - expr_print(expr->index.index); - printf("]"); - }break; - - case EK_Call:{ - expr_print(expr->call.atom); - printf("("); - expr_print(expr->call.list); - printf(")"); - }break; - default: {invalid_codepath;} break; - } -} - -function void -test_ast(){ - -} \ No newline at end of file diff --git a/new_parse.c b/new_parse.c index 9f035ed..ce6531c 100644 --- a/new_parse.c +++ b/new_parse.c @@ -39,7 +39,9 @@ parser_push_error(Parser *p, Token *token, char *str, ...){ __debugbreak(); } - +//----------------------------------------------------------------------------- +// Parsing helpers +//----------------------------------------------------------------------------- function Token * token_get(Parser *p){ Token *result = token_array_iter_peek(&p->tokens, 0); @@ -93,25 +95,31 @@ token_expect(Parser *p, Token_Kind kind){ return 0; } +//----------------------------------------------------------------------------- +// Expression parsing +//----------------------------------------------------------------------------- /* - add = [+-] mul = [/%*] compare = == | != | >= | > | <= | < logical = [&|^] | && | || +unary = [&*-!~+] | ++ | -- -expr_atom = Int +atom_expr = Int | Float | String | Identifier | 'cast' '(' typespec ',' expr ')' -mul_expr = expr_atom (mul expr_atom)* +postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')* +unary_expr = unary ? unary_expr : atom_expr +mul_expr = atom_expr (mul atom_expr)* add_expr = mul_expr (add mul_expr)* compare_expr = add_expr (compare add_expr)* logical_expr = compare_expr (logical compare_expr)* ternary_expr = logical_expr ('?' ternary_expr ':' ternary_expr)? expr = logical_expr */ +function Expr *parse_expr(Parser *p); function Expr * parse_expr_atom(Parser *p){ @@ -120,10 +128,20 @@ parse_expr_atom(Parser *p){ Expr *result = expr_str(p->arena, token); return result; } + else if((token = token_match(p, TK_Identifier))){ + Expr *result = expr_identifier(p->arena, token); + return result; + } else if((token = token_match(p, TK_Int))){ Expr *result = expr_int(p->arena, token); return result; } + else if((token = token_match(p, TK_OpenParen))){ + Expr *expr = parse_expr(p); + token_expect(p, TK_CloseParen); + Expr *result = expr_paren(p->arena, token, expr); + return result; + } else if((token = token_match_keyword(p, keyword_cast))){ token_expect(p, TK_OpenParen); token_expect(p, TK_Identifier); @@ -138,6 +156,77 @@ parse_expr_atom(Parser *p){ } } +function B32 +token_is_postfix(Parser *p){ + Token *token = token_get(p); + B32 result = token->kind == TK_OpenBracket + || token->kind == TK_OpenParen + || token->kind == TK_Dot + || token->kind == TK_Increment + || token->kind == TK_Decrement; + return result; +} + +function Expr * +parse_expr_postfix(Parser *p){ + Expr *left = parse_expr_atom(p); + while(token_is_postfix(p)){ + Token *token = 0; + if((token = token_match(p, TK_OpenBracket))){ + Expr *size = parse_expr(p); + token_expect(p, TK_CloseBracket); + left = expr_index(p->arena, token, left, size); + } + else if((token = token_match(p, TK_OpenParen))){ + left = expr_call(p->arena, token, left); + if(!token_is(p, TK_CloseParen)){ + expr_call_push(left, parse_expr(p)); + while(token_match(p, TK_Comma)){ + expr_call_push(left, parse_expr(p)); + } + } + token_expect(p, TK_CloseParen); + } + else if(token_match(p, TK_Dot)){ + token = token_expect(p, TK_Identifier); + left = expr_field(p->arena, token, left); + } + else{ + token = token_next(p); + assert(token->kind == TK_Increment || token->kind == TK_Decrement); + left = expr_postfix_unary(p->arena, token, left); + } + } + return left; +} + +function B32 +token_is_unary(Parser *p){ + Token *token = token_get(p); + B32 result = token->kind == TK_Add + || token->kind == TK_Increment + || token->kind == TK_Decrement + || token->kind == TK_Sub + || token->kind == TK_Mul + || token->kind == TK_BitAnd + || token->kind == TK_Neg + || token->kind == TK_Not; + return result; +} + +function Expr * +parse_expr_unary(Parser *p){ + if(token_is_unary(p)){ + Token *op = token_next(p); + Expr *right = parse_expr_unary(p); + Expr *result = expr_unary(p->arena, op, right); + return result; + } + else{ + return parse_expr_postfix(p); + } +} + function B32 token_is_mul(Parser *p){ Token *token = token_get(p); @@ -147,10 +236,10 @@ token_is_mul(Parser *p){ function Expr * parse_expr_mul(Parser *p){ - Expr *left = parse_expr_atom(p); + Expr *left = parse_expr_unary(p); while(token_is_mul(p)){ Token *op = token_next(p); - Expr *right = parse_expr_atom(p); + Expr *right = parse_expr_unary(p); left = expr_binary(p->arena, op, left, right); } return left; @@ -229,15 +318,126 @@ parse_expr(Parser *p){ return parse_expr_ternary(p); } +//----------------------------------------------------------------------------- +// Test code +//----------------------------------------------------------------------------- +function void +token_print(Token *token){ + printf("%.*s", (S32)token->len, token->str); +} + +function void +expr_print(Expr *expr){ + switch(expr->kind) { + case EK_Int:case EK_String:case EK_Identifier: { + token_print(expr->token); + } break; + + case EK_Sizeof:{ + printf("sizeof("); + if(expr->size_of.kind == SIZEOF_Expr){ + expr_print(expr->size_of.expr); + } + else{ + assert(expr->size_of.kind == SIZEOF_Type); + //print_typespec(expr->size_of.type); + } + printf(")"); + }break; + + case EK_Paren:{ + printf("("); + expr_print(expr->paren.expr); + printf(")"); + } break; + + case EK_Field:{ + expr_print(expr->field.expr); + printf(".%s", expr->field.name.s.str); + } break; + + case EK_Binary:{ + printf("("); + expr_print(expr->binary.left); + token_print(expr->token); + expr_print(expr->binary.right); + printf(")"); + } break; + + case EK_PostfixUnary:{ + printf("("); + expr_print(expr->unary.expr); + token_print(expr->token); + printf(")"); + } break; + + case EK_Unary:{ + printf("("); + token_print(expr->token); + expr_print(expr->unary.expr); + printf(")"); + } break; + + case EK_Ternary:{ + printf("("); + expr_print(expr->ternary.cond); + printf("?"); + expr_print(expr->ternary.on_true); + printf(":"); + expr_print(expr->ternary.on_false); + printf(")"); + } break; + + case EK_Cast:{ + printf("("); + printf("("); + //print_typespec(expr->cast.type); + printf(")"); + expr_print(expr->cast.expr); + printf(")"); + } break; + + case EK_Index:{ + expr_print(expr->index.atom); + printf("["); + expr_print(expr->index.index); + printf("]"); + }break; + + case EK_Call:{ + expr_print(expr->call.atom); + printf("("); + for(Expr *n = expr->call.first; n; n=n->next){ + expr_print(n); + if(n!=expr->call.last) printf(","); + } + printf(")"); + }break; + default: {invalid_codepath;} break; + } +} + + function S64 eval_expr(Expr *expr){ switch(expr->kind){ case EK_Int: return expr->int_val; break; + case EK_Unary:{ + S64 left = eval_expr(expr->unary.expr); + switch(expr->unary.op){ + case TK_Not: return !left; break; + case TK_Neg: return ~left; break; + case TK_Sub: return -left; break; + case TK_Add: return +left; break; + default: invalid_codepath; + } + } break; case EK_Ternary:{ S64 cond = eval_expr(expr->ternary.cond); if(cond) return eval_expr(expr->ternary.on_true); else return eval_expr(expr->ternary.on_false); } break; + case EK_Paren: return eval_expr(expr->paren.expr); break; case EK_Binary: { S64 left = eval_expr(expr->binary.left); S64 right = eval_expr(expr->binary.right); @@ -273,10 +473,14 @@ parse_test(){ Arena *scratch = arena_begin_scratch(); String test_case = lit("32+52-242*2/424%5-23" " 1<<5>>6<<2 " + " 5*(4/3)*(2+5) " " 1&&5*3 " " 1&&5||0 " " 1>5>=5==0 " " 1>5 ? 1 : 2 " + " !!!!!1 " + " ~~1 + -!2 " + " 1 + ++Thing[12]++ + ++Thing[12].expr + --Not_Thing[156](Thing) + test_func(func1, func2, func3)" ); Parser parser = { .tokens = lex_stream(scratch, test_case, lit("expr_test")), @@ -288,10 +492,13 @@ parse_test(){ S64 test_val[] = { (32+52-242*2/424%5-23), (((1<<5)>>6)<<2), + 5*(4/3)*(2+5), 1&&(t*3), (1&&t)||0, 1>t>=t==0, 1>t ? 1 : 2, + !!!!!1, + ~~1 + -!2, }; for(int i = 0; i < buff_cap(test_val); i++){ Expr *expr = parse_expr(p); @@ -299,6 +506,9 @@ parse_test(){ assert(val == test_val[i]); } + Expr *expr = parse_expr(p); + expr_print(expr); + arena_end_scratch(); } diff --git a/os_win32.c b/os_win32.c index 9e91a79..0fd5f2c 100644 --- a/os_win32.c +++ b/os_win32.c @@ -8,7 +8,7 @@ os_read_file(Arena *arena, String name){ assert(f); fseek(f, 0, SEEK_END); result.len = ftell(f); - fseek(f, 0, SEEK_SET); /* same as rewind(f); */ + fseek(f, 0, SEEK_SET); result.str = arena_push_size(arena, result.len + 1); fread(result.str, result.len, 1, f); diff --git a/token_array.c b/token_array.c index 6fba214..7f111de 100644 --- a/token_array.c +++ b/token_array.c @@ -92,6 +92,7 @@ token_array_iter_peek(Token_Array *array, S64 i){ Token *result = array->iter_bucket->data + over; array->iter_len = save_len; array->iter_bucket = save_bucket; + array->iter_block = save_block; return result; }