More parsing of expressions

This commit is contained in:
Krzosa Karol
2022-05-06 21:58:09 +02:00
parent 76a8cc779c
commit 501e42be19
6 changed files with 661 additions and 267 deletions

View File

@@ -1,69 +0,0 @@
typedef struct Token_Bucket Token_Bucket;
typedef struct Token_Array Token_Array;
struct Token_Bucket{
Token_Bucket*next;
Token data[4096];
};
struct Token_Array{
Intern_Table interns;
Token_Bucket first;
Token_Bucket*last;
S64 len;
S64 block;
Arena*arena;
Token_Bucket*iter_bucket;
S64 iter_len;
S64 iter_block;
};
function Token_Array token_array_make(Arena*arena){
Token_Array result={
.last=&result.first,.arena=arena,.interns=intern_table(arena,4096*4)};
return result;
}
function void token_array_push(Token_Array*array,Token*p){
if(array->len>=buff_cap(array->first.data)){
Token_Bucket*bucket=arena_push_struct(array->arena,Token_Bucket);
array->last=array->last->next=bucket;
array->len=0;
array->block+=1;
}
array->last->data[array->len++]=*p;
}
function B32 token_array_iter_is_end(Token_Array*array){
B32 result=array->iter_len==array->len&&array->iter_block==array->block;
return result;
}
function Token*token_array_iter_next(Token_Array*array){
if(token_array_iter_is_end(array)){
return0;
}
if(array->iter_len>=buff_cap(array->first.data)){
array->iter_len=0;
array->iter_block+=1;
array->iter_bucket=array->iter_bucket->next;
}
Token*result=array->iter_bucket->data+array->iter_len++;
return result;
}
function Token*token_array_iter_peek(Token_Array*array,S64 i){
S64 save_len=array->iter_len;
Token_Bucket*save_bucket=array->iter_bucket;
assert(i<buff_cap(array->first.data));
S64 over=i;
if(array->iter_len+i>=buff_cap(array->first.data)){
over=buff_cap(array->first.data)-(array->iter_len+i);
array->iter_len=0;
array->iter_bucket=array->iter_bucket->next;
}
Token*result=array->iter_bucket->data+array->iter_len+over;
array->iter_len=save_len;
array->iter_bucket=save_bucket;
return result;
}
function Token*token_array_iter_begin(Token_Array*array){
array->iter_len=0;
array->iter_block=0;
array->iter_bucket=&array->first;
Token*result=token_array_iter_next(array);
return result;
}

View File

