Swinging in a different direction, different syntax
This commit is contained in:
68
ast.c
68
ast.c
@@ -15,12 +15,47 @@ ast_node_new(Parser *p, AST_Kind kind, Token *token, Intern_String name){
|
||||
return node;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
ast_note(Parser *p, Token *token, Intern_String name, Expr *expr){
|
||||
AST_Node *node = ast_node_new(p, AK_Note, token, name);
|
||||
node->expr = expr;
|
||||
return node;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
ast_enum(Parser *p, Token *token, Intern_String name){
|
||||
AST_Node *node = ast_node_new(p, AK_Enum, token, name);
|
||||
return node;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
ast_struct(Parser *p, Token *token, Intern_String name, AST_Kind kind){
|
||||
AST_Node *node = ast_node_new(p, kind, token, name);
|
||||
return node;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
ast_variable(Parser *p, Token *token, Intern_String name, AST_Node *type, Expr *expr){
|
||||
AST_Node *node = ast_node_new(p, AK_Variable, token, name);
|
||||
node->variable_type = type;
|
||||
node->expr = expr;
|
||||
return node;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
ast_typedef(Parser *p, Token *token, Intern_String name, AST_Node *type){
|
||||
AST_Node *node = ast_node_new(p, AK_Typedef, token, name);
|
||||
node->typedef_type = type;
|
||||
return node;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
ast_function(Parser *p, Token *token, Intern_String name, AST_Node *return_type){
|
||||
AST_Node *node = ast_node_new(p, AK_Function, token, name);
|
||||
node->func_return_type = return_type;
|
||||
return node;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
ast_enum_child(Parser *p, Token *token, Intern_String name, Expr *expr){
|
||||
AST_Node *node = ast_node_new(p, AK_EnumChild, token, name);
|
||||
@@ -28,6 +63,39 @@ ast_enum_child(Parser *p, Token *token, Intern_String name, Expr *expr){
|
||||
return node;
|
||||
}
|
||||
|
||||
function void
|
||||
ast_copy_symbol(AST_Node *dst, AST_Node *src){
|
||||
AST_Node *scope_next = dst->next_scope;
|
||||
*dst = *src;
|
||||
dst->next_scope = scope_next;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
ast_type_pointer(Parser *p, Token *token, AST_Node *pointer_to){
|
||||
AST_Node *node = ast_node_new(p, AK_Pointer, token, intern_empty);
|
||||
node->pointer = pointer_to;
|
||||
return node;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
ast_type_array(Parser *p, Token *token, AST_Node *pointer_to, Expr *expr){
|
||||
AST_Node *node = ast_node_new(p, AK_Array, token, intern_empty);
|
||||
node->pointer = pointer_to;
|
||||
node->expr = expr;
|
||||
return node;
|
||||
}
|
||||
|
||||
function void
|
||||
ast_node_pass_note_list(AST_Node *node, AST_Node *notes){
|
||||
node->first_note = notes->first_note;
|
||||
node->last_note = notes->last_note;
|
||||
}
|
||||
|
||||
function void
|
||||
ast_node_push_note(AST_Node *node, AST_Node *child){
|
||||
SLLQueuePush(node->first_note, node->last_note, child);
|
||||
}
|
||||
|
||||
function void
|
||||
ast_node_push_child(AST_Node *node, AST_Node *child){
|
||||
SLLQueuePush(node->first_child, node->last_child, child);
|
||||
|
||||
141
ast.h
141
ast.h
@@ -1,9 +1,142 @@
|
||||
#if 0
|
||||
|
||||
|
||||
String:struct{
|
||||
str: U8*;
|
||||
len: S64;
|
||||
}
|
||||
Intern_String:typedef String;
|
||||
|
||||
Token_Kind:enum{
|
||||
@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,
|
||||
}
|
||||
|
||||
|
||||
Token:struct{
|
||||
kind:Token_Kind;
|
||||
union:{
|
||||
string:String;
|
||||
struct:{str:U8*; len:U64;}
|
||||
}
|
||||
union:{
|
||||
int_val:S64;
|
||||
error_val:String;
|
||||
intern_val:Intern_String;
|
||||
}
|
||||
file:String;
|
||||
line:S64;
|
||||
line_begin:U8*;
|
||||
}
|
||||
|
||||
|
||||
AST_Kind:enum{
|
||||
BaseType,
|
||||
Typedef,
|
||||
Enum,
|
||||
Struct,
|
||||
Union,
|
||||
|
||||
Note,
|
||||
List,
|
||||
|
||||
Pointer,
|
||||
Array,
|
||||
Function,
|
||||
Variable,
|
||||
EnumChild,
|
||||
}
|
||||
|
||||
AST_Node:struct{
|
||||
kind: AST_Kind;
|
||||
node: AST_Node[16];
|
||||
|
||||
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*;
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
typedef struct AST_Node AST_Node;
|
||||
typedef struct Expr Expr;
|
||||
|
||||
typedef enum AST_Kind{
|
||||
AK_None,
|
||||
AK_Undefined,
|
||||
|
||||
AK_BaseType,
|
||||
AK_Typedef,
|
||||
@@ -19,7 +152,6 @@ typedef enum AST_Kind{
|
||||
AK_Function,
|
||||
AK_Variable,
|
||||
AK_EnumChild,
|
||||
|
||||
}AST_Kind;
|
||||
|
||||
struct AST_Node{
|
||||
@@ -29,7 +161,7 @@ struct AST_Node{
|
||||
Intern_String name;
|
||||
|
||||
AST_Node *next;
|
||||
AST_Node *scope_next;
|
||||
AST_Node *next_scope;
|
||||
|
||||
AST_Node *first_note;
|
||||
AST_Node *last_note;
|
||||
@@ -37,9 +169,10 @@ struct AST_Node{
|
||||
AST_Node *first_child;
|
||||
AST_Node *last_child;
|
||||
union{
|
||||
AST_Node *pointer;
|
||||
SizeU base_type_size;
|
||||
AST_Node *pointer;
|
||||
AST_Node *typedef_type;
|
||||
AST_Node *variable_type;
|
||||
AST_Node *func_return_type;
|
||||
};
|
||||
};
|
||||
|
||||
55
ideas.cpp
55
ideas.cpp
@@ -1,3 +1,56 @@
|
||||
|
||||
call:(param:U32)U32{
|
||||
|
||||
}
|
||||
|
||||
@stringify
|
||||
Enumeration:enum{
|
||||
None,
|
||||
Thing = 1 << 10,
|
||||
Thing2,
|
||||
Thing3,
|
||||
}
|
||||
|
||||
@sllqueue()
|
||||
@sllqueue(prefix=thing_scope, next=next_scope)
|
||||
Thing:struct{
|
||||
next: Thing*;
|
||||
first: Thing*;
|
||||
last: Thing*;
|
||||
next_scope: Thing*;
|
||||
|
||||
val: U32[16];
|
||||
str: String;
|
||||
embed: struct{
|
||||
thing: S32;
|
||||
}
|
||||
}
|
||||
|
||||
@register(sllqueue, first, last, next)
|
||||
sllqueue_push:(base:T1, child:T2) void {
|
||||
if(base.first == 0){
|
||||
base.first = base.last = child;
|
||||
}
|
||||
else{
|
||||
base.last = base.last.next = child;
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
/*
|
||||
function void
|
||||
thing_sllqueue_push(){
|
||||
|
||||
}
|
||||
|
||||
function void
|
||||
thing_scope_sllqueue_push(){
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
Builtin types:
|
||||
B8,B16,B32,B64
|
||||
S8,S16,S32,S64
|
||||
@@ -42,3 +95,5 @@ return 0;
|
||||
if(a){}elseif(b){}else{}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
4
lang.h
4
lang.h
@@ -41,7 +41,7 @@ typedef struct String{
|
||||
S64 len;
|
||||
}String;
|
||||
|
||||
#define SLLQueuePush(f,l,n) do{\
|
||||
#define SLLQueuePushMod(f,l,n,next) do{\
|
||||
if((f)==0){\
|
||||
(f)=(l)=(n);\
|
||||
}\
|
||||
@@ -50,6 +50,8 @@ else{\
|
||||
} \
|
||||
}while(0)
|
||||
|
||||
#define SLLQueuePush(f,l,n) SLLQueuePushMod(f,l,n,next)
|
||||
|
||||
|
||||
#define SLLStackPush(l,n) do{\
|
||||
(n)->next = (l);\
|
||||
|
||||
35
lex.c
35
lex.c
@@ -57,7 +57,7 @@ lex_is_alphanumeric(U8 c){
|
||||
|
||||
function void
|
||||
lex_set_len(Lex_Stream *s, Token *token){
|
||||
assert(s->stream > token->str);
|
||||
assert(s->stream >= token->str);
|
||||
token->len = s->stream - token->str;
|
||||
}
|
||||
|
||||
@@ -150,6 +150,13 @@ break
|
||||
|
||||
|
||||
Token *t = token_alloc(tokens);
|
||||
if(0){
|
||||
top:
|
||||
while(lex_is_whitespace(*s->stream))
|
||||
lex_advance(s);
|
||||
if(lexc(s) == 0)
|
||||
break;
|
||||
}
|
||||
lex_token_seed(s, t);
|
||||
lex_advance(s);
|
||||
switch(*t->str) {
|
||||
@@ -164,6 +171,7 @@ break
|
||||
#undef CASE2
|
||||
#undef CASE3
|
||||
|
||||
case 0: break;
|
||||
case '@': t->kind = TK_At; break;
|
||||
case '(': t->kind = TK_OpenParen; break;
|
||||
case ')': t->kind = TK_CloseParen; break;
|
||||
@@ -279,20 +287,21 @@ break
|
||||
lex_advance(s);
|
||||
if(lexc(s) == '/'){
|
||||
lex_advance(s);
|
||||
t->kind = TK_DocComment;
|
||||
//t->kind = TK_DocComment;
|
||||
}
|
||||
else {
|
||||
t->kind = TK_Comment;
|
||||
//t->kind = TK_Comment;
|
||||
}
|
||||
for(;;){
|
||||
if(lexc(s) == '\n' || lexc(s) == 0) break;
|
||||
lex_advance(s);
|
||||
}
|
||||
lex_set_len(s,t);
|
||||
goto top;
|
||||
//lex_set_len(s,t);
|
||||
}
|
||||
else if(lexc(s) == '*'){
|
||||
lex_advance(s);
|
||||
t->kind = TK_Comment;
|
||||
//t->kind = TK_Comment;
|
||||
for(;;){
|
||||
if(s->stream[0] == '*' && s->stream[1] == '/'){
|
||||
lex_advance(s);
|
||||
@@ -305,7 +314,8 @@ break
|
||||
}
|
||||
lex_advance(s);
|
||||
}
|
||||
lex_set_len(s,t);
|
||||
goto top;
|
||||
//lex_set_len(s,t);
|
||||
}
|
||||
else t->kind = TK_Div;
|
||||
} break;
|
||||
@@ -424,9 +434,7 @@ token_is_keyword(Parser *p, Intern_String keyword){
|
||||
|
||||
function void
|
||||
token_advance(Parser *p){
|
||||
do{
|
||||
p->tokens.iter = clamp_top_s64(p->tokens.iter + 1, p->tokens.len);
|
||||
}while(token_is_comment(token_get(p)));
|
||||
}
|
||||
|
||||
function Token *
|
||||
@@ -496,3 +504,14 @@ token_peek_is(Parser *p, S64 count, Token_Kind kind){
|
||||
return token;
|
||||
return 0;
|
||||
}
|
||||
|
||||
function Token *
|
||||
token_peek_is_keyword(Parser *p, S64 count, Intern_String keyword){
|
||||
Token *token = token_peek(p, count);
|
||||
if(token->kind == TK_Keyword){
|
||||
if(intern_compare(keyword, token->intern_val)){
|
||||
return token;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
28
main.c
28
main.c
@@ -67,10 +67,10 @@ parser_test(){
|
||||
}
|
||||
|
||||
parser_lex_stream(&p, lit("S64 thing; S64 second_var = 10;"), lit("File"));
|
||||
assert(token_match(&p, TK_Keyword));
|
||||
assert(token_match(&p, TK_Identifier));
|
||||
assert(token_match(&p, TK_Identifier));
|
||||
assert(token_match(&p, TK_Semicolon));
|
||||
assert(token_match(&p, TK_Keyword));
|
||||
assert(token_match(&p, TK_Identifier));
|
||||
assert(token_match(&p, TK_Identifier));
|
||||
assert(token_match(&p, TK_Assign));
|
||||
assert(token_match(&p, TK_Int));
|
||||
@@ -99,20 +99,26 @@ parser_test(){
|
||||
lex_print("\n");
|
||||
}
|
||||
|
||||
String decls[] = {
|
||||
lit("enum Thing{ Thing_1 = 10, Thing_2 = 20<<1 };"),
|
||||
};
|
||||
for(S64 i = 0; i < buff_cap(decls); i++){
|
||||
parser_lex_stream(&p, decls[i], lit("File"));
|
||||
AST_Node *node = parse(&p);
|
||||
assert(node);
|
||||
/*
|
||||
String decls =
|
||||
lit("@Test(a=\"thing\") @str=\"based\" Thing:enum{ Thing_1 = 1<<10, Thing_2 = 10 }"
|
||||
"TTT:struct{ thing:U64; nested:struct{ thing:S64; }}"
|
||||
""
|
||||
);
|
||||
*/
|
||||
|
||||
String decls = os_read_file(lit("ast.h"));
|
||||
parser_lex_stream(&p, decls, lit("File"));
|
||||
AST_Node *node = parse(&p);
|
||||
assert(node->first_child);
|
||||
assert(node->last_child);
|
||||
ast_print(node);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function S32
|
||||
os_main(){
|
||||
global_output_file = fopen("output.txt", "w");
|
||||
global_output_file = fopen("output.cc", "w");
|
||||
assert_msg(global_output_file, "Failed to open output.txt");
|
||||
lex_test();
|
||||
parser_test();
|
||||
|
||||
4
memory.c
4
memory.c
@@ -24,8 +24,8 @@ arena_init(Arena *a){
|
||||
|
||||
function void *
|
||||
arena_push_size(Arena *a, SizeU size){
|
||||
SizeU generous_size = size + a->alignment;
|
||||
if(generous_size>a->memory.commit){
|
||||
SizeU generous_size = size;
|
||||
if(a->memory.commit+generous_size>a->memory.commit){
|
||||
if(a->memory.reserve == 0){
|
||||
arena_init(a);
|
||||
}
|
||||
|
||||
16
os_win32.c
16
os_win32.c
@@ -22,6 +22,22 @@ WinMain(HINSTANCE hInstance, HINSTANCE a, LPSTR b, int nShowCmd){
|
||||
return os_main();
|
||||
}
|
||||
|
||||
function String
|
||||
os_read_file(String name){
|
||||
String result = {};
|
||||
FILE *f = fopen((char *)name.str, "rb");
|
||||
fseek(f, 0, SEEK_END);
|
||||
result.len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET); /* same as rewind(f); */
|
||||
|
||||
result.str = malloc(result.len + 1);
|
||||
fread(result.str, result.len, 1, f);
|
||||
fclose(f);
|
||||
|
||||
result.str[result.len] = 0;
|
||||
return result;
|
||||
}
|
||||
|
||||
function OS_Memory
|
||||
os_reserve(SizeU size){
|
||||
OS_Memory result = {0};
|
||||
|
||||
142
output.cc
Normal file
142
output.cc
Normal file
@@ -0,0 +1,142 @@
|
||||
(4+(2*53))
|
||||
Error: Expected token of kind: ), got instead token of kind: End of stream
|
||||
((4+2)*53)
|
||||
(++5)
|
||||
(--5)
|
||||
(-5)
|
||||
(+5)
|
||||
(()5)
|
||||
((()5)+3)
|
||||
((534>43)?435:42)
|
||||
(((534>43)?435:42),234,(()42),Thing[10][2],Thing(1,2))
|
||||
typedef struct String String;
|
||||
struct String{
|
||||
U8 *str;
|
||||
S64 len;
|
||||
};
|
||||
|
||||
typedef Intern_String;
|
||||
enum Token_Kind{
|
||||
End,
|
||||
Mul,
|
||||
Div,
|
||||
Add,
|
||||
Sub,
|
||||
Mod,
|
||||
BitAnd,
|
||||
BitOr,
|
||||
BitXor,
|
||||
Neg,
|
||||
Not,
|
||||
OpenParen,
|
||||
CloseParen,
|
||||
OpenBrace,
|
||||
CloseBrace,
|
||||
OpenBracket,
|
||||
CloseBracket,
|
||||
Comma,
|
||||
Pound,
|
||||
Question,
|
||||
ThreeDots,
|
||||
Semicolon,
|
||||
Dot,
|
||||
LesserThen,
|
||||
GreaterThen,
|
||||
Colon,
|
||||
Assign,
|
||||
DivAssign,
|
||||
MulAssign,
|
||||
ModAssign,
|
||||
SubAssign,
|
||||
AddAssign,
|
||||
AndAssign,
|
||||
OrAssign,
|
||||
XorAssign,
|
||||
LeftShiftAssign,
|
||||
RightShiftAssign,
|
||||
DoubleColon,
|
||||
At,
|
||||
Decrement,
|
||||
Increment,
|
||||
PostDecrement,
|
||||
PostIncrement,
|
||||
LesserThenOrEqual,
|
||||
GreaterThenOrEqual,
|
||||
Equals,
|
||||
And,
|
||||
Or,
|
||||
NotEquals,
|
||||
LeftShift,
|
||||
RightShift,
|
||||
Arrow,
|
||||
ExprSizeof,
|
||||
DocComment,
|
||||
Comment,
|
||||
Identifier,
|
||||
StringLit,
|
||||
U8Lit,
|
||||
Character,
|
||||
Error,
|
||||
Float,
|
||||
Int,
|
||||
Keyword,
|
||||
}
|
||||
|
||||
typedef struct Token Token;
|
||||
struct Token{
|
||||
Token_Kind kind;
|
||||
union {
|
||||
String string;
|
||||
struct {
|
||||
U8 *str;
|
||||
U64 len;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
union {
|
||||
S64 int_val;
|
||||
String error_val;
|
||||
String intern_val;
|
||||
};
|
||||
|
||||
String file;
|
||||
S64 line;
|
||||
U8 *line_begin;
|
||||
};
|
||||
|
||||
enum AST_Kind{
|
||||
BaseType,
|
||||
Typedef,
|
||||
Enum,
|
||||
Struct,
|
||||
Union,
|
||||
Note,
|
||||
List,
|
||||
Pointer,
|
||||
Array,
|
||||
Function,
|
||||
Variable,
|
||||
EnumChild,
|
||||
}
|
||||
|
||||
typedef struct AST_Node AST_Node;
|
||||
struct AST_Node{
|
||||
AST_Kind kind;
|
||||
AST_Node node[16];
|
||||
AST_Node *next;
|
||||
AST_Node *next_scope;
|
||||
AST_Node *first_note;
|
||||
AST_Node *last_note;
|
||||
AST_Node *first_child;
|
||||
AST_Node *last_child;
|
||||
union {
|
||||
SizeU base_type_size;
|
||||
AST_Node *pointer;
|
||||
AST_Node *typedef_type;
|
||||
AST_Node *variable_type;
|
||||
AST_Node *func_return_type;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
198
parse_decl.c
198
parse_decl.c
@@ -1,50 +1,168 @@
|
||||
global Intern_String intern_empty;
|
||||
|
||||
|
||||
function Token *
|
||||
parse__get_name(Parser *p){
|
||||
Token *name = token_next(p);
|
||||
token_next(p);
|
||||
token_next(p);
|
||||
return name;
|
||||
}
|
||||
|
||||
function void
|
||||
parse_note_list(Parser *ctx, AST_Node *parent) {
|
||||
if(token_match(ctx, TK_OpenParen)) {
|
||||
do {
|
||||
Token *name = token_expect(ctx, TK_Identifier);
|
||||
AST_Node *current = ast_note(ctx, name, name->intern_val, 0);
|
||||
ast_node_push_note(parent, current);
|
||||
parse_note_list(ctx, current);
|
||||
if(token_match(ctx, TK_Assign)) {
|
||||
current->expr = parse_expr(ctx);
|
||||
}
|
||||
} while(token_match(ctx, TK_Comma));
|
||||
token_expect(ctx, TK_CloseParen);
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
parse__notes(Parser *ctx, AST_Node *result) {
|
||||
while(token_match(ctx, TK_At)) {
|
||||
Token *name = token_expect(ctx, TK_Identifier);
|
||||
AST_Node *current = ast_note(ctx, name, name->intern_val, 0);
|
||||
ast_node_push_note(result, current);
|
||||
parse_note_list(ctx, current);
|
||||
if(token_match(ctx, TK_Assign)) {
|
||||
current->expr = parse_expr(ctx);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function AST_Node
|
||||
parse_notes(Parser *p){
|
||||
AST_Node result = {};
|
||||
parse__notes(p, &result);
|
||||
return result;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
parse_enum(Parser *p){
|
||||
parse_enum(Parser *p, Token *name){
|
||||
AST_Node *result = 0;
|
||||
Token *name = token_match(p, TK_Identifier);
|
||||
if(token_match(p, TK_OpenBrace)){
|
||||
Token *op_close_brace = token_match(p, TK_CloseBrace);
|
||||
|
||||
if(!op_close_brace){
|
||||
|
||||
if(token_expect(p, TK_OpenBrace)){
|
||||
result = ast_enum(p, name, name->intern_val);
|
||||
do{ // Parse enum members
|
||||
Token *identifier = token_match(p, TK_Identifier);
|
||||
if(identifier){
|
||||
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, identifier, identifier->intern_val, expr);
|
||||
|
||||
AST_Node *child = ast_enum_child(p, token, token->intern_val, expr);
|
||||
ast_node_pass_note_list(child,¬es);
|
||||
ast_node_push_child(result, child);
|
||||
{
|
||||
// Insert into scope
|
||||
}
|
||||
}
|
||||
else{
|
||||
parser_push_error(p, token_get(p), "invalid syntax of enum member");
|
||||
break;
|
||||
}
|
||||
} while(token_match(p, TK_Comma));
|
||||
token_expect(p, TK_CloseBrace);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
parse_variable(Parser *p, Token *name){
|
||||
AST_Node *result = 0;
|
||||
Token *type_token = token_expect(p, TK_Identifier);
|
||||
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, ¬es);
|
||||
ast_node_push_child(result, mem);
|
||||
}
|
||||
|
||||
}
|
||||
else{
|
||||
parser_push_error(p, op_close_brace, "enum without body");
|
||||
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, ¬es);
|
||||
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, ¬es);
|
||||
ast_node_push_child(result, mem);
|
||||
}
|
||||
else if(token_expect(p, TK_CloseBrace)){
|
||||
break;
|
||||
}
|
||||
else{
|
||||
if(name == 0){
|
||||
parser_push_error(p, token_get(p), "enum without name or body is illegal");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if(ast_is_named(result)){
|
||||
// Insert into scope
|
||||
}
|
||||
|
||||
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);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -54,6 +172,7 @@ parse(Parser *p){
|
||||
|
||||
for(;;){
|
||||
AST_Node *node = 0;
|
||||
AST_Node notes = parse_notes(p);
|
||||
|
||||
if(token_is(p, TK_End)){
|
||||
break;
|
||||
@@ -61,29 +180,40 @@ parse(Parser *p){
|
||||
else if(token_is(p, TK_Error)){
|
||||
break;
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_struct)){
|
||||
|
||||
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_match_keyword(p, keyword_union)){
|
||||
|
||||
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_match_keyword(p, keyword_enum)){
|
||||
node = parse_enum(p);
|
||||
token_expect(p, TK_Semicolon);
|
||||
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_match_keyword(p, keyword_function)){
|
||||
|
||||
else if(token_peek_is_keyword(p, 2, keyword_typedef)){
|
||||
node = parse_typedef(p, parse__get_name(p));
|
||||
symbol_register(p, node);
|
||||
}
|
||||
else{
|
||||
token_next(p);
|
||||
}
|
||||
else if(token_match_keyword(p, keyword_typedef)){
|
||||
|
||||
}
|
||||
else{
|
||||
token_next(p);
|
||||
}
|
||||
|
||||
|
||||
if(node){
|
||||
ast_node_pass_note_list(node, ¬es);
|
||||
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;
|
||||
|
||||
@@ -92,7 +92,7 @@ Expr* parse_unary_expr(Parser* p) {
|
||||
}
|
||||
else if (token_is(p, TK_OpenParen)) { // cast requires lookahead
|
||||
Token *token = token_peek(p, 1);
|
||||
if (token->kind == TK_Keyword || token->kind == TK_Identifier) {
|
||||
if (token->kind == TK_Identifier) {
|
||||
|
||||
AST_Node *type = symbol_lookup_type(p, token->intern_val);
|
||||
if(type){
|
||||
|
||||
138
parser.c
138
parser.c
@@ -1,9 +1,19 @@
|
||||
global Intern_String keyword_s64;
|
||||
global Intern_String keyword_u64;
|
||||
global Intern_String keyword_void;
|
||||
global Intern_String keyword_sizeu;
|
||||
global Intern_String keyword_sizeof;
|
||||
global Intern_String intern_empty;
|
||||
|
||||
global Intern_String intern_s64;
|
||||
global Intern_String intern_s32;
|
||||
global Intern_String intern_s16;
|
||||
global Intern_String intern_s8;
|
||||
|
||||
global Intern_String intern_u64;
|
||||
global Intern_String intern_u32;
|
||||
global Intern_String intern_u16;
|
||||
global Intern_String intern_u8;
|
||||
|
||||
global Intern_String intern_void;
|
||||
global Intern_String intern_sizeu;
|
||||
|
||||
global Intern_String keyword_sizeof;
|
||||
global Intern_String keyword_enum;
|
||||
global Intern_String keyword_typedef;
|
||||
global Intern_String keyword_struct;
|
||||
@@ -12,7 +22,15 @@ global Intern_String keyword_function;
|
||||
global Intern_String keyword_global;
|
||||
|
||||
global AST_Node *type_s64;
|
||||
global AST_Node *type_s32;
|
||||
global AST_Node *type_s16;
|
||||
global AST_Node *type_s8;
|
||||
|
||||
global AST_Node *type_u64;
|
||||
global AST_Node *type_u32;
|
||||
global AST_Node *type_u16;
|
||||
global AST_Node *type_u8;
|
||||
|
||||
global AST_Node *type_void;
|
||||
global AST_Node *type_sizeu;
|
||||
|
||||
@@ -24,10 +42,6 @@ parser_init(Parser *p){
|
||||
p->symbols_count = 4096;
|
||||
p->symbols = arena_push_array(&p->symbol_table_arena, AST_Node, p->symbols_count);
|
||||
|
||||
keyword_s64 = intern_string(p, lit("S64"));
|
||||
keyword_u64 = intern_string(p, lit("U64"));
|
||||
keyword_void = intern_string(p, lit("void"));
|
||||
keyword_sizeu = intern_string(p, lit("SizeU"));
|
||||
keyword_sizeof = intern_string(p, lit("sizeof"));
|
||||
keyword_struct = intern_string(p, lit("struct"));
|
||||
keyword_enum = intern_string(p, lit("enum"));
|
||||
@@ -35,14 +49,37 @@ parser_init(Parser *p){
|
||||
keyword_union = intern_string(p, lit("union"));
|
||||
keyword_function = intern_string(p, lit("function"));
|
||||
keyword_global = intern_string(p, lit("global"));
|
||||
p->first_keyword = keyword_s64.s.str;
|
||||
p->first_keyword = keyword_sizeof.s.str;
|
||||
p->last_keyword = keyword_global.s.str;
|
||||
|
||||
|
||||
intern_s64 = intern_string(p, lit("S64"));
|
||||
intern_s32 = intern_string(p, lit("S32"));
|
||||
intern_s16 = intern_string(p, lit("S16"));
|
||||
intern_s8 = intern_string(p, lit("S8"));
|
||||
|
||||
intern_u64 = intern_string(p, lit("U64"));
|
||||
intern_u32 = intern_string(p, lit("U32"));
|
||||
intern_u16 = intern_string(p, lit("U16"));
|
||||
intern_u8 = intern_string(p, lit("U8"));
|
||||
|
||||
intern_void = intern_string(p, lit("void"));
|
||||
intern_sizeu = intern_string(p, lit("SizeU"));
|
||||
|
||||
parser_push_scope(p); // Global scope
|
||||
type_s64 = symbol_register_basic_type(p, keyword_s64, sizeof(S64));
|
||||
type_u64 = symbol_register_basic_type(p, keyword_u64, sizeof(U64));
|
||||
type_sizeu = symbol_register_basic_type(p, keyword_sizeu, sizeof(SizeU));
|
||||
type_void = symbol_register_basic_type(p, keyword_void, sizeof(void));
|
||||
|
||||
type_s64 = symbol_register_basic_type(p, intern_s64, sizeof(S64));
|
||||
type_s32 = symbol_register_basic_type(p, intern_s32, sizeof(S32));
|
||||
type_s16 = symbol_register_basic_type(p, intern_s16, sizeof(S16));
|
||||
type_s8 = symbol_register_basic_type(p, intern_s8, sizeof(S8));
|
||||
|
||||
type_u64 = symbol_register_basic_type(p, intern_u64, sizeof(U64));
|
||||
type_u32 = symbol_register_basic_type(p, intern_u32, sizeof(U32));
|
||||
type_u16 = symbol_register_basic_type(p, intern_u16, sizeof(U16));
|
||||
type_u8 = symbol_register_basic_type(p, intern_u8, sizeof(U8));
|
||||
|
||||
type_void = symbol_register_basic_type(p, intern_void, sizeof(void));
|
||||
type_sizeu = symbol_register_basic_type(p, intern_sizeu, sizeof(SizeU));
|
||||
|
||||
}
|
||||
|
||||
@@ -53,19 +90,6 @@ intern_is_keyword(Parser *p, Intern_String intern){
|
||||
return false;
|
||||
}
|
||||
|
||||
function void
|
||||
intern_tokens(Parser *p){
|
||||
for(S64 i = 0; i < p->tokens.len; i++){
|
||||
Token *t = p->tokens.tokens + i;
|
||||
if(t->kind == TK_Identifier){
|
||||
t->intern_val = intern_string(p, t->string);
|
||||
if(intern_is_keyword(p, t->intern_val)){
|
||||
t->kind = TK_Keyword;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
parser_push_error(Parser *p, Token *token, char *str, ...){
|
||||
|
||||
@@ -90,6 +114,22 @@ parser_push_error(Parser *p, Token *token, char *str, ...){
|
||||
SLLQueuePush(p->first_error, p->last_error, error);
|
||||
}
|
||||
|
||||
function void
|
||||
intern_tokens(Parser *p){
|
||||
for(S64 i = 0; i < p->tokens.len; i++){
|
||||
Token *t = p->tokens.tokens + i;
|
||||
if(t->kind == TK_Identifier){
|
||||
t->intern_val = intern_string(p, t->string);
|
||||
if(intern_is_keyword(p, t->intern_val)){
|
||||
t->kind = TK_Keyword;
|
||||
}
|
||||
}
|
||||
else if(t->kind == TK_Error){
|
||||
parser_push_error(p, t, (char *)t->error_val.str);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
@@ -162,10 +202,10 @@ symbol_alloc_slot(Parser *p, Intern_String string, B32 is_global){
|
||||
if(symbol->name.s.str == 0){
|
||||
/* @Note(Krzosa): Push on scope */ {
|
||||
if(is_global){
|
||||
SLLQueuePush(p->scope_stack->first, p->scope_stack->last, symbol);
|
||||
SLLQueuePushMod(p->scope_stack->first, p->scope_stack->last, symbol, next_scope);
|
||||
}
|
||||
else{
|
||||
SLLQueuePush(p->global_scope->first, p->global_scope->last, symbol);
|
||||
SLLQueuePushMod(p->global_scope->first, p->global_scope->last, symbol, next_scope);
|
||||
}
|
||||
}
|
||||
symbol->name = string;
|
||||
@@ -181,6 +221,7 @@ symbol_alloc_slot(Parser *p, Intern_String string, B32 is_global){
|
||||
break;
|
||||
}
|
||||
|
||||
assert_msg(0, "Ran out of slots in symbol table");
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -205,11 +246,39 @@ symbol_lookup(Parser *p, Intern_String string){
|
||||
function AST_Node *
|
||||
symbol_register_basic_type(Parser *p, Intern_String string, SizeU size){
|
||||
AST_Node *node = symbol_alloc_slot(p, string, true);
|
||||
assert(node->kind == AK_None);
|
||||
node->kind = AK_BaseType;
|
||||
node->base_type_size = size;
|
||||
return node;
|
||||
}
|
||||
|
||||
function void
|
||||
symbol_register(Parser *p, AST_Node *node){
|
||||
AST_Node *look = symbol_alloc_slot(p, node->name, false);
|
||||
if(look->kind == AK_None){
|
||||
ast_copy_symbol(look, node);
|
||||
}
|
||||
else if(look->kind == node->kind){
|
||||
if(look->kind == AK_Enum ||
|
||||
look->kind == AK_Function ||
|
||||
look->kind == AK_Union ||
|
||||
look->kind == AK_Struct){
|
||||
if(look->first_child == 0){
|
||||
ast_copy_symbol(look, node);
|
||||
}
|
||||
else {
|
||||
parser_push_error(p, token_get(p), "Symbol already has a body");
|
||||
}
|
||||
}
|
||||
else {
|
||||
parser_push_error(p, token_get(p), "Trying to register a symbol again");
|
||||
}
|
||||
}
|
||||
else{
|
||||
parser_push_error(p, token_get(p), "Trying to register a symbol of different kind with the same name");
|
||||
}
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
symbol_lookup_type(Parser *p, Intern_String string){
|
||||
AST_Node *node = symbol_lookup(p, string);
|
||||
@@ -221,6 +290,15 @@ symbol_lookup_type(Parser *p, Intern_String string){
|
||||
return 0;
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
symbol_require_type(Parser *p, Token *token){
|
||||
AST_Node *result = symbol_lookup_type(p, token->intern_val);
|
||||
if(!result){
|
||||
parser_push_error(p, token, "Undefined type");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function void
|
||||
parser_push_scope(Parser *p){
|
||||
Scope *scope = 0;
|
||||
@@ -240,7 +318,7 @@ parser_pop_scope(Parser *p){
|
||||
SLLStackPop(p->scope_stack, scope);
|
||||
assert(scope);
|
||||
|
||||
for(AST_Node *s = scope->first; s; s=s->scope_next){
|
||||
for(AST_Node *s = scope->first; s; s=s->next_scope){
|
||||
memory_zero(s, sizeof(AST_Node));
|
||||
p->symbols_inserted--;
|
||||
}
|
||||
|
||||
1
parser.h
1
parser.h
@@ -48,3 +48,4 @@ function Token *token_get(Parser *p);
|
||||
function B32 intern_compare(Intern_String a, Intern_String b);
|
||||
function void parser_push_scope(Parser *p);
|
||||
function AST_Node *symbol_register_basic_type(Parser *p, Intern_String string, SizeU size);
|
||||
function void ast_copy_symbol(AST_Node *dst, AST_Node *src);
|
||||
137
print.c
137
print.c
@@ -74,3 +74,140 @@ expr_print(Expr *expr){
|
||||
default: {invalid_codepath;} break;
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
print_indent(S64 indent){
|
||||
for(S64 i = 0; i < indent; i++){
|
||||
lex_print(" ");
|
||||
}
|
||||
}
|
||||
|
||||
function AST_Node *
|
||||
ast_get_basis_type(AST_Node *node){
|
||||
switch(node->kind) {
|
||||
case AK_Struct: case AK_Union: case AK_Enum: case AK_BaseType:{return node;} break;
|
||||
case AK_Function:{return node;} break;
|
||||
case AK_Typedef:{return node->typedef_type;} break;
|
||||
case AK_Array: case AK_Pointer:{return ast_get_basis_type(node->pointer);} break;
|
||||
default: invalid_codepath;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function void
|
||||
ast_print_pointers(AST_Node *node){
|
||||
if(node->kind == AK_Pointer){
|
||||
lex_print("*");
|
||||
ast_print_pointers(node->pointer);
|
||||
}
|
||||
else if(node->kind == AK_Array){
|
||||
ast_print_pointers(node->pointer);
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
ast_print_arrays(AST_Node *node){
|
||||
if(node->kind == AK_Pointer){
|
||||
ast_print_arrays(node->pointer);
|
||||
}
|
||||
else if(node->kind == AK_Array){
|
||||
lex_print("[");
|
||||
expr_print(node->expr);
|
||||
lex_print("]");
|
||||
ast_print_arrays(node->pointer);
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
ast_print_var(AST_Node *node);
|
||||
function void
|
||||
ast_print_func_params(AST_Node *node){
|
||||
for(AST_Node *n = node->first_child; n; n=n->next){
|
||||
ast_print_var(n);
|
||||
if(n != node->last_child) lex_print(", ");
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
ast_print_var(AST_Node *node){
|
||||
AST_Node *basis_type = ast_get_basis_type(node->variable_type);
|
||||
if(basis_type->kind == AK_Function){
|
||||
lex_print("%s (*%s)(", basis_type->func_return_type->name.s.str, node->name.s.str);
|
||||
ast_print_func_params(basis_type);
|
||||
lex_print(")");
|
||||
}
|
||||
else{
|
||||
lex_print("%s ", basis_type->name.s.str);
|
||||
ast_print_pointers(node->variable_type);
|
||||
lex_print("%s", node->name.s.str);
|
||||
ast_print_arrays(node->variable_type);
|
||||
}
|
||||
|
||||
if(node->expr){
|
||||
lex_print(" = ");
|
||||
expr_print(node->expr);
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
ast__print(AST_Node *node, S64 indent){
|
||||
switch(node->kind){
|
||||
|
||||
case AK_List:{
|
||||
for(AST_Node *n = node->first_child; n; n=n->next){
|
||||
ast__print(n, indent);
|
||||
lex_print("\n");
|
||||
}
|
||||
} break;
|
||||
|
||||
case AK_Union:
|
||||
case AK_Struct:{
|
||||
const char *type = node->kind == AK_Struct ? "struct":"union";
|
||||
if(indent == 0) lex_print("typedef %s %s %s;\n", type, node->name.s.str, node->name.s.str);
|
||||
lex_print("%s %s{\n", type, indent == 0 ? node->name.s.str:(U8 *)"");
|
||||
for(AST_Node *n = node->first_child; n; n=n->next){
|
||||
ast__print(n, indent+2);
|
||||
lex_print("\n");
|
||||
}
|
||||
|
||||
lex_print("}");
|
||||
lex_print("%s;\n", indent == 0 ? (U8 *)"":node->name.s.str?node->name.s.str:(U8*)"");
|
||||
} break;
|
||||
|
||||
case AK_Variable:{
|
||||
if(indent == 0) lex_print("global ");
|
||||
ast_print_var(node);
|
||||
lex_print(";");
|
||||
} break;
|
||||
|
||||
case AK_Typedef:{
|
||||
lex_print("typedef ");
|
||||
lex_print("%s;", node->name.s.str);
|
||||
} break;
|
||||
|
||||
case AK_Enum:{
|
||||
print_indent(indent);
|
||||
lex_print("enum %s{\n", node->name.s.str);
|
||||
|
||||
for(AST_Node *n = node->first_child; n; n=n->next){
|
||||
print_indent(indent+2);
|
||||
lex_print("%s", n->name.s.str);
|
||||
if(n->expr){
|
||||
lex_print(" = ");
|
||||
expr_print(n->expr);
|
||||
}
|
||||
lex_print(",\n");
|
||||
}
|
||||
|
||||
print_indent(indent);
|
||||
lex_print("}\n");
|
||||
} break;
|
||||
|
||||
default: invalid_codepath;
|
||||
}
|
||||
}
|
||||
|
||||
function void
|
||||
ast_print(AST_Node *node){
|
||||
ast__print(node, 0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user