Added almost all expr operators

This commit is contained in:
Krzosa Karol
2022-05-06 12:52:33 +02:00
parent 9552126da2
commit 7e3eefda57
6 changed files with 266 additions and 117 deletions

View File

@@ -2,5 +2,5 @@
rem clang generate.c -fdiagnostics-absolute-paths -std=c99 -g -o generate.exe -Wl,user32.lib rem clang generate.c -fdiagnostics-absolute-paths -std=c99 -g -o generate.exe -Wl,user32.lib
rem generate.exe 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 rem cl main.c -std:c17

1
main.c
View File

@@ -17,6 +17,5 @@
int main(){ int main(){
lex_test(); lex_test();
test_ast();
parse_test(); parse_test();
} }

155
new_ast.c
View File

@@ -41,11 +41,13 @@ typedef enum Expr_Kind{
EK_Int, EK_Int,
EK_String, EK_String,
EK_Identifier, EK_Identifier,
EK_Paren,
EK_PostfixUnary,
EK_Unary, EK_Unary,
EK_Binary, EK_Binary,
EK_Ternary, EK_Ternary,
EK_Cast, EK_Cast,
EK_List, EK_Field,
EK_Call, EK_Call,
EK_Index, EK_Index,
EK_Sizeof, EK_Sizeof,
@@ -59,18 +61,24 @@ struct Expr {
U64 int_val; U64 int_val;
Intern_String intern_val; Intern_String intern_val;
double float_val; double float_val;
struct {
Expr *expr;
} paren;
struct { struct {
Typespec *type; Typespec *type;
Expr* expr; Expr* expr;
} cast; } cast;
struct {
Expr *first; struct{
Expr *last; Intern_String name;
} list; Expr *expr;
}field;
struct { struct {
Expr *atom; Expr *atom;
Expr *list; Expr *first;
Expr *last;
} call; } call;
struct { struct {
Expr *atom; Expr *atom;
@@ -80,6 +88,10 @@ struct Expr {
Token_Kind op; Token_Kind op;
Expr* expr; Expr* expr;
} unary; } unary;
struct {
Token_Kind op;
Expr *expr;
} postfix_unary;
struct { struct {
Token_Kind op; Token_Kind op;
Expr* left; Expr* left;
@@ -90,6 +102,7 @@ struct Expr {
Expr* on_true; Expr* on_true;
Expr* on_false; Expr* on_false;
} ternary; } ternary;
struct{ struct{
Expr_Sizeof_Kind kind; Expr_Sizeof_Kind kind;
union{ union{
@@ -128,13 +141,37 @@ expr_str(Arena *p, Token *token){
} }
function Expr * function Expr *
expr_name(Arena *p, Token *token){ expr_identifier(Arena *p, Token *token){
assert(token->kind == TK_Identifier); assert(token->kind == TK_Identifier);
Expr *expr = expr_new(p, EK_Identifier, token); Expr *expr = expr_new(p, EK_Identifier, token);
expr->intern_val = token->intern_val; expr->intern_val = token->intern_val;
return expr; 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 * function Expr *
expr_unary(Arena *p, Token *op, Expr *exp){ expr_unary(Arena *p, Token *op, Expr *exp){
Expr *expr = expr_new(p, EK_Unary, op); 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 * 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 *expr = expr_new(p, EK_Call, token);
expr->call.atom = atom; expr->call.atom = atom;
expr->call.list = list;
return expr; return expr;
} }
@@ -201,104 +237,7 @@ expr_sizeof_expr(Arena *p, Token *token, Expr *in_expr){
return expr; return expr;
} }
function Expr *
expr_list(Arena *p, Token *token){
Expr *expr = expr_new(p, EK_List, token);
return expr;
}
function void function void
expr_list_push(Expr *list, Expr *expr){ expr_call_push(Expr *list, Expr *expr){
SLLQueuePush(list->list.first, list->list.last, 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(){
} }

View File

@@ -39,7 +39,9 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
__debugbreak(); __debugbreak();
} }
//-----------------------------------------------------------------------------
// Parsing helpers
//-----------------------------------------------------------------------------
function Token * function Token *
token_get(Parser *p){ token_get(Parser *p){
Token *result = token_array_iter_peek(&p->tokens, 0); Token *result = token_array_iter_peek(&p->tokens, 0);
@@ -93,25 +95,31 @@ token_expect(Parser *p, Token_Kind kind){
return 0; return 0;
} }
//-----------------------------------------------------------------------------
// Expression parsing
//-----------------------------------------------------------------------------
/* /*
add = [+-] add = [+-]
mul = [/%*] mul = [/%*]
compare = == | != | >= | > | <= | < compare = == | != | >= | > | <= | <
logical = [&|^] | && | || logical = [&|^] | && | ||
unary = [&*-!~+] | ++ | --
expr_atom = Int atom_expr = Int
| Float | Float
| String | String
| Identifier | Identifier
| 'cast' '(' typespec ',' expr ')' | '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)* add_expr = mul_expr (add mul_expr)*
compare_expr = add_expr (compare add_expr)* compare_expr = add_expr (compare add_expr)*
logical_expr = compare_expr (logical compare_expr)* logical_expr = compare_expr (logical compare_expr)*
ternary_expr = logical_expr ('?' ternary_expr ':' ternary_expr)? ternary_expr = logical_expr ('?' ternary_expr ':' ternary_expr)?
expr = logical_expr expr = logical_expr
*/ */
function Expr *parse_expr(Parser *p);
function Expr * function Expr *
parse_expr_atom(Parser *p){ parse_expr_atom(Parser *p){
@@ -120,10 +128,20 @@ parse_expr_atom(Parser *p){
Expr *result = expr_str(p->arena, token); Expr *result = expr_str(p->arena, token);
return result; 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))){ else if((token = token_match(p, TK_Int))){
Expr *result = expr_int(p->arena, token); Expr *result = expr_int(p->arena, token);
return result; 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))){ else if((token = token_match_keyword(p, keyword_cast))){
token_expect(p, TK_OpenParen); token_expect(p, TK_OpenParen);
token_expect(p, TK_Identifier); 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 function B32
token_is_mul(Parser *p){ token_is_mul(Parser *p){
Token *token = token_get(p); Token *token = token_get(p);
@@ -147,10 +236,10 @@ token_is_mul(Parser *p){
function Expr * function Expr *
parse_expr_mul(Parser *p){ parse_expr_mul(Parser *p){
Expr *left = parse_expr_atom(p); Expr *left = parse_expr_unary(p);
while(token_is_mul(p)){ while(token_is_mul(p)){
Token *op = token_next(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); left = expr_binary(p->arena, op, left, right);
} }
return left; return left;
@@ -229,15 +318,126 @@ parse_expr(Parser *p){
return parse_expr_ternary(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 function S64
eval_expr(Expr *expr){ eval_expr(Expr *expr){
switch(expr->kind){ switch(expr->kind){
case EK_Int: return expr->int_val; break; 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:{ case EK_Ternary:{
S64 cond = eval_expr(expr->ternary.cond); S64 cond = eval_expr(expr->ternary.cond);
if(cond) return eval_expr(expr->ternary.on_true); if(cond) return eval_expr(expr->ternary.on_true);
else return eval_expr(expr->ternary.on_false); else return eval_expr(expr->ternary.on_false);
} break; } break;
case EK_Paren: return eval_expr(expr->paren.expr); break;
case EK_Binary: { case EK_Binary: {
S64 left = eval_expr(expr->binary.left); S64 left = eval_expr(expr->binary.left);
S64 right = eval_expr(expr->binary.right); S64 right = eval_expr(expr->binary.right);
@@ -273,10 +473,14 @@ parse_test(){
Arena *scratch = arena_begin_scratch(); Arena *scratch = arena_begin_scratch();
String test_case = lit("32+52-242*2/424%5-23" String test_case = lit("32+52-242*2/424%5-23"
" 1<<5>>6<<2 " " 1<<5>>6<<2 "
" 5*(4/3)*(2+5) "
" 1&&5*3 " " 1&&5*3 "
" 1&&5||0 " " 1&&5||0 "
" 1>5>=5==0 " " 1>5>=5==0 "
" 1>5 ? 1 : 2 " " 1>5 ? 1 : 2 "
" !!!!!1 "
" ~~1 + -!2 "
" 1 + ++Thing[12]++ + ++Thing[12].expr + --Not_Thing[156](Thing) + test_func(func1, func2, func3)"
); );
Parser parser = { Parser parser = {
.tokens = lex_stream(scratch, test_case, lit("expr_test")), .tokens = lex_stream(scratch, test_case, lit("expr_test")),
@@ -288,10 +492,13 @@ parse_test(){
S64 test_val[] = { S64 test_val[] = {
(32+52-242*2/424%5-23), (32+52-242*2/424%5-23),
(((1<<5)>>6)<<2), (((1<<5)>>6)<<2),
5*(4/3)*(2+5),
1&&(t*3), 1&&(t*3),
(1&&t)||0, (1&&t)||0,
1>t>=t==0, 1>t>=t==0,
1>t ? 1 : 2, 1>t ? 1 : 2,
!!!!!1,
~~1 + -!2,
}; };
for(int i = 0; i < buff_cap(test_val); i++){ for(int i = 0; i < buff_cap(test_val); i++){
Expr *expr = parse_expr(p); Expr *expr = parse_expr(p);
@@ -299,6 +506,9 @@ parse_test(){
assert(val == test_val[i]); assert(val == test_val[i]);
} }
Expr *expr = parse_expr(p);
expr_print(expr);
arena_end_scratch(); arena_end_scratch();
} }

View File

@@ -8,7 +8,7 @@ os_read_file(Arena *arena, String name){
assert(f); assert(f);
fseek(f, 0, SEEK_END); fseek(f, 0, SEEK_END);
result.len = ftell(f); 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); result.str = arena_push_size(arena, result.len + 1);
fread(result.str, result.len, 1, f); fread(result.str, result.len, 1, f);

View File

@@ -92,6 +92,7 @@ token_array_iter_peek(Token_Array *array, S64 i){
Token *result = array->iter_bucket->data + over; Token *result = array->iter_bucket->data + over;
array->iter_len = save_len; array->iter_len = save_len;
array->iter_bucket = save_bucket; array->iter_bucket = save_bucket;
array->iter_block = save_block;
return result; return result;
} }