@@ -8,129 +8,91 @@ typedef struct Lex_Stream Lex_Stream;
typedef struct Tokens Tokens; typedef struct Tokens Tokens;
struct Intern_String{ struct Intern_String{
String s; String s;
}; };
typedef enum Token_Kind{ typedef enum Token_Kind{
TK_End, TK_End,
TK_Mul, TK_Mul,
TK_Div, TK_Div,
TK_Add, TK_Add,
TK_Sub, TK_Sub,
TK_Mod, TK_Mod,
TK_BitAnd, TK_BitAnd,
TK_BitOr, TK_BitOr,
TK_BitXor, TK_BitXor,
TK_Neg, TK_Neg,
TK_Not, TK_Not,
TK_OpenParen, TK_OpenParen,
TK_CloseParen, TK_CloseParen,
TK_OpenBrace, TK_OpenBrace,
TK_CloseBrace, TK_CloseBrace,
TK_OpenBracket, TK_OpenBracket,
TK_CloseBracket, TK_CloseBracket,
TK_Comma, TK_Comma,
TK_Pound, TK_Pound,
TK_Question, TK_Question,
TK_ThreeDots, TK_ThreeDots,
TK_Semicolon, TK_Semicolon,
TK_Dot, TK_Dot,
TK_LesserThen, TK_LesserThen,
TK_GreaterThen, TK_GreaterThen,
TK_Colon, TK_Colon,
TK_Assign, TK_Assign,
TK_DivAssign, TK_DivAssign,
TK_MulAssign, TK_MulAssign,
TK_ModAssign, TK_ModAssign,
TK_SubAssign, TK_SubAssign,
TK_AddAssign, TK_AddAssign,
TK_AndAssign, TK_AndAssign,
TK_OrAssign, TK_OrAssign,
TK_XorAssign, TK_XorAssign,
TK_LeftShiftAssign, TK_LeftShiftAssign,
TK_RightShiftAssign, TK_RightShiftAssign,
TK_DoubleColon, TK_DoubleColon,
TK_At, TK_At,
TK_Decrement, TK_Decrement,
TK_Increment, TK_Increment,
TK_PostDecrement, TK_PostDecrement,
TK_PostIncrement, TK_PostIncrement,
TK_LesserThenOrEqual, TK_LesserThenOrEqual,
TK_GreaterThenOrEqual, TK_GreaterThenOrEqual,
TK_Equals, TK_Equals,
TK_And, TK_And,
TK_Or, TK_Or,
TK_NotEquals, TK_NotEquals,
TK_LeftShift, TK_LeftShift,
TK_RightShift, TK_RightShift,
TK_Arrow, TK_Arrow,
TK_ExprSizeof, TK_ExprSizeof,
TK_DocComment, TK_DocComment,
TK_Comment, TK_Comment,
TK_Identifier, TK_Identifier,
TK_StringLit, TK_StringLit,
TK_U8Lit, TK_U8Lit,
TK_Character, TK_Character,
TK_Error, TK_Error,
TK_Float, TK_Float,
TK_Int, TK_Int,
TK_Keyword, TK_Keyword,
}Token_Kind; }Token_Kind;
struct Token{ struct Token{
Token_Kind kind; Token_Kind kind;
union{ union{
struct{ struct{
U8 (*str); U8 (*str);
S64 len; S64 len;
}; };
String string; String string;
}; };
union{ union{
S64 int_val; S64 int_val;
String error_val; String error_val;
Intern_String intern_val; Intern_String intern_val;
}; };
String file; String file;
S64 line; S64 line;
U8 (*line_begin); U8 (*line_begin);
};
// Generated Array block
typedef struct Token_Array Token_Array;
typedef struct Token_Array_Block Token_Array_Block;
typedef struct Token_Array_Iter Token_Array_Iter;
struct Token_Array_Block{
Token_Array_Block*next;
Token data[4096];
};
struct Token_Array_Iter{
Token_Array_Block*block;
U32 iter_len;
U32 iter_block;
U32 total_len;
U32 total_block;
};
struct Token_Array{
Token_Array_Block first;
Token_Array_Block*last;
Token_Array_Iter it;
Arena*arena;
S64 block;
S64 len;
};
struct Lex_Stream{
U8 (*stream);
U8 (*line_begin);
String filename;
S64 line;
};
struct Tokens{
Token (*tokens);
S64 len;
S64 cap;
S64 iter;
}; };

177
new_ast.c
View File

