New syntax that's easier to parse, parsing doesn't need variable lookup

This commit is contained in:
Krzosa Karol
2022-05-03 11:31:21 +02:00
parent 3c376bbe30
commit 8c04044ea2
12 changed files with 1216 additions and 244 deletions

127
ast.c Normal file
View File

@@ -0,0 +1,127 @@
function Decl *
decl_new(Parser *p, Decl_Kind kind, Token *pos, Intern_String name){
Decl *result = arena_push_struct(&p->main_arena, Decl);
result->kind = kind;
result->pos = pos;
result->name = name;
return result;
}
function Decl *
decl_struct(Parser *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(Parser *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(Parser *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(Parser *p, Token *pos, Intern_String name, Typespec *typespec, Expr *expr){
Decl *result = decl_new(p, DECL_Variable, pos, name);
result->variable_decl.type = typespec;
result->variable_decl.expr = expr;
return result;
}
function void
decl_enum_push(Parser *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->main_arena, 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.first, parent->list.last, child);
}
function Note *
note_push_new(Parser *p, Note *parent, Token *pos, Intern_String name, Expr *expr){
Note *result = arena_push_struct(&p->main_arena, Note);
result->pos = pos;
result->name = name;
result->expr = expr;
SLLQueuePush(parent->first, parent->last, result);
return result;
}
function void
decl_pass_notes(Decl *a, Note *b){
a->first_note = b->first;
a->last_note = b->last;
}
function Typespec *
typespec_new(Parser *p, Typespec_Kind kind, Token *pos){
Typespec *result = arena_push_struct(&p->main_arena, Typespec);
result->kind = kind;
result->pos = pos;
return result;
}
function Typespec *
typespec_struct(Parser *p, Token *pos, Decl *aggregate){
Typespec *result = typespec_new(p, TS_Struct, pos);
result->struct_spec = aggregate;
return result;
}
function Typespec *
typespec_name(Parser *p, Token *pos, Intern_String name){
Typespec *result = typespec_new(p, TS_Name, pos);
result->name = name;
return result;
}
function Typespec *
typespec_pointer(Parser *p, Token *pos, Typespec *base){
Typespec *result = typespec_new(p, TS_Pointer, pos);
result->base = base;
return result;
}
function Typespec *
typespec_array(Parser *p, Token *pos, Typespec *base, Expr *size){
Typespec *result = typespec_new(p, TS_Array, pos);
result->array_spec.base = base;
result->array_spec.size = size;
return result;
}
function Typespec *
typespec_function(Parser *p, Token *pos, Typespec *ret){
Typespec *result = typespec_new(p, TS_Function, pos);
result->function_spec.ret = ret;
return result;
}
function void
typespec_function_push(Typespec *func, Typespec *arg){
SLLQueuePush(func->function_spec.first, func->function_spec.last, arg);
}

106
ast.h Normal file
View File

@@ -0,0 +1,106 @@
typedef struct Decl_Enum_Child Decl_Enum_Child;
typedef struct Typespec Typespec;
typedef struct Decl Decl;
typedef struct Note Note;
//-----------------------------------------------------------------------------
// Type specifier
//-----------------------------------------------------------------------------
typedef enum Typespec_Kind{
TS_None,
TS_Name,
TS_Pointer,
TS_Array,
TS_Function,
TS_Struct,
}Typespec_Kind;
struct Typespec{
Typespec_Kind kind;
Typespec *next;
Token *pos;
union{
Intern_String name;
Decl *struct_spec;
struct{
Typespec *first;
Typespec *last;
Typespec *ret;
}function_spec;
struct{
Typespec *base;
Expr *size;
}array_spec;
Typespec *base;
};
};
//-----------------------------------------------------------------------------
// Notes
//-----------------------------------------------------------------------------
struct Note{
Token *pos;
Intern_String name;
Expr *expr;
Note *next;
Note *first;
Note *last;
};
//-----------------------------------------------------------------------------
// Declarations
//-----------------------------------------------------------------------------
typedef enum Decl_Kind{
DECL_None,
DECL_Struct,
DECL_Union,
DECL_Enum,
DECL_Variable,
DECL_Typedef,
DECL_List,
}Decl_Kind;
struct Decl_Enum_Child{
Decl_Enum_Child *next;
Intern_String name;
Token *pos;
Expr *expr;
Note *first_note;
Note *last_note;
};
struct Decl{
Decl_Kind kind;
Intern_String name;
Token *pos;
Decl *next;
Note *first_note;
Note *last_note;
union{
struct{
Decl_Enum_Child *first;
Decl_Enum_Child *last;
Typespec *typespec;
}enum_decl;
struct{
Decl *first;
Decl *last;
} struct_decl;
struct{
Typespec *type;
Expr *expr;
}variable_decl;
struct{
Typespec *type;
}typedef_decl;
struct{
Decl *first;
Decl *last;
}list;
};
};

20
expr.c
View File

@@ -53,15 +53,29 @@ expr_index(Parser *p, Token *token, Expr *atom, Expr *index){
return expr; return expr;
} }
/*
function Expr * function Expr *
expr_cast(Parser *p, Token *token, AST_Node *type, Expr *exp){ expr_cast(Parser *p, Token *token, Typespec *type, Expr *exp){
Expr *expr = expr_new(p, EK_Cast, token); Expr *expr = expr_new(p, EK_Cast, token);
expr->cast.type = type; expr->cast.type = type;
expr->cast.expr = exp; expr->cast.expr = exp;
return expr; return expr;
} }
*/
function Expr *
expr_sizeof_type(Parser *p, Token *token, Typespec *type){
Expr *expr = expr_new(p, EK_Sizeof, token);
expr->size_of.kind = SIZEOF_Type;
expr->size_of.type = type;
return expr;
}
function Expr *
expr_sizeof_expr(Parser *p, Token *token, Expr *in_expr){
Expr *expr = expr_new(p, EK_Sizeof, token);
expr->size_of.kind = SIZEOF_Expr;
expr->size_of.expr = in_expr;
return expr;
}
function Expr * function Expr *
expr_list(Parser *p, Token *token){ expr_list(Parser *p, Token *token){

16
expr.h
View File

@@ -1,5 +1,11 @@
#pragma once #pragma once
typedef struct Expr Expr; typedef struct Expr Expr;
typedef struct Typespec Typespec;
typedef enum Expr_Sizeof_Kind{
SIZEOF_Expr,
SIZEOF_Type,
}Expr_Sizeof_Kind;
typedef enum Expr_Kind{ typedef enum Expr_Kind{
EK_None, EK_None,
@@ -11,6 +17,7 @@ typedef enum Expr_Kind{
EK_List, EK_List,
EK_Call, EK_Call,
EK_Index, EK_Index,
EK_Sizeof,
} Expr_Kind; } Expr_Kind;
struct Expr { struct Expr {
@@ -19,7 +26,7 @@ struct Expr {
Expr *next; Expr *next;
union { union {
struct { struct {
//Typespec *type; Typespec *type;
Expr* expr; Expr* expr;
} cast; } cast;
struct { struct {
@@ -46,5 +53,12 @@ struct Expr {
Expr* on_true; Expr* on_true;
Expr* on_false; Expr* on_false;
} ternary; } ternary;
struct{
Expr_Sizeof_Kind kind;
union{
Typespec *type;
Expr *expr;
};
} size_of;
}; };
}; };

View File

@@ -1,5 +1,41 @@
Thing :: struct{
data: (U32) U32; // Function pointer
data: (U32) U32 @ [32]; // Array of function pointers
data: (U32) U32* @ [32]; // Array of function pointers, they return a pointer
Thingy::enum{ actual_function :: (first: Thing*, last: Thing*, node: Thing*)/*no type == void*/{
if first == 0 {
first = last = node;
}
else{
last = last->next = node;
}
}
StructInside :: struct { // This is not part of struct
// just in scope
some_val: U16;
some_val2: U16;
}
insider: StructInside;
named_union_part_of_struct: union{
some_val: U16;
some_val2: U32;
}
_: union {
// Unamed union
val: U32;
}
}
Thingy::enum:U32{
@str=10 Value = 1, @str=10 Value = 1,
} }

24
main.c
View File

@@ -9,6 +9,7 @@
#include "lex.h" #include "lex.h"
#include "parser.h" #include "parser.h"
#include "expr.h" #include "expr.h"
#include "ast.h"
global FILE *global_output_file; global FILE *global_output_file;
#define lex_print(...) fprintf(global_output_file, __VA_ARGS__) #define lex_print(...) fprintf(global_output_file, __VA_ARGS__)
@@ -21,8 +22,10 @@ global FILE *global_output_file;
#include "lex.c" #include "lex.c"
#include "expr.c" #include "expr.c"
#include "ast.c"
#include "parse_expr.c" #include "parse_expr.c"
#include "parse_decl.c" #include "parse_decl.c"
#include "print.c"
function void function void
lex_test(){ lex_test(){
@@ -77,25 +80,40 @@ parser_test(){
assert(token_match(&p, TK_End)); assert(token_match(&p, TK_End));
String exprs[] = { String exprs[] = {
lit("(534>43?435:42,234,cast(S64)32/*todo cast*/,Thing[10][2],Thing(1,2))"),
lit("(4+2*53)"), lit("(4+2*53)"),
lit("((4+2)*53)"), lit("((4+2)*53)"),
lit("++5"), lit("++5"),
lit("5--"), // @Todo(Krzosa): lit("5--"), // @Todo(Krzosa):
lit("-5"), lit("-5"),
lit("(+5)"), lit("(+5)"),
lit("cast(S64)5"), lit("sizeof(32) + sizeof(:S32*)"),
lit("cast(S64**)5"),
lit("cast(S64)5+3"), lit("cast(S64)5+3"),
lit("534>43?435:42"), lit("534>43?435:42"),
lit("(534>43?435:42,234,cast(S64)42,Thing[10][2],Thing(1,2))"),
}; };
for(S64 i = 0; i < buff_cap(exprs); i++){ for(S64 i = 0; i < buff_cap(exprs); i++){
parser_lex_stream(&p, exprs[i], lit("File")); parser_lex_stream(&p, exprs[i], lit("File"));
Expr *expr = parse_expr(&p); Expr *expr = parse_expr(&p);
assert(expr); assert(expr);
expr_print(expr); expr_print(&p, expr);
lex_print("\n"); lex_print("\n");
} }
/*
String string
= lit(
"@test Thing2 :: struct { thing: union{a:U32;}; _: union{ thing: U32*; }; }"
"Thing :: enum: U32 { @str=\"as\" Thing = 32, Thing2 = 15<<2, }"
"Thing :: struct{ identi: U64*[32]; InnerStruct :: struct { t: U32; } var: InnerStruct; pp :: enum { Thing_1 } }"
"thing:(S64*,U64) U32*@[10]; }"
);
*/
String string = os_read_file(lit("test.cc"));
parser_lex_stream(&p, string, lit("Parse"));
Decl *decls = parse(&p);
assert(decls->list.first);
print_decl(&p, decls);
} }
function S32 function S32

246
output.cc
View File

@@ -0,0 +1,246 @@
(((534>43)?435:42),234,((S64)32),Thing[10][2],Thing((1,2)))
(4+(2*53))
((4+2)*53)
(++5)
(--5)
(-5)
(+5)
(sizeof(32)+sizeof(S32*))
((S64**)5)
(((S64)5)+3)
((534>43)?435:42)
struct OS_Memory{
data: void*;
commit: SizeU;
reserve: SizeU;
};
struct Arena{
@using memory: OS_Memory;
len: U64;
alignment: U64;
};
struct String{
str: U8*;
len: S64;
};
typedef Intern_String String;
@stringify @prefix = TK_ enum Token_Kind : S64{
@str = End of stream End,
@str = * Mul,
@str = / Div,
@str = + Add,
@str = - Sub,
@str = % Mod,
@str = & BitAnd,
@str = | BitOr,
@str = ^ BitXor,
@str = ~ Neg,
@str = ! Not,
@str = ( OpenParen,
@str = CloseParen,
@str = { OpenBrace,
@str = } CloseBrace,
@str = [ OpenBracket,
@str = ] CloseBracket,
@str = , Comma,
@str = # Pound,
@str = ? Question,
@str = ... ThreeDots,
@str = ; Semicolon,
@str = . Dot,
@str = < LesserThen,
@str = > GreaterThen,
@str = : Colon,
@str = = Assign,
@str = /= DivAssign,
@str = *= MulAssign,
@str = %= ModAssign,
@str = -= SubAssign,
@str = += AddAssign,
@str = &= AndAssign,
@str = |= OrAssign,
@str = ^= XorAssign,
@str = <<= LeftShiftAssign,
@str = >>= RightShiftAssign,
@str = :: DoubleColon,
@str = @ At,
@str = -- Decrement,
@str = ++ Increment,
@str = -- PostDecrement,
@str = ++ PostIncrement,
@str = <= LesserThenOrEqual,
@str = >= GreaterThenOrEqual,
@str = == Equals,
@str = && And,
@str = || Or,
@str = != NotEquals,
@str = << LeftShift,
@str = >> RightShift,
@str = -> Arrow,
@str = sizeof ExprSizeof,
DocComment,
Comment,
Identifier,
StringLit,
U8Lit,
Character,
Error,
Float,
Int,
Keyword,
};
struct Token{
kind: Token_Kind;
@using string: String;
val: union {
integer: S64;
error: String;
intern: Intern_String;
};
file: String;
line: S64;
line_begin: U8*;
};
struct Tokens{
@array tokens: Token*;
iter: S64;
};
struct Lex_Stream{
stream: U8*;
line_begin: U8*;
filename: String;
line: S64;
};
@prefix = EK_ enum Expr_Kind : S64{
None,
Atom,
Unary,
Binary,
Ternary,
Cast,
List,
Call,
Index,
};
struct Expr{
kind: Expr_Kind;
token: Token*;
next: Expr*;
_: union {
cast_val: struct {
type: AST_Node*;
expr: Expr*;
};
list: struct {
first: Expr*;
last: Expr*;
};
call: struct {
atom: Expr*;
list: Expr*;
};
index: struct {
atom: Expr*;
index: Expr*;
};
unary: struct {
expr: Expr*;
};
binary: struct {
left: Expr*;
right: Expr*;
};
ternary: struct {
cond: Expr*;
on_true: Expr*;
on_false: Expr*;
};
};
};
@prefix = AK_ enum AST_Kind : S64{
None,
BaseType,
Typedef,
Enum,
Struct,
Union,
Note,
List,
Pointer,
Array,
Function,
Variable,
EnumChild,
};
struct AST_Node{
kind: AST_Kind;
pos: Token*;
name: Intern_String;
next: AST_Node*;
next_scope: AST_Node*;
first_note: AST_Node*;
last_note: AST_Node*;
first_child: AST_Node*;
last_child: AST_Node*;
_: union {
base_type_size: SizeU;
pointer: AST_Node*;
typedef_type: AST_Node*;
variable_type: AST_Node*;
func_return_type: AST_Node*;
};
};
struct Parser_Error{
next: Parser_Error*;
message: String;
token: Token*;
};
struct Scope{
next: Scope*;
first: AST_Node*;
last: AST_Node*;
};
struct Parser{
main_arena: Arena;
intern_table_arena: Arena;
symbol_table_arena: Arena;
scope_free_list: Scope*;
scope_stack: Scope*;
global_scope: Scope*;
symbols_inserted: S64;
symbols_count: S64;
symbols: AST_Node*;
interns: Intern_String*;
interns_in_bytes: S64;
interns_inserted: S64;
interns_count: S64;
first_keyword: U8*;
last_keyword: U8*;
@sllqueue default: Parser_Error;
@sllqueue error: Parser_Error;
@using token_array: Tokens;
};

View File

@@ -1,20 +1,88 @@
#if 0 function Decl *parse_decl(Parser *p);
function Decl *parse_struct(Parser *p, Token *name, Decl_Kind kind);
function Typespec *parse_type(Parser *p);
function Token * function Typespec *
parse__get_name(Parser *p){ parse_type_struct(Parser *p, Token *token){
Token *name = token_next(p); Decl_Kind kind = intern_compare(token->intern_val, keyword_struct) ? DECL_Struct : DECL_Union;
token_next(p); Decl *decl = parse_struct(p, token, kind);
token_next(p); decl->name = (Intern_String){};
return name; return typespec_struct(p, token, decl);
}
function Typespec *
parse_type_function(Parser *p, Token *token){
Typespec *result = typespec_function(p, token, 0);
if(!token_is(p, TK_CloseParen))
for(;;) {
if(token_is(p, TK_Identifier)){
Typespec *arg = parse_type(p);
typespec_function_push(result, arg);
}
else if(!token_match(p, TK_Comma)){
break;
}
}
token_expect(p, TK_CloseParen);
if(token_is(p, TK_Identifier)){
result->function_spec.ret = parse_type(p);
}
else{
result->function_spec.ret = typespec_name(p, token_get(p), intern_void);
}
return result;
}
function Typespec *
parse_type(Parser *p){
Token *token = 0;
Typespec *result = 0;
if((token = token_match(p, TK_Identifier))){
result = typespec_name(p, token, token->intern_val);
}
else if((token = token_match_keyword(p, keyword_struct)) || (token = token_match_keyword(p, keyword_union))){
result = parse_type_struct(p, token);
}
else if((token = token_match(p, TK_OpenParen))){
result = parse_type_function(p, token);
}
else{
parser_push_error(p, token, "Failed to parse type, unexpected token");
return 0;
}
for(;;){
if((token = token_match(p, TK_Mul))){
result = typespec_pointer(p, token, result);
}
else if((token = token_match(p, TK_OpenBracket))){
Expr *expr = parse_expr(p);
result = typespec_array(p, token, result, expr);
token_expect(p, TK_CloseBracket);
}
else if(token_match(p, TK_At)){
break;
}
else break;
}
return result;
}
function Expr *
parse_expr_assignment(Parser *p){
Expr *result = 0;
if(token_match(p, TK_Assign)){
result = parse_expr(p);
}
return result;
} }
function void function void
parse_note_list(Parser *ctx, AST_Node *parent) { parse_note_list(Parser *ctx, Note *parent) {
if(token_match(ctx, TK_OpenParen)) { if(token_match(ctx, TK_OpenParen)) {
do { do {
Token *name = token_expect(ctx, TK_Identifier); Token *name = token_expect(ctx, TK_Identifier);
AST_Node *current = ast_note(ctx, name, name->intern_val, 0); Note *current = note_push_new(ctx, parent, name, name->intern_val, 0);
ast_node_push_note(parent, current);
parse_note_list(ctx, current); parse_note_list(ctx, current);
if(token_match(ctx, TK_Assign)) { if(token_match(ctx, TK_Assign)) {
current->expr = parse_expr(ctx); current->expr = parse_expr(ctx);
@@ -25,11 +93,10 @@ parse_note_list(Parser *ctx, AST_Node *parent) {
} }
function void function void
parse__notes(Parser *ctx, AST_Node *result) { parse__notes(Parser *ctx, Note *result) {
while(token_match(ctx, TK_At)) { while(token_match(ctx, TK_At)) {
Token *name = token_expect(ctx, TK_Identifier); Token *name = token_expect(ctx, TK_Identifier);
AST_Node *current = ast_note(ctx, name, name->intern_val, 0); Note *current = note_push_new(ctx, result, name, name->intern_val, 0);
ast_node_push_note(result, current);
parse_note_list(ctx, current); parse_note_list(ctx, current);
if(token_match(ctx, TK_Assign)) { if(token_match(ctx, TK_Assign)) {
current->expr = parse_expr(ctx); current->expr = parse_expr(ctx);
@@ -37,185 +104,316 @@ parse__notes(Parser *ctx, AST_Node *result) {
} }
} }
function AST_Node function Note
parse_notes(Parser *p){ parse_notes(Parser *p){
AST_Node result = {}; Note result = {};
parse__notes(p, &result); parse__notes(p, &result);
return result; return result;
} }
function AST_Node * function Decl *
parse_enum(Parser *p, Token *name){ parse_enum(Parser *p, Token *name){
AST_Node *result = 0; Typespec *type = 0;
if(token_expect(p, TK_OpenBrace)){ if(token_match(p, TK_Colon)) type = parse_type(p);
result = ast_enum(p, name, name->intern_val); else type = typespec_name(p, token_get(p), intern_s64);
do{
AST_Node notes = parse_notes(p);
Token *token = token_match(p, TK_Identifier);
if(token){
Expr *expr = 0;
if(token_match(p, TK_Assign)){
expr = parse_expr(p);
}
AST_Node *child = ast_enum_child(p, token, token->intern_val, expr); Decl *result = decl_enum(p, name, name->intern_val, type);
ast_node_pass_note_list(child,&notes); token_expect(p, TK_OpenBrace);
ast_node_push_child(result, child); do{
} Note notes = parse_notes(p);
else{ Token *token = token_match(p, TK_Identifier);
break; if(token){
} Expr *expr = parse_expr_assignment(p);
} while(token_match(p, TK_Comma)); decl_enum_push(p, result, token, token->intern_val, expr, &notes);
token_expect(p, TK_CloseBrace); } else break;
} } while(token_match(p, TK_Comma));
token_expect(p, TK_CloseBrace);
return result; return result;
} }
function AST_Node * function Decl *
parse_struct(Parser *p, Token *name, Decl_Kind kind){
Decl *result = decl_struct(p, kind, name, name->intern_val);
token_expect(p, TK_OpenBrace);
while(!token_is(p, TK_CloseBrace)){
Decl *decl = 0;
if((decl = parse_decl(p))){
decl_struct_push(result, decl);
}
else {
parser_push_error(p, token_get(p), "Unexpected token while parsing struct");
break;
}
}
token_expect(p, TK_CloseBrace);
return result;
}
function Decl *
parse_variable(Parser *p, Token *name){ parse_variable(Parser *p, Token *name){
AST_Node *result = 0; Typespec *type = parse_type(p);
Token *type_token = token_expect(p, TK_Identifier); Expr *expr = parse_expr_assignment(p);
if(type_token){
AST_Node *type = symbol_require_type(p, type_token);
Token *star;
while((star = token_match(p, TK_Mul))){
type = ast_type_pointer(p, star, type);
}
while((star = token_match(p, TK_OpenBracket))){
Expr *expr = parse_expr(p);
type = ast_type_array(p, star, type, expr);
token_expect(p, TK_CloseBracket);
}
Expr *expr = 0;
if(token_match(p, TK_Assign)){
expr = parse_expr(p);
}
result = ast_variable(p, name, name->intern_val, type, expr);
}
return result;
}
function AST_Node *
parse_struct(Parser *p, Token *name, AST_Kind kind, B32 is_global){
AST_Node *result = 0;
if(token_expect(p, TK_OpenBrace)){
result = ast_struct(p, name, name?name->intern_val:(Intern_String){}, kind);
if(is_global) symbol_register(p, result);
for(;;){
AST_Node notes = parse_notes(p);
AST_Node *mem = 0;
Token *mem_name = token_match(p, TK_Identifier);
if(mem_name){
if(token_expect(p, TK_Colon)){
if(token_match_keyword(p, keyword_struct)){
mem = parse_struct(p, mem_name, AK_Struct, false);
}
else if(token_match_keyword(p, keyword_union)){
mem = parse_struct(p, mem_name, AK_Union, false);
}
//else if(token_match_keyword(p, keyword_enum)){
//mem = parse_enum(p, mem_name);
//}
else if(token_is(p, TK_Identifier)){
mem = parse_variable(p, mem_name);
token_expect(p, TK_Semicolon);
}
else parser_push_error(p, mem_name, "Unrecognized token while parsing struct");
if(mem){
ast_node_pass_note_list(mem, &notes);
ast_node_push_child(result, mem);
}
}
else{
break;
}
}
else if(token_match_keyword(p, keyword_union) &&
token_match(p, TK_Colon)){
mem = parse_struct(p, 0, AK_Union, false);
ast_node_pass_note_list(mem, &notes);
ast_node_push_child(result, mem);
}
else if(token_match_keyword(p, keyword_struct) &&
token_match(p, TK_Colon)){
mem = parse_struct(p, 0, AK_Struct, false);
ast_node_pass_note_list(mem, &notes);
ast_node_push_child(result, mem);
}
else if(token_expect(p, TK_CloseBrace)){
break;
}
else{
break;
}
}
}
return result;
}
function AST_Node *
parse_typedef(Parser *p, Token *name){
Token *type_token = token_expect(p, TK_Identifier);
AST_Node *type = symbol_require_type(p, type_token);
AST_Node *result = ast_typedef(p, name, name->intern_val, type);
token_expect(p, TK_Semicolon); token_expect(p, TK_Semicolon);
return decl_variable(p, name, name->intern_val, type, expr);
}
function Decl *
parse_typedef(Parser *p, Token *name){
Typespec *type = parse_type(p);
return decl_typedef(p, name, name->intern_val, type);
}
function Token *
parse_get_token_name(Parser *p, S32 count){
Token *result = token_next(p);
for(S32 i = 0; i < count; i++)
token_next(p);
return result; return result;
} }
function AST_Node_List * function Decl *
parse(Parser *p){ parse_decl(Parser *p){
AST_Node_List *result = ast_node_new(p, AK_List, token_get(p), intern_empty); Decl *result = 0;
Note notes = parse_notes(p);
for(;;){ if(token_is(p, TK_Identifier)){
AST_Node *node = 0; if(token_peek_is(p, 1, TK_DoubleColon)){
AST_Node notes = parse_notes(p);
if(token_is(p, TK_End)){
break;
}
else if(token_is(p, TK_Error)){
break;
}
else if(token_is(p, TK_Identifier) && // Peeking to be more error averse
token_peek_is(p, 1, TK_Colon)){
if(token_peek_is_keyword(p, 2, keyword_struct)){ if(token_peek_is_keyword(p, 2, keyword_struct)){
node = parse_struct(p, parse__get_name(p), AK_Struct, true); result = parse_struct(p, parse_get_token_name(p,2), DECL_Struct);
symbol_register(p, node);
} }
else if(token_peek_is_keyword(p, 2, keyword_union)){ else if(token_peek_is_keyword(p, 2, keyword_union)){
node = parse_struct(p, parse__get_name(p), AK_Union, true); result = parse_struct(p, parse_get_token_name(p,2), DECL_Union);
symbol_register(p, node);
} }
else if(token_peek_is_keyword(p, 2, keyword_enum)){ else if(token_peek_is_keyword(p, 2, keyword_enum)){
node = parse_enum(p, parse__get_name(p)); result = parse_enum(p, parse_get_token_name(p,2));
symbol_register(p, node);
} }
else if(token_peek_is_keyword(p, 2, keyword_typedef)){ else if(token_peek_is_keyword(p, 2, keyword_typedef)){
node = parse_typedef(p, parse__get_name(p)); result = parse_typedef(p, parse_get_token_name(p,2));
symbol_register(p, node); }
}
else if(token_peek_is(p, 1, TK_Colon)){
if(token_peek_is(p, 2, TK_Identifier) ||
token_peek_is_keyword(p, 2, keyword_union) ||
token_peek_is_keyword(p, 2, keyword_struct) ||
token_peek_is(p, 2, TK_OpenParen)){
result = parse_variable(p, parse_get_token_name(p,1));
}
}
}
if(result){
result->first_note = notes.first;
result->last_note = notes.last;
}
else if(notes.first != 0){
parser_push_error(p, token_get(p), "Detected notes that are not attached to anything");
}
return result;
}
function Decl *
parse(Parser *p){
Decl *result = decl_new(p, DECL_List, token_get(p), (Intern_String){});
for(;;){
Decl *decl = 0;
if(token_is(p, TK_End)) {
break;
}
else if((decl = parse_decl(p))){
// Noop
}
else token_next(p);
if(decl){
decl_list_push(result, decl);
}
}
return result;
}
/*
function Token *
parse__get_name(Parser *p){
Token *name = token_next(p);
token_next(p);
token_next(p);
return name;
}
function Note *
parse_enum(Parser *p, Token *name){
Note *result = 0;
if(token_expect(p, TK_OpenBrace)){
result = ast_enum(p, name, name->intern_val);
do{
Note notes = parse_notes(p);
Token *token = token_match(p, TK_Identifier);
if(token){
Expr *expr = 0;
if(token_match(p, TK_Assign)){
expr = parse_expr(p);
}
Note *child = ast_enum_child(p, token, token->intern_val, expr);
ast_node_pass_note_list(child,&notes);
ast_node_push_child(result, child);
}
else{
break;
}
} while(token_match(p, TK_Comma));
token_expect(p, TK_CloseBrace);
}
return result;
}
function Note *
parse_variable(Parser *p, Token *name){
Note *result = 0;
Token *type_token = token_expect(p, TK_Identifier);
if(type_token){
Note *type = symbol_require_type(p, type_token);
Token *star;
while((star = token_match(p, TK_Mul))){
type = ast_type_pointer(p, star, type);
}
while((star = token_match(p, TK_OpenBracket))){
Expr *expr = parse_expr(p);
type = ast_type_array(p, star, type, expr);
token_expect(p, TK_CloseBracket);
}
Expr *expr = 0;
if(token_match(p, TK_Assign)){
expr = parse_expr(p);
}
result = ast_variable(p, name, name->intern_val, type, expr);
}
return result;
}
function Note *
parse_struct(Parser *p, Token *name, AST_Kind kind, B32 is_global){
Note *result = 0;
if(token_expect(p, TK_OpenBrace)){
result = ast_struct(p, name, name?name->intern_val:(Intern_String){}, kind);
if(is_global) symbol_register(p, result);
for(;;){
Note notes = parse_notes(p);
Note *mem = 0;
Token *mem_name = token_match(p, TK_Identifier);
if(mem_name){
if(token_expect(p, TK_Colon)){
if(token_match_keyword(p, keyword_struct)){
mem = parse_struct(p, mem_name, AK_Struct, false);
}
else if(token_match_keyword(p, keyword_union)){
mem = parse_struct(p, mem_name, AK_Union, false);
}
//else if(token_match_keyword(p, keyword_enum)){
//mem = parse_enum(p, mem_name);
//}
else if(token_is(p, TK_Identifier)){
mem = parse_variable(p, mem_name);
token_expect(p, TK_Semicolon);
}
else parser_push_error(p, mem_name, "Unrecognized token while parsing struct");
if(mem){
ast_node_pass_note_list(mem, &notes);
ast_node_push_child(result, mem);
}
} }
else{ else{
token_next(p); break;
} }
} }
else if(token_match_keyword(p, keyword_union) &&
token_match(p, TK_Colon)){
mem = parse_struct(p, 0, AK_Union, false);
ast_node_pass_note_list(mem, &notes);
ast_node_push_child(result, mem);
}
else if(token_match_keyword(p, keyword_struct) &&
token_match(p, TK_Colon)){
mem = parse_struct(p, 0, AK_Struct, false);
ast_node_pass_note_list(mem, &notes);
ast_node_push_child(result, mem);
}
else if(token_expect(p, TK_CloseBrace)){
break;
}
else{
break;
}
}
}
return result;
}
function Note *
parse_typedef(Parser *p, Token *name){
Token *type_token = token_expect(p, TK_Identifier);
Note *type = symbol_require_type(p, type_token);
Note *result = ast_typedef(p, name, name->intern_val, type);
token_expect(p, TK_Semicolon);
return result;
}
function Note_List *
parse(Parser *p){
Note_List *result = ast_node_new(p, AK_List, token_get(p), intern_empty);
for(;;){
Note *node = 0;
Note notes = parse_notes(p);
if(token_is(p, TK_End)){
break;
}
else if(token_is(p, TK_Error)){
break;
}
else if(token_is(p, TK_Identifier) && // Peeking to be more error averse
token_peek_is(p, 1, TK_Colon)){
if(token_peek_is_keyword(p, 2, keyword_struct)){
node = parse_struct(p, parse__get_name(p), AK_Struct, true);
symbol_register(p, node);
}
else if(token_peek_is_keyword(p, 2, keyword_union)){
node = parse_struct(p, parse__get_name(p), AK_Union, true);
symbol_register(p, node);
}
else if(token_peek_is_keyword(p, 2, keyword_enum)){
node = parse_enum(p, parse__get_name(p));
symbol_register(p, node);
}
else if(token_peek_is_keyword(p, 2, keyword_typedef)){
node = parse_typedef(p, parse__get_name(p));
symbol_register(p, node);
}
else{ else{
token_next(p); token_next(p);
} }
}
else{
if(node){ token_next(p);
ast_node_pass_note_list(node, &notes);
ast_node_push_child(result, node);
}
else if(notes.first_note != 0){
parser_push_error(p, token_get(p), "Warning: notes got lost");
}
} }
return result;
if(node){
ast_node_pass_note_list(node, &notes);
ast_node_push_child(result, node);
}
else if(notes.first_note != 0){
parser_push_error(p, token_get(p), "Warning: notes got lost");
}
} }
#endif
return result;
}
*/

View File

@@ -1,5 +1,6 @@
function Expr* parse_expr(Parser* p); function Expr* parse_expr(Parser* p);
function Expr* parse_list_expr(Parser* p); function Expr* parse_list_expr(Parser* p);
function Typespec *parse_type(Parser *p);
function Expr* function Expr*
parse_atom_expr(Parser* p){ parse_atom_expr(Parser* p){
@@ -10,6 +11,21 @@ parse_atom_expr(Parser* p){
token_is(p, TK_Int)){ token_is(p, TK_Int)){
result = expr_atom(p, token_next(p)); result = expr_atom(p, token_next(p));
} }
else if (token_is_keyword(p, keyword_sizeof)) {
Token *token = token_next(p);
token_expect(p, TK_OpenParen);
Typespec *type = 0;
Expr *expr = 0;
if(token_match(p, TK_Colon)) {
result = expr_sizeof_type(p, token, parse_type(p));
}
else {
result = expr_sizeof_expr(p, token, parse_expr(p));
}
token_expect(p, TK_CloseParen);
}
else if (token_match(p, TK_OpenParen)){ else if (token_match(p, TK_OpenParen)){
result = parse_list_expr(p); result = parse_list_expr(p);
token_expect(p, TK_CloseParen); token_expect(p, TK_CloseParen);
@@ -24,17 +40,13 @@ function Expr*
parse_postfix_expr(Parser* p){ parse_postfix_expr(Parser* p){
Expr* result = parse_atom_expr(p); Expr* result = parse_atom_expr(p);
while (token_is(p, TK_Dot) while (token_is(p, TK_Dot)
|| token_is(p, TK_Arrow)
|| token_is(p, TK_DoubleColon)
|| token_is(p, TK_OpenParen) || token_is(p, TK_OpenParen)
|| token_is(p, TK_OpenBracket) || token_is(p, TK_OpenBracket)
|| token_is(p, TK_Decrement) || token_is(p, TK_Decrement)
|| token_is(p, TK_Increment)){ || token_is(p, TK_Increment)){
Token *op = token_get(p); Token *op = token_get(p);
if (token_match(p, TK_Arrow) if (token_match(p, TK_Dot)){
|| token_match(p, TK_DoubleColon)
|| token_match(p, TK_Dot)){
Expr* r = parse_atom_expr(p); Expr* r = parse_atom_expr(p);
result = expr_binary(p, op, result, r); result = expr_binary(p, op, result, r);
} }
@@ -85,35 +97,16 @@ Expr* parse_unary_expr(Parser* p) {
result = parse_unary_expr(p); result = parse_unary_expr(p);
result = expr_unary(p, op, result); result = expr_unary(p, op, result);
} }
else if (token_is_keyword(p, keyword_sizeof)) {
else if (token_is_keyword(p, keyword_cast)) {
Token *token = token_next(p); Token *token = token_next(p);
token_expect(p, TK_OpenParen);
Typespec *type = parse_type(p);
token_expect(p, TK_CloseParen);
result = parse_unary_expr(p); result = parse_unary_expr(p);
result = expr_unary(p, token, result); result = expr_cast(p, token, type, result);
} }
/*
else if (token_is(p, TK_OpenParen)) { // cast requires lookahead
Token *token = token_peek(p, 1);
if (token->kind == TK_Identifier) {
AST_Node *type = symbol_lookup_type(p, token->intern_val);
if(type){
token_next(p);
token_next(p);
// @Todo(Krzosa): Parse pointer types
token_expect(p, TK_CloseParen);
result = parse_unary_expr(p);
result = expr_cast(p, token, type, result);
}
else {
result = parse_postfix_expr(p);
}
}
else {
result = parse_postfix_expr(p);
}
}
*/
else { else {
result = parse_postfix_expr(p); result = parse_postfix_expr(p);
} }

View File

@@ -14,6 +14,7 @@ global Intern_String intern_void;
global Intern_String intern_sizeu; global Intern_String intern_sizeu;
global Intern_String keyword_sizeof; global Intern_String keyword_sizeof;
global Intern_String keyword_cast;
global Intern_String keyword_enum; global Intern_String keyword_enum;
global Intern_String keyword_typedef; global Intern_String keyword_typedef;
global Intern_String keyword_struct; global Intern_String keyword_struct;
@@ -27,6 +28,7 @@ parser_init(Parser *p){
p->interns = arena_push_array(&p->intern_table_arena, Intern_String, p->interns_count); p->interns = arena_push_array(&p->intern_table_arena, Intern_String, p->interns_count);
keyword_sizeof = intern_string(p, lit("sizeof")); keyword_sizeof = intern_string(p, lit("sizeof"));
keyword_cast = intern_string(p, lit("cast"));
keyword_struct = intern_string(p, lit("struct")); keyword_struct = intern_string(p, lit("struct"));
keyword_enum = intern_string(p, lit("enum")); keyword_enum = intern_string(p, lit("enum"));
keyword_typedef = intern_string(p, lit("typedef")); keyword_typedef = intern_string(p, lit("typedef"));
@@ -36,7 +38,6 @@ parser_init(Parser *p){
p->first_keyword = keyword_sizeof.s.str; p->first_keyword = keyword_sizeof.s.str;
p->last_keyword = keyword_global.s.str; p->last_keyword = keyword_global.s.str;
intern_s64 = intern_string(p, lit("S64")); intern_s64 = intern_string(p, lit("S64"));
intern_s32 = intern_string(p, lit("S32")); intern_s32 = intern_string(p, lit("S32"));
intern_s16 = intern_string(p, lit("S16")); intern_s16 = intern_string(p, lit("S16"));
@@ -60,7 +61,6 @@ intern_is_keyword(Parser *p, Intern_String intern){
function void function void
parser_push_error(Parser *p, Token *token, char *str, ...){ parser_push_error(Parser *p, Token *token, char *str, ...){
String string; String string;
{ {
va_list args1, args2; va_list args1, args2;
@@ -80,6 +80,9 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
error->next = 0; error->next = 0;
error->token = token; error->token = token;
SLLQueuePush(p->first_error, p->last_error, error); SLLQueuePush(p->first_error, p->last_error, error);
__debugbreak();
exit(-1);
} }
function void function void

219
print.c Normal file
View File

@@ -0,0 +1,219 @@
function void print_decl(Parser *p, Decl *node);
function B32 print_typespec(Parser *p, Typespec *spec);
function void
tokens_print(Tokens tokens){
lex_print("\n== Token count = %d\n", (S32)tokens.len);
for(Token *t = tokens.tokens; t != tokens.tokens + tokens.len; t++){
lex_print("%s \"%.*s\"\n", token_kind_string[t->kind].str, (S32)t->len, t->str);
}
}
function void
token_print(Token *token){
lex_print("%.*s", (S32)token->len, token->str);
}
function void
expr_print(Parser *p, Expr *expr){
switch(expr->kind) {
case EK_Atom: {
token_print(expr->token);
} break;
case EK_Sizeof:{
lex_print("sizeof(");
if(expr->size_of.kind == SIZEOF_Expr){
expr_print(p, expr->size_of.expr);
}
else{
assert(expr->size_of.kind == SIZEOF_Type);
print_typespec(p, expr->size_of.type);
}
lex_print(")");
}break;
case EK_Binary:{
lex_print("(");
expr_print(p, expr->binary.left);
token_print(expr->token);
expr_print(p, expr->binary.right);
lex_print(")");
} break;
case EK_Unary:{
lex_print("(");
token_print(expr->token);
expr_print(p, expr->unary.expr);
lex_print(")");
} break;
case EK_Ternary:{
lex_print("(");
expr_print(p, expr->ternary.cond);
lex_print("?");
expr_print(p, expr->ternary.on_true);
lex_print(":");
expr_print(p, expr->ternary.on_false);
lex_print(")");
} break;
case EK_List:{
lex_print("(");
for(Expr *n = expr->list.first; n; n=n->next){
expr_print(p, n);
if(n!=expr->list.last) lex_print(",");
}
lex_print(")");
}break;
case EK_Cast:{
lex_print("(");
lex_print("(");
print_typespec(p, expr->cast.type);
lex_print(")");
expr_print(p, expr->cast.expr);
lex_print(")");
} break;
case EK_Index:{
expr_print(p, expr->index.atom);
lex_print("[");
expr_print(p, expr->index.index);
lex_print("]");
}break;
case EK_Call:{
expr_print(p, expr->call.atom);
lex_print("(");
expr_print(p, expr->call.list);
lex_print(")");
}break;
default: {invalid_codepath;} break;
}
}
global S64 indent;
function B32
print_typespec(Parser *p, Typespec *spec){
switch(spec->kind) {
case TS_Name: {
lex_print("%s", spec->name.s.str);
} break;
case TS_Struct:{
print_decl(p, spec->struct_spec);
return false;
} break;
case TS_Pointer: {
print_typespec(p, spec->base);
lex_print("*");
} break;
case TS_Array: {
print_typespec(p, spec->array_spec.base);
lex_print("[");
expr_print(p, spec->array_spec.size);
lex_print("]");
} break;
case TS_Function: {
lex_print("(");
for(Typespec *n = spec->function_spec.first; n; n=n->next){
print_typespec(p,n);
if(n!=spec->function_spec.last)
lex_print(", ");
}
lex_print(")");
print_typespec(p,spec->function_spec.ret);
} break;
default: {invalid_codepath;} break;
}
return true;
}
function void
print_assign_expr(Parser *p, Expr *expr){
if(expr){
lex_print(" = ");
expr_print(p, expr);
}
}
function void
print_note_list(Parser *p, Note *note){
if(note){
lex_print("(");
for(Note *n = note; n; n=n->next){
lex_print("%s", n->name.s.str);
print_note_list(p,n->first);
print_assign_expr(p, n->expr);
}
lex_print(")");
}
}
function void
print_notes(Parser *p, Note *note){
for(Note *n = note; n; n=n->next){
lex_print("@%s", n->name.s.str);
print_note_list(p,n->first);
print_assign_expr(p,n->expr);
lex_print(" ");
}
}
function void
print_decl(Parser *p, Decl *node){
print_notes(p, node->first_note);
switch(node->kind) {
case DECL_List: {
for(Decl *n = node->list.first; n; n=n->next){
print_decl(p,n);
lex_new_line();
}
} break;
case DECL_Variable:{
lex_print("%s: ", node->name.s.str);
B32 r = print_typespec(p, node->variable_decl.type);
print_assign_expr(p,node->variable_decl.expr);
if(r) lex_print(";");
} break;
case DECL_Typedef:{
lex_print("typedef %s ", node->name.s.str);
print_typespec(p, node->typedef_decl.type);
lex_print(";");
} break;
case DECL_Struct:
case DECL_Union :{
const char *struct_name = node->kind==DECL_Struct ? "struct" : "union";
lex_print("%s %s{\n", struct_name, node->name.s.str?(char*)node->name.s.str:"");
for(Decl *n = node->struct_decl.first; n; n=n->next){
print_decl(p, n);
lex_print("\n");
}
lex_print("};\n");
} break;
case DECL_Enum:{
lex_print("enum %s : ", node->name.s.str);
print_typespec(p, node->enum_decl.typespec);
lex_print("{\n");
for(Decl_Enum_Child *n = node->enum_decl.first; n; n=n->next){
print_notes(p, n->first_note);
lex_print("%s", n->name.s.str);
print_assign_expr(p, n->expr);
lex_print(",\n");
}
lex_print("};\n");
} break;
default: {invalid_codepath;} break;
}
}

66
test.cc
View File

@@ -1,26 +1,26 @@
#if 0 #if 0
OS_Memory:struct{ OS_Memory::struct{
data: void*; data: void*;
commit: SizeU; commit: SizeU;
reserve: SizeU; reserve: SizeU;
} }
Arena:struct{ Arena::struct{
@using memory: OS_Memory; @using memory: OS_Memory;
len: U64; len: U64;
alignment: U64; alignment: U64;
} }
String:struct{ String::struct{
str: U8*; str: U8*;
len: S64; len: S64;
} }
Intern_String:typedef String; Intern_String::typedef String;
@stringify @stringify
@prefix="TK_" @prefix="TK_"
Token_Kind:enum{ Token_Kind::enum{
@str="End of stream" End, @str="End of stream" End,
@str="*" Mul, @str="*" Mul,
@str="/" Div, @str="/" Div,
@@ -86,25 +86,25 @@ Token_Kind:enum{
Keyword, Keyword,
} }
Token:struct{ Token::struct{
kind:Token_Kind; kind:Token_Kind;
@using string:String; @using string:String;
union:{ val: union{
int_val:S64; integer:S64;
error_val:String; error:String;
intern_val:Intern_String; intern:Intern_String;
} };
file:String; file:String;
line:S64; line:S64;
line_begin:U8*; line_begin:U8*;
} }
Tokens:struct{ Tokens::struct{
@array tokens: Token*; @array tokens: Token*;
iter : S64; iter : S64;
} }
Lex_Stream:struct{ Lex_Stream::struct{
stream: U8*; stream: U8*;
line_begin: U8*; line_begin: U8*;
filename: String; filename: String;
@@ -112,7 +112,7 @@ Lex_Stream:struct{
} }
@prefix="EK_" @prefix="EK_"
Expr_Kind: enum{ Expr_Kind::enum{
None, None,
Atom, Atom,
Unary, Unary,
@@ -124,46 +124,44 @@ Expr_Kind: enum{
Index, Index,
} }
/* Expr:: struct{
Expr: struct{
kind: Expr_Kind; kind: Expr_Kind;
token: Token*; token: Token*;
next : Expr*; next : Expr*;
union:{ _: union{
cast: struct{ cast_val: struct{
type: AST_Node*; type: AST_Node*;
expr: Expr*; expr: Expr*;
} };
list: struct{ list: struct{
first: Expr *; first: Expr *;
last: Expr *; last: Expr *;
} };
call: struct{ call: struct{
atom: Expr *; atom: Expr *;
list: Expr *; list: Expr *;
} };
index: struct{ index: struct{
atom: Expr *; atom: Expr *;
index: Expr *; index: Expr *;
} };
unary: struct{ unary: struct{
expr: Expr* ; expr: Expr* ;
} };
binary: struct{ binary: struct{
left: Expr* ; left: Expr* ;
right: Expr* ; right: Expr* ;
} };
ternary: struct{ ternary: struct{
cond: Expr* ; cond: Expr* ;
on_true: Expr*; on_true: Expr*;
on_false: Expr*; on_false: Expr*;
} };
} };
} }
*/
@prefix="AK_" @prefix="AK_"
AST_Kind:enum{ AST_Kind::enum{
None, None,
BaseType, BaseType,
Typedef, Typedef,
@@ -179,7 +177,7 @@ AST_Kind:enum{
EnumChild, EnumChild,
} }
AST_Node:struct{ AST_Node::struct{
kind: AST_Kind; kind: AST_Kind;
pos : Token*; pos : Token*;
name: Intern_String; name: Intern_String;
@@ -192,28 +190,28 @@ AST_Node:struct{
first_child: AST_Node*; first_child: AST_Node*;
last_child: AST_Node*; last_child: AST_Node*;
union:{ _:union{
base_type_size: SizeU; base_type_size: SizeU;
pointer: AST_Node*; pointer: AST_Node*;
typedef_type: AST_Node*; typedef_type: AST_Node*;
variable_type: AST_Node*; variable_type: AST_Node*;
func_return_type: AST_Node*; func_return_type: AST_Node*;
} };
} }
Parser_Error: struct{ Parser_Error :: struct{
next: Parser_Error*; next: Parser_Error*;
message: String; message: String;
token : Token *; token : Token *;
} }
Scope: struct{ Scope :: struct{
next : Scope*; next : Scope*;
first: AST_Node*; first: AST_Node*;
last : AST_Node*; last : AST_Node*;
} }
Parser: struct{ Parser :: struct{
main_arena: Arena; main_arena: Arena;
intern_table_arena: Arena; intern_table_arena: Arena;
symbol_table_arena: Arena; symbol_table_arena: Arena;