@@ -4,6 +4,7 @@ typedef struct Decl Decl;
typedef struct Stmt Stmt; typedef struct Stmt Stmt;
typedef struct Stmt_If Stmt_If; typedef struct Stmt_If Stmt_If;
typedef struct Typespec Typespec; typedef struct Typespec Typespec;
typedef struct Typespec_Function_Arg Typespec_Function_Arg;
typedef struct Decl_Enum_Child Decl_Enum_Child; typedef struct Decl_Enum_Child Decl_Enum_Child;
typedef struct Decl_Function_Arg Decl_Function_Arg; typedef struct Decl_Function_Arg Decl_Function_Arg;
typedef struct Expr_Compound_Field Expr_Compound_Field; typedef struct Expr_Compound_Field Expr_Compound_Field;
@@ -130,15 +131,20 @@ typedef enum Typespec_Kind{
TS_Pointer, TS_Pointer,
TS_Array, TS_Array,
TS_Function, TS_Function,
TS_NamedArgument,
}Typespec_Kind; }Typespec_Kind;
struct Typespec{ struct Typespec{
Typespec_Kind kind;
Typespec *next; Typespec *next;
Typespec_Kind kind;
Token *pos; Token *pos;
union{ union{
Typespec *base;
Intern_String name;
struct{
Intern_String name; Intern_String name;
Typespec *base; Typespec *base;
}named;
struct{ struct{
Typespec *first; Typespec *first;
Typespec *last; Typespec *last;
@@ -165,15 +171,6 @@ typedef enum Decl_Kind{
DECL_List, DECL_List,
}Decl_Kind; }Decl_Kind;
struct Note{
Token *pos;
Intern_String name;
Expr *expr;
Note *next;
Note *first;
Note *last;
};
struct Decl{ struct Decl{
Decl_Kind kind; Decl_Kind kind;
Decl *next; Decl *next;
@@ -208,7 +205,7 @@ struct Decl{
Decl_Function_Arg *first; Decl_Function_Arg *first;
Decl_Function_Arg *last; Decl_Function_Arg *last;
Typespec *ret; Typespec *ret;
//Stmt *body; Stmt *body;
}func_decl; }func_decl;
struct{ struct{
Decl *first; Decl *first;
@@ -217,6 +214,15 @@ struct Decl{
}; };
}; };
struct Note{
Token *pos;
Intern_String name;
Expr *expr;
Note *next;
Note *first;
Note *last;
};
struct Decl_Function_Arg{ struct Decl_Function_Arg{
Decl_Function_Arg *next; Decl_Function_Arg *next;
Token *pos; Token *pos;
@@ -439,11 +445,148 @@ expr_compound_push(Expr *list, Expr_Compound_Field *field){
SLLQueuePush(list->compound.first, list->compound.last, field); SLLQueuePush(list->compound.first, list->compound.last, field);
} }
//-----------------------------------------------------------------------------
// Type specifier constructors
//-----------------------------------------------------------------------------
function Typespec *
typespec_new(Arena *p, Typespec_Kind kind, Token *pos){
Typespec *result = arena_push_struct(p, Typespec);
result->kind = kind;
result->pos = pos;
return result;
}
function Typespec *
typespec_name(Arena *p, Token *pos, Intern_String name){
Typespec *result = typespec_new(p, TS_Name, pos);
result->name = name;
return result;
}
function Typespec *
typespec_pointer(Arena *p, Token *pos, Typespec *base){
Typespec *result = typespec_new(p, TS_Pointer, pos);
result->base = base;
return result;
}
function Typespec *
typespec_array(Arena *p, Token *pos, Typespec *base, Expr *size){
Typespec *result = typespec_new(p, TS_Array, pos);
result->arr.base = base;
result->arr.size = size;
return result;
}
function Typespec *
typespec_function(Arena *p, Token *pos, Typespec *ret){
Typespec *result = typespec_new(p, TS_Function, pos);
result->func.ret = ret;
return result;
}
function Typespec *
typespec_named_argument(Arena *arena, Token *pos, Typespec *typespec, Intern_String name){
Typespec *result = typespec_new(arena, TS_NamedArgument, pos);
result->named.base = typespec;
result->named.name = name;
return result;
}
function void
typespec_function_push(Typespec *func, Typespec *arg){
SLLQueuePush(func->func.first, func->func.last, arg);
}
//-----------------------------------------------------------------------------
// Declarations
//-----------------------------------------------------------------------------
function Decl *
decl_new(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){
Decl *result = arena_push_struct(p, Decl);
result->kind = kind;
result->pos = pos;
result->name = name;
return result;
}
function Decl *
decl_struct(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){
assert(kind == DECL_Struct || kind == DECL_Union);
Decl *result = decl_new(p, kind, pos, name);
return result;
}
function Decl *
decl_typedef(Arena *p, Token *pos, Intern_String name, Typespec *type){
Decl *result = decl_new(p, DECL_Typedef, pos, name);
result->typedef_decl.type = type;
return result;
}
function Decl *
decl_enum(Arena *p, Token *pos, Intern_String name, Typespec *typespec){
Decl *result = decl_new(p, DECL_Enum, pos, name);
result->enum_decl.typespec = typespec;
return result;
}
function Decl *
decl_variable(Arena *p, Token *pos, Intern_String name, Typespec *typespec, Expr *expr){
Decl *result = decl_new(p, DECL_Variable, pos, name);
result->var_decl.type = typespec;
result->var_decl.expr = expr;
return result;
}
function Decl *
decl_function(Arena *p, Token *pos, Intern_String name, Typespec *ret){
Decl *result = decl_new(p, DECL_Function, pos, name);
result->func_decl.ret = ret;
return result;
}
function void
decl_func_push(Arena *p, Decl *parent, Token *pos, Intern_String name, Typespec *type){
assert(parent->kind == DECL_Function);
Decl_Function_Arg *result = arena_push_struct(p, Decl_Function_Arg);
result->name = name;
result->typespec = type;
result->pos = pos;
SLLQueuePush(parent->func_decl.first, parent->func_decl.last, result);
}
function void
decl_enum_push(Arena *p, Decl *parent, Token *pos, Intern_String name, Expr *expr, Note *notes){
assert(parent->kind == DECL_Enum);
Decl_Enum_Child *child = arena_push_struct(p, Decl_Enum_Child);
child->pos = pos;
child->name = name;
child->expr = expr;
child->first_note = notes->first;
child->last_note = notes->last;
SLLQueuePush(parent->enum_decl.first, parent->enum_decl.last, child);
}
function void
decl_struct_push(Decl *parent, Decl *child){
assert(parent->kind == DECL_Struct || parent->kind == DECL_Union);
SLLQueuePush(parent->struct_decl.first, parent->struct_decl.last, child);
}
function void
decl_list_push(Decl *parent, Decl *child){
assert(parent->kind == DECL_List);
SLLQueuePush(parent->list_decl.first, parent->list_decl.last, child);
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Double linked list // Double linked list
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function void function void
decl_list_push(Decl *l, Decl *node){ decl_dll_list_push(Decl *l, Decl *node){
if(l->list_decl.first == 0){ if(l->list_decl.first == 0){
l->list_decl.first = l->list_decl.last = node; l->list_decl.first = l->list_decl.last = node;
node->prev = 0; node->prev = 0;
@@ -459,7 +602,7 @@ decl_list_push(Decl *l, Decl *node){
} }
function void function void
decl_list_push_front(Decl *l, Decl *node){ decl_dll_list_push_front(Decl *l, Decl *node){
if(l->list_decl.first == 0){ if(l->list_decl.first == 0){
l->list_decl.first = l->list_decl.last = node; l->list_decl.first = l->list_decl.last = node;
node->prev = 0; node->prev = 0;
@@ -523,10 +666,10 @@ ast_test(){
decls[2].kind = 2; decls[2].kind = 2;
decls[3].kind = 3; decls[3].kind = 3;
decls[4].kind = 4; decls[4].kind = 4;
decl_list_push(decls, decls+1); decl_dll_list_push(decls, decls+1);
decl_list_push(decls, decls+2); decl_dll_list_push(decls, decls+2);
decl_list_push(decls, decls+3); decl_dll_list_push(decls, decls+3);
decl_list_push_front(decls, decls+4); decl_dll_list_push_front(decls, decls+4);
//list_print(decls); //list_print(decls);
decl_list_remove(decls, decls+1); decl_list_remove(decls, decls+1);

View File

@@ -4,6 +4,7 @@ global Intern_String keyword_cast;
global Intern_String keyword_else; global Intern_String keyword_else;
global Intern_String keyword_size_type; global Intern_String keyword_size_type;
global Intern_String keyword_size_expr; global Intern_String keyword_size_expr;
global Intern_String keyword_const;
global Intern_String keyword_typeof; global Intern_String keyword_typeof;
global Intern_String keyword_while; global Intern_String keyword_while;
global Intern_String keyword_switch; global Intern_String keyword_switch;
@@ -14,6 +15,9 @@ global Intern_String keyword_union;
global U8 *first_keyword; global U8 *first_keyword;
global U8 *last_keyword; global U8 *last_keyword;
global Intern_String intern_void;
global Intern_String intern_int;
function void function void
init_default_keywords(Intern_Table *t){ init_default_keywords(Intern_Table *t){
keyword_if = intern_string(t, lit("if")); keyword_if = intern_string(t, lit("if"));
@@ -25,6 +29,7 @@ init_default_keywords(Intern_Table *t){
keyword_size_type = intern_string(t, lit("size_type")); keyword_size_type = intern_string(t, lit("size_type"));
keyword_size_expr = intern_string(t, lit("size_expr")); keyword_size_expr = intern_string(t, lit("size_expr"));
keyword_typeof = intern_string(t, lit("typeof")); keyword_typeof = intern_string(t, lit("typeof"));
keyword_const = intern_string(t, lit("const"));
keyword_while = intern_string(t, lit("while")); keyword_while = intern_string(t, lit("while"));
keyword_switch = intern_string(t, lit("switch")); keyword_switch = intern_string(t, lit("switch"));
keyword_case = intern_string(t, lit("case")); keyword_case = intern_string(t, lit("case"));
@@ -33,6 +38,9 @@ init_default_keywords(Intern_Table *t){
keyword_union = intern_string(t, lit("union")); keyword_union = intern_string(t, lit("union"));
last_keyword = keyword_union.s.str; last_keyword = keyword_union.s.str;
intern_void = intern_string(t, lit("void"));
intern_int = intern_string(t, lit("int"));
} }
function B32 function B32
@@ -489,15 +497,32 @@ lex__stream(Token_Array *array, Lex_Stream *s){
} }
} }
function Token_Array function void
lex_stream(Arena *arena, String stream, String file){ lex_add_stream(Token_Array *array, String stream, String file){
Lex_Stream s = {stream, 0, stream.str, file, 0}; Lex_Stream s = {stream, 0, stream.str, file, 0};
lex__stream(array, &s);
}
function Token_Array
lex_make_token_array(Arena *arena){
Token_Array array = token_array_make(arena); Token_Array array = token_array_make(arena);
init_default_keywords(&array.interns); init_default_keywords(&array.interns);
lex__stream(&array, &s);
return array; return array;
} }
function Token_Array
lex_stream(Arena *arena, String stream, String file){
Token_Array array = lex_make_token_array(arena);
lex_add_stream(&array, stream, file);
return array;
}
function void
lex_restream(Token_Array *array, String stream, String file){
token_array_reset(array);
lex_add_stream(array, stream, file);
}
function void function void
lex_test(){ lex_test(){
Arena *scratch = arena_begin_scratch(); Arena *scratch = arena_begin_scratch();

View File

@@ -29,7 +29,23 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
va_end(args1); va_end(args1);
} }
// @Note(Krzosa): Print nice error message
{
printf("Error: %s %s:%d\n", string.str, token->file.str, (S32)token->line); printf("Error: %s %s:%d\n", string.str, token->file.str, (S32)token->line);
// @Note(Krzosa): Print error line
{
int i = 0;
while(token->line_begin[i]!='\n' && token->line_begin[i]!=0) i++;
printf("%.*s\n", i, token->line_begin);
// @Note(Krzosa): Print error marker
int token_i = token->str - token->line_begin;
for(int i = 0; i < token_i-2; i++) printf(" ");
printf("^^^^^^\n");
}
}
Parser_Error *error = arena_push_struct(p->arena, Parser_Error); Parser_Error *error = arena_push_struct(p->arena, Parser_Error);
error->message = string; error->message = string;
error->next = 0; error->next = 0;
@@ -48,6 +64,20 @@ token_get(Parser *p){
return result; return result;
} }
function Token *
token_peek(Parser *p, S64 i){
Token *result = token_array_iter_peek(&p->tokens, i);
return result;
}
function Token *
token_peek_is(Parser *p, Token_Kind kind, S64 i){
Token *result = token_peek(p, i);
if(result->kind == kind)
return result;
return 0;
}
function Token * function Token *
token_is(Parser *p, Token_Kind kind){ token_is(Parser *p, Token_Kind kind){
Token *result = token_get(p); Token *result = token_get(p);
@@ -95,6 +125,8 @@ token_expect(Parser *p, Token_Kind kind){
return 0; return 0;
} }
function Typespec *parse_typespec(Parser *p);
function Expr *parse_expr(Parser *p);
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Expression parsing // Expression parsing
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
@@ -112,6 +144,9 @@ atom_expr = Int
| 'cast' '(' typespec ',' expr ')' | 'cast' '(' typespec ',' expr ')'
| 'size_type' '(' typespec ')' | 'size_type' '(' typespec ')'
| 'size_expr' '(' expr ')' | 'size_expr' '(' expr ')'
| '{' compound_expr '}'
| '(' expr ')'
| '(' ':' typespec ')' '{' compound_expr '}'
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')* postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
unary_expr = unary ? unary_expr : atom_expr unary_expr = unary ? unary_expr : atom_expr
mul_expr = atom_expr (mul atom_expr)* mul_expr = atom_expr (mul atom_expr)*
@@ -120,57 +155,16 @@ logical_expr = add_expr (logical add_expr)*
compare_expr = logical_expr (compare logical_expr)* compare_expr = logical_expr (compare logical_expr)*
ternary_expr = compare_expr ('?' ternary_expr ':' ternary_expr)? ternary_expr = compare_expr ('?' ternary_expr ':' ternary_expr)?
expr = logical_expr expr = logical_expr
Compound literals
- (:[23]*Type){}
- Type{}
- { }
*/ */
function Expr *parse_expr(Parser *p);
function Expr *
parse_expr_atom(Parser *p){
Token *token = 0;
if((token = token_match(p, TK_StringLit))){
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);
token_expect(p, TK_Comma);
token_expect(p, TK_Identifier);
token_expect(p, TK_CloseParen);
return 0;
}
else{
parser_push_error(p, token_get(p), "Failed to parse expression");
return 0;
}
}
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_Compound_Field * function Expr_Compound_Field *
parse_expr_compound(Parser *p){ parse_expr_compound_field(Parser *p){
Token *token = token_get(p); Token *token = token_get(p);
Expr_Compound_Field *result = 0; Expr_Compound_Field *result = 0;
if(token_match(p, TK_OpenBracket)){ if(token_match(p, TK_OpenBracket)){
@@ -196,6 +190,81 @@ parse_expr_compound(Parser *p){
return result; return result;
} }
function Expr *
parse_expr_compound(Parser *p, Typespec *typespec){
Token *token = token_expect(p, TK_OpenBrace);
Expr *expr = expr_compound(p->arena, token, typespec);
while(!token_is(p, TK_CloseBrace)){
Expr_Compound_Field *field = parse_expr_compound_field(p);
expr_compound_push(expr, field);
if(!token_match(p, TK_Comma)){
break;
}
}
token_expect(p, TK_CloseBrace);
return expr;
}
function Expr *
parse_expr_atom(Parser *p){
Expr *result = 0;
Token *token = token_get(p);
if(token_match(p, TK_StringLit)){
result = expr_str(p->arena, token);
}
else if(token_match(p, TK_Identifier)){
if(token_is(p, TK_OpenBrace)){
Typespec *typespec = typespec_name(p->arena, token, token->intern_val);
result = parse_expr_compound(p, typespec);
}
else{
result = expr_identifier(p->arena, token);
}
}
else if(token_match(p, TK_Int)){
result = expr_int(p->arena, token);
}
else if(token_is(p, TK_OpenBrace)){
result = parse_expr_compound(p, 0);
}
else if(token_match(p, TK_OpenParen)){
if(token_match(p, TK_Colon)){
Typespec *typespec = parse_typespec(p);
token_expect(p, TK_CloseParen);
result = parse_expr_compound(p, typespec);
}
else{
Expr *expr = parse_expr(p);
token_expect(p, TK_CloseParen);
result = expr_paren(p->arena, token, expr);
}
}
else if(token_match_keyword(p, keyword_cast)){
token_expect(p, TK_OpenParen);
Typespec *typespec = parse_typespec(p);
token_expect(p, TK_Comma);
Expr *expr = parse_expr(p);
token_expect(p, TK_CloseParen);
result = expr_cast(p->arena, token, typespec, expr);
}
else{
parser_push_error(p, token, "Failed to parse expression");
}
return result;
}
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_Compound_Field * function Expr_Compound_Field *
parse_expr_function_argument(Parser *p){ parse_expr_function_argument(Parser *p){
Token *token = token_get(p); Token *token = token_get(p);
@@ -365,10 +434,171 @@ parse_expr(Parser *p){
return parse_expr_ternary(p); return parse_expr_ternary(p);
} }
//-----------------------------------------------------------------------------
// Type specifier parsing
//-----------------------------------------------------------------------------
/*
base_type = NAME
| '(' type_list? ')' type?
type = ('*' | '[' expr ']')* base_type
Examples:
[32]*U32 - Array of 32 pointers to U32
**CustomDataType - Pointer to pointer of CustomDataType
(*U32, S64) **S64 - Function pointer
(CoolType: optional, S32) - Implicit void return value
*/
function Typespec *
parse_typespec_function(Parser *p, Token *token){
Typespec *result = typespec_function(p->arena, token, 0);
if(!token_is(p, TK_CloseParen))
for(;;) {
// Optional name
Token *name = 0;
if((token = token_is(p, TK_Identifier))){
if(token_peek_is(p, TK_Colon, 1)){
token_next(p);
token_next(p);
name = token;
}
}
// Parse type
Typespec *arg = parse_typespec(p);
if(name)
arg = typespec_named_argument(p->arena, name, arg, name->intern_val);
typespec_function_push(result, arg);
if(!token_match(p, TK_Comma)){
break;
}
}
token_expect(p, TK_CloseParen);
if(token_is(p, TK_Identifier)
|| token_is(p, TK_OpenParen)
|| token_is(p, TK_Mul)
|| token_is(p, TK_OpenBracket))
result->func.ret = parse_typespec(p);
else
result->func.ret = typespec_name(p->arena, token_get(p), intern_void);
return result;
}
// [10]*int - Array of 10 pointers to ints
function Typespec *
parse_typespec_recurse(Parser *p){
Token *token = token_get(p);
if(token_match(p, TK_Mul)){
Typespec *result = parse_typespec_recurse(p);
result = typespec_pointer(p->arena, token, result);
return result;
}
else if(token_match(p, TK_OpenBracket)){
Expr *expr = parse_expr(p);
token_expect(p, TK_CloseBracket);
Typespec *result = parse_typespec_recurse(p);
result = typespec_array(p->arena, token, result, expr);
return result;
}
else if(token_match(p, TK_OpenParen)){
Typespec *result = parse_typespec_function(p, token);
return result;
}
else if(token_match(p, TK_Identifier)){
Typespec *result = typespec_name(p->arena, token, token->intern_val);
return result;
}
else{
parser_push_error(p, token, "Failed to parse type, unexpected token");
return 0;
}
}
function Typespec *
parse_typespec(Parser *p){
Typespec *result = parse_typespec_recurse(p);
return result;
}
//-----------------------------------------------------------------------------
// Parsing decls
//-----------------------------------------------------------------------------
/*
name::(param:U32)*U32{}
name::struct{}
name::union{}
name::enum{}
name::typedef = name2;
name::const = 4254;
*/
function Decl *
parse_enum(Parser *p, Token *name){
Typespec *typespec = 0;
if(token_match(p, TK_Colon)){
typespec = parse_typespec(p);
}
else{
typespec = typespec_name(p->arena, token_get(p), intern_int);
}
Decl *result = decl_enum(p->arena, name, name->intern_val, typespec);
token_expect(p, TK_OpenBrace);
do{
Token *val = token_expect(p, TK_Identifier);
Expr *expr = 0;
if(token_match(p, TK_Assign)){
expr = parse_expr(p);
}
decl_enum_push(p->arena, result, val, val->intern_val, expr, 0);
} while(token_is(p, TK_Comma));
token_expect(p, TK_CloseBrace);
return result;
}
function Decl *
parse_decl(Parser *p){
Decl *result = 0;
Token *name = 0;
if((name = token_match(p, TK_Identifier))){
if(token_match(p, TK_DoubleColon)){
Token *token = 0;
if((token = token_match_keyword(p, keyword_enum))){
result = parse_enum(p, name);
}
else if((token = token_match_keyword(p, keyword_union))){
// Union
}
else if((token = token_match_keyword(p, keyword_struct))){
// Struct
}
else if((token = token_match_keyword(p, keyword_const))){
// Const value
}
else if((token = token_match(p, TK_OpenParen))){
// Function
}
else{
parser_push_error(p, token_get(p), "Expected token of kind todo:decl_tokens");
}
}
else{
parser_push_error(p, token_get(p), "Expected token of kind '::'");
}
}
return result;
}
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// Test code // Test code
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
function void expr_print(Expr *expr); function void expr_print(Expr *expr);
function B32 typespec_print(Typespec *spec);
function void function void
token_print(Token *token){ token_print(Token *token){
printf("%.*s", (S32)token->len, token->str); printf("%.*s", (S32)token->len, token->str);
@@ -408,7 +638,11 @@ expr_print(Expr *expr){
}break; }break;
case EK_Compound:{ case EK_Compound:{
// typespec_print(p); if(expr->compound.typespec){
printf("(");
typespec_print(expr->compound.typespec);
printf(")");
}
printf("{"); printf("{");
for(Expr_Compound_Field *n = expr->compound.first; n; n=n->next){ for(Expr_Compound_Field *n = expr->compound.first; n; n=n->next){
expr_compound_print(n); expr_compound_print(n);
@@ -468,7 +702,7 @@ expr_print(Expr *expr){
case EK_Cast:{ case EK_Cast:{
printf("("); printf("(");
printf("("); printf("(");
//print_typespec(expr->cast.type); typespec_print(expr->cast.typespec);
printf(")"); printf(")");
expr_print(expr->cast.expr); expr_print(expr->cast.expr);
printf(")"); printf(")");
@@ -494,6 +728,46 @@ expr_print(Expr *expr){
} }
} }
function B32
typespec_print(Typespec *spec){
switch(spec->kind) {
case TS_Name: {
printf("%s", spec->name.s.str);
} break;
case TS_NamedArgument: {
printf("%s: ", spec->named.name.s.str);
typespec_print(spec->named.base);
}break;
case TS_Pointer: {
typespec_print(spec->base);
printf("*");
} break;
case TS_Array: {
typespec_print(spec->arr.base);
printf("[");
expr_print(spec->arr.size);
printf("]");
} break;
case TS_Function: {
printf("(");
for(Typespec *n = spec->func.first; n; n=n->next){
typespec_print(n);
if(n!=spec->func.last)
printf(", ");
}
printf(")");
typespec_print(spec->func.ret);
} break;
default: {invalid_codepath;} break;
}
return true;
}
function S64 function S64
eval_expr(Expr *expr){ eval_expr(Expr *expr){
@@ -545,8 +819,34 @@ eval_expr(Expr *expr){
return 0; return 0;
} }
function Parser
parser_make(Arena *arena){
Parser result = {
.tokens = lex_make_token_array(arena),
.arena = arena,
};
return result;
}
function void function void
parse_test(){ parser_restream(Parser *p, String stream, String file){
lex_restream(&p->tokens, stream, file);
}
function Parser
parser_make_stream(Arena *arena, String stream, String file){
Parser parser = parser_make(arena);
lex_restream(&parser.tokens, stream, file);
return parser;
}
function void
parser_add_stream(Parser *p, String string, String file){
lex_add_stream(&p->tokens, string, file);
}
function void
parse_test_expr(){
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 "
@@ -558,12 +858,9 @@ parse_test(){
" 1>5 ? 1 : 2 " " 1>5 ? 1 : 2 "
" !!!!!1 " " !!!!!1 "
" ~~1 + -!2 " " ~~1 + -!2 "
" 1 + ++Thing[12]++ + ++Thing[12].expr + --Not_Thing[156](Thing) + test_func(asd=func1, af=func2, gg=func3)" " 1 + ++Thing[12]++ + ++Thing[12].expr +"
); );
Parser parser = { Parser parser = parser_make_stream(scratch, test_case, lit("Big_Expr"));
.tokens = lex_stream(scratch, test_case, lit("expr_test")),
.arena = scratch,
};
Parser *p = &parser; Parser *p = &parser;
S64 t = 5; S64 t = 5;
@@ -585,10 +882,33 @@ parse_test(){
assert(val == test_val[i]); assert(val == test_val[i]);
} }
String exprs[] = {
lit("cast([12](thing: U32, qwe: *U32) [32]Result, (123+234))"),
lit("cast((thing: U32, qwe: *U32), (123+234))"),
lit("(:(U32,U32)){Thing=10}"),
lit("--Not_Thing[156](Thing) + test_func(asd=func1, af=func2, gg=func3)"),
lit("(:[23]*Type){Thing=10}"),
lit("cast(**Data,{Thing=10})"),
lit("(:[64]S64){1,2,3,4,5}"),
lit("Data_Type{1,2,3,4,5}"),
};
for(SizeU i = 0; i < buff_cap(exprs); i++){
parser_restream(p, exprs[i], lit("Test_Exprs"));
Expr *expr = parse_expr(p); Expr *expr = parse_expr(p);
expr_print(expr); expr_print(expr);
printf("\n");
}
arena_end_scratch(); arena_end_scratch();
} }
function void
parse_test_decls(){
}
function void
parse_test(){
parse_test_expr();
parse_test_decls();
}

View File

@@ -96,6 +96,19 @@ token_array_iter_peek(Token_Array *array, S64 i){
return result; return result;
} }
function void
token_array_reset(Token_Array *array){
// @Todo(Krzosa): Add free list
assert(&array->first == array->last);
array->len = 0;
array->block = 0;
array->last = &array->first;
array->last->next = 0;
array->iter_bucket = array->last;
array->iter_len = 0;
array->iter_block = 0;
}
function Token * function Token *
token_array_iter_begin(Token_Array *array){ token_array_iter_begin(Token_Array *array){
array->iter_len = 0; array->iter_len = 0;