Named function args

This commit is contained in:
Krzosa Karol
2022-05-06 15:56:22 +02:00
parent 7e3eefda57
commit 76a8cc779c
5 changed files with 543 additions and 291 deletions

179
ideas.cpp
View File

@@ -1,170 +1,33 @@
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
New_Data_Type::typedef int;
CONST_VAL::const 324;
actual_function :: (first: Thing*, last: Thing*, node: Thing*)/*no type == void*/{
if first == 0 {
first = last = node;
}
else{
last = last->next = node;
}
Ideas::enum{
One,
Two,
Three
}
StructInside :: struct { // This is not part of struct
// just in scope
some_val: U16;
some_val2: U16;
Data::struct{
first: int;
second: int;
idea: Ideas;
}
insider: StructInside;
named_union_part_of_struct: union{
some_val: U16;
some_val2: U32;
function_call::(first_param: Data*, second_param: int[32]){
first_param.first = 10;
first_param.second = 10;
first_param.idea = Ideas.One;
p:= first_param;
for i in 0...32 {
second_param[i] = i;
}
_: union {
// Unamed union
val: U32;
for i := 0; i < 32; i++ {
second_param[i] = i;
}
return p;
}
Scope :: scope{
Thingy::enum:U32{
@str=10 Value = 1,
}
}
//Scope.Thingy
Thing::union{
union:{
}
struct:{
}
}
Thing::struct{
data: U32;
inside_call :: (param: U32){
}
}
call :: (param:U32) U32{
inner_call :: (param2:U32){
size_of_s64 = sizeof(:S64);
size_of_val = sizeof(param);
param2 + 10;
return;
}
inner_call();
}
@stringify
Enumeration:enum{
None,
Thing = 1 << 10,
Thing2,
Thing3,
}
@sllqueue()
@sllqueue(prefix=thing_scope, next=next_scope)
Thing::struct{
Inner_Struct :: {
test_val : U32;
}
thing:Inner_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
U8,U16,U32,U64
SizeI, SizeU
F32, F64
Decls:
S32 *var;
S32 (*func)();
S32 *var[expr][expr];
S32 **var;
Global scope:
function S32
do_thing(S32 a, U32 b){
stmt_list
}
function S32
do_thing(S32 a, S32 b);
typedef struct Thing Thing;
struct Thing{};
typedef struct Thing{} Thing;
typedef enum Thingy Thingy;
enum Thingy{};
typedef enum Thingy{} Thingy;
global S32 variable = expr | compound;
// typedef S32 NewName;
// typedef S32 BaseFunctionType(S32 thing);
// typedef S32 (*FunctionPointer)(S32 thing);
Local scope-(stmts):
S32 variable = expr;
variable = expr;
variable++;
return 0;
if(a){}elseif(b){}else{}

1
main.c
View File

@@ -18,4 +18,5 @@
int main(){
lex_test();
parse_test();
ast_test();
}

469
new_ast.c
View File

@@ -1,6 +1,129 @@
typedef struct Expr Expr;
typedef struct Note Note;
typedef struct Decl Decl;
typedef struct Stmt Stmt;
typedef struct Stmt_If Stmt_If;
typedef struct Typespec Typespec;
typedef struct Decl_Enum_Child Decl_Enum_Child;
typedef struct Decl_Function_Arg Decl_Function_Arg;
typedef struct Expr_Compound_Field Expr_Compound_Field;
//-----------------------------------------------------------------------------
// Expressions
//-----------------------------------------------------------------------------
typedef enum Expr_Sizeof_Kind{
SIZEOF_Expr,
SIZEOF_Type,
}Expr_Sizeof_Kind;
typedef enum Expr_Kind{
EK_None,
EK_Int,
EK_String,
EK_Identifier,
EK_Compound,
EK_Paren,
EK_PostfixUnary,
EK_Unary,
EK_Binary,
EK_Ternary,
EK_Cast,
EK_Field,
EK_Call,
EK_Index,
EK_SizeType,
EK_SizeExpr,
} Expr_Kind;
typedef enum Expr_Compound_Kind{
COMPOUND_None,
COMPOUND_Default,
COMPOUND_Named,
COMPOUND_Index,
}Expr_Compound_Kind;
struct Expr_Compound_Field{
Expr_Compound_Field *next;
Expr_Compound_Kind kind;
Token *pos;
Expr *init;
union{
Expr *index;
Intern_String name;
};
};
struct Expr {
Expr_Kind kind;
Token *token;
Expr *next;
union {
U64 int_val;
Intern_String intern_val;
double float_val;
struct {
Expr *expr;
} paren;
struct {
Typespec *typespec;
Expr* expr;
} cast;
struct{
Intern_String name;
Expr *expr;
}field;
struct{
Typespec *typespec;
Expr_Compound_Field *first;
Expr_Compound_Field *last;
}compound;
struct {
Expr *atom;
Expr_Compound_Field *first;
Expr_Compound_Field *last;
} call;
struct{
}arg;
struct {
Expr *atom;
Expr *index;
} index;
struct {
Token_Kind op;
Expr* expr;
} unary;
struct {
Token_Kind op;
Expr *expr;
} postfix_unary;
struct {
Token_Kind op;
Expr* left;
Expr* right;
} binary;
struct {
Expr* cond;
Expr* on_true;
Expr* on_false;
} ternary;
struct{
Typespec *typespec;
} size_type;
struct{
Expr *expr;
} size_expr;
};
};
//-----------------------------------------------------------------------------
// Type specifiers
//-----------------------------------------------------------------------------
typedef enum Typespec_Kind{
TS_None,
TS_Name,
@@ -29,92 +152,127 @@ struct Typespec{
};
//-----------------------------------------------------------------------------
// Expressions
// Declarations
//-----------------------------------------------------------------------------
typedef enum Expr_Sizeof_Kind{
SIZEOF_Expr,
SIZEOF_Type,
}Expr_Sizeof_Kind;
typedef enum Decl_Kind{
DECL_None,
DECL_Struct,
DECL_Union,
DECL_Enum,
DECL_Variable,
DECL_Typedef,
DECL_Function,
DECL_List,
}Decl_Kind;
typedef enum Expr_Kind{
EK_None,
EK_Int,
EK_String,
EK_Identifier,
EK_Paren,
EK_PostfixUnary,
EK_Unary,
EK_Binary,
EK_Ternary,
EK_Cast,
EK_Field,
EK_Call,
EK_Index,
EK_Sizeof,
} Expr_Kind;
struct Expr {
Expr_Kind kind;
Token *token;
Expr *next;
union {
U64 int_val;
Intern_String intern_val;
double float_val;
struct {
Expr *expr;
} paren;
struct {
Typespec *type;
Expr* expr;
} cast;
struct{
struct Note{
Token *pos;
Intern_String name;
Expr *expr;
}field;
Note *next;
Note *first;
Note *last;
};
struct {
Expr *atom;
Expr *first;
Expr *last;
} call;
struct {
Expr *atom;
Expr *index;
} index;
struct {
Token_Kind op;
Expr* expr;
} unary;
struct {
Token_Kind op;
Expr *expr;
} postfix_unary;
struct {
Token_Kind op;
Expr* left;
Expr* right;
} binary;
struct {
Expr* cond;
Expr* on_true;
Expr* on_false;
} ternary;
struct Decl{
Decl_Kind kind;
Decl *next;
B32 is_incomplete;
struct{
Expr_Sizeof_Kind kind;
Decl *prev; // Doubly linked list?
Decl *parent; // ?
Intern_String name;
Token *pos;
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;
}var_decl;
struct{
Typespec *type;
}typedef_decl;
struct{
Decl_Function_Arg *first;
Decl_Function_Arg *last;
Typespec *ret;
//Stmt *body;
}func_decl;
struct{
Decl *first;
Decl *last;
}list_decl;
};
} size_of;
};
struct Decl_Function_Arg{
Decl_Function_Arg *next;
Token *pos;
Intern_String name;
Typespec *typespec;
};
struct Decl_Enum_Child{
Decl_Enum_Child *next;
Intern_String name;
Token *pos;
Expr *expr;
Note *first_note;
Note *last_note;
};
//-----------------------------------------------------------------------------
// Expr
// Statements
//-----------------------------------------------------------------------------
typedef enum Stmt_Kind{
STMT_None,
STMT_Decl,
STMT_Expr,
STMT_List,
STMT_Return,
STMT_If,
STMT_For,
}Stmt_Kind;
struct Stmt_If{
Stmt_If *next;
Expr *cond;
Stmt *body;
};
struct Stmt{
Stmt_Kind kind;
Stmt *next;
Token *pos;
union{
Stmt_If stmt_if;
Decl *decl;
Expr *expr;
struct{
Stmt *first;
Stmt *last;
}list;
struct{
Expr *expr;
}ret;
};
};
//-----------------------------------------------------------------------------
// Expression constructors
//-----------------------------------------------------------------------------
function Expr *
expr_new(Arena *p, Expr_Kind kind, Token *token){
@@ -216,28 +374,171 @@ expr_index(Arena *p, Token *token, Expr *atom, Expr *index){
function Expr *
expr_cast(Arena *p, Token *token, Typespec *type, Expr *exp){
Expr *expr = expr_new(p, EK_Cast, token);
expr->cast.type = type;
expr->cast.typespec = type;
expr->cast.expr = exp;
return expr;
}
function Expr *
expr_sizeof_type(Arena *p, Token *token, Typespec *type){
Expr *expr = expr_new(p, EK_Sizeof, token);
expr->size_of.kind = SIZEOF_Type;
expr->size_of.type = type;
expr_size_type(Arena *p, Token *token, Typespec *type){
Expr *expr = expr_new(p, EK_SizeType, token);
expr->size_type.typespec = type;
return expr;
}
function Expr *
expr_sizeof_expr(Arena *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;
Expr *expr = expr_new(p, EK_SizeExpr, token);
expr->size_expr.expr = in_expr;
return expr;
}
function void
expr_call_push(Expr *list, Expr *expr){
SLLQueuePush(list->call.first, list->call.last, expr);
function Expr *
expr_compound(Arena *arena, Token *pos, Typespec *typespec){
Expr *result = expr_new(arena, EK_Compound, pos);
result->compound.typespec = typespec;
return result;
}
function Expr_Compound_Field *
expr_compound_new(Arena *arena, Expr_Compound_Kind kind, Token *pos, Expr *init){
Expr_Compound_Field *result = arena_push_struct(arena, Expr_Compound_Field);
result->kind = kind;
result->pos = pos;
result->init = init;
return result;
}
function Expr_Compound_Field *
expr_compound_default(Arena *arena, Token *pos, Expr *init){
Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Default, pos, init);
return result;
}
function Expr_Compound_Field *
expr_compound_named(Arena *arena, Token *pos, Intern_String name, Expr *init){
Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Named, pos, init);
result->name = name;
return result;
}
function Expr_Compound_Field *
expr_compound_index(Arena *arena, Token *pos, Expr *index, Expr *init){
Expr_Compound_Field *result = expr_compound_new(arena, COMPOUND_Index, pos, init);
result->index = index;
return result;
}
function void
expr_call_push(Expr *list, Expr_Compound_Field *field){
SLLQueuePush(list->call.first, list->call.last, field);
}
function void
expr_compound_push(Expr *list, Expr_Compound_Field *field){
SLLQueuePush(list->compound.first, list->compound.last, field);
}
//-----------------------------------------------------------------------------
// Double linked list
//-----------------------------------------------------------------------------
function void
decl_list_push(Decl *l, Decl *node){
if(l->list_decl.first == 0){
l->list_decl.first = l->list_decl.last = node;
node->prev = 0;
node->next = 0;
}
else{
l->list_decl.last->next = node;
node->prev = l->list_decl.last;
node->next = 0;
l->list_decl.last = node;
}
node->parent = l;
}
function void
decl_list_push_front(Decl *l, Decl *node){
if(l->list_decl.first == 0){
l->list_decl.first = l->list_decl.last = node;
node->prev = 0;
node->next = 0;
}
else{
node->next = l->list_decl.first;
l->list_decl.first->prev = node;
node->prev = 0;
l->list_decl.first = node;
}
node->parent = l;
}
function void
decl_list_remove(Decl *l, Decl *node){
if(l->list_decl.first == l->list_decl.last){
assert(node == l->list_decl.last);
l->list_decl.first = l->list_decl.last = 0;
}
else if(l->list_decl.last == node){
l->list_decl.last = l->list_decl.last->prev;
l->list_decl.last->next = 0;
}
else if(l->list_decl.first == node){
l->list_decl.first = l->list_decl.first->next;
l->list_decl.first->prev = 0;
}
else{
node->prev->next = node->next;
node->next->prev = node->prev;
}
node->parent = 0;
node->prev = 0;
node->next = 0;
}
function void
list_print(Decl *decls){
printf("next:");
for(Decl *n = decls[0].list_decl.first; n; n=n->next){
printf("%d", n->kind);
}
printf("prev:");
for(Decl *n = decls[0].list_decl.last; n; n=n->prev){
printf("%d", n->kind);
}
printf("parent:");
for(Decl *n = decls[0].list_decl.first; n; n=n->next){
printf("%d", n->parent->kind);
}
}
function void
ast_test(){
Decl decls[16] = {0};
decls[0].kind = 9;
decls[1].kind = 1;
decls[2].kind = 2;
decls[3].kind = 3;
decls[4].kind = 4;
decl_list_push(decls, decls+1);
decl_list_push(decls, decls+2);
decl_list_push(decls, decls+3);
decl_list_push_front(decls, decls+4);
//list_print(decls);
decl_list_remove(decls, decls+1);
//list_print(decls);
decl_list_remove(decls, decls+2);
//list_print(decls);
decl_list_remove(decls, decls+3);
//list_print(decls);
decl_list_remove(decls, decls+4);
//list_print(decls);
assert(decls[0].list_decl.first == 0);
assert(decls[0].list_decl.last == 0);
}

View File

@@ -2,7 +2,8 @@ global Intern_String keyword_if;
global Intern_String keyword_for;
global Intern_String keyword_cast;
global Intern_String keyword_else;
global Intern_String keyword_sizeof;
global Intern_String keyword_size_type;
global Intern_String keyword_size_expr;
global Intern_String keyword_typeof;
global Intern_String keyword_while;
global Intern_String keyword_switch;
@@ -21,7 +22,8 @@ init_default_keywords(Intern_Table *t){
keyword_cast = intern_string(t, lit("cast"));
keyword_for = intern_string(t, lit("for"));
keyword_else = intern_string(t, lit("else"));
keyword_sizeof = intern_string(t, lit("sizeof"));
keyword_size_type = intern_string(t, lit("size_type"));
keyword_size_expr = intern_string(t, lit("size_expr"));
keyword_typeof = intern_string(t, lit("typeof"));
keyword_while = intern_string(t, lit("while"));
keyword_switch = intern_string(t, lit("switch"));
@@ -89,6 +91,7 @@ typedef enum Token_Kind{
TK_Colon,
TK_Assign,
TK_ColonAssign,
TK_DivAssign,
TK_MulAssign,
TK_ModAssign,
@@ -370,6 +373,10 @@ lex__stream(Token_Array *array, Lex_Stream *s){
lex_advance(s);
t.kind = TK_DoubleColon;
}
else if(lexc(s) == '='){
lex_advance(s);
t.kind = TK_ColonAssign;
}
else {
t.kind = TK_Colon;
}
@@ -496,7 +503,7 @@ lex_test(){
Arena *scratch = arena_begin_scratch();
String test = lit("18446744073709551616{})(@?&+-;....->,:::/**/\"Thing\"//R\n Thingy"
"\"Test_Meme\"+=-===42524 4294967295 18446744073709551615"
"for if while switch");
"for if while switch :=");
Token_Array array = lex_stream(scratch, test, lit("Test1"));
Token_Kind kind[] = {
@@ -505,7 +512,7 @@ lex_test(){
TK_ThreeDots, TK_Dot, TK_Arrow, TK_Comma, TK_DoubleColon, TK_Colon,
TK_StringLit, TK_Identifier, TK_StringLit, TK_AddAssign, TK_SubAssign,
TK_Equals, TK_Int, TK_Int, TK_Int, TK_Keyword, TK_Keyword,
TK_Keyword, TK_Keyword, TK_End
TK_Keyword, TK_Keyword, TK_ColonAssign, TK_End
};
String strs[] = {
lit("18446744073709551616"),lit("{"),lit("}"),lit(")"),lit("("),
@@ -513,7 +520,7 @@ lex_test(){
lit("..."),lit("."),lit("->"),lit(","),lit("::"),lit(":"),
lit("Thing"),lit("Thingy"),lit("Test_Meme"), lit("+="),lit("-="),
lit("=="),lit("42524"),lit("4294967295"),lit("18446744073709551615"),
lit("for"), lit("if"), lit("while"), lit("switch"), lit(""),
lit("for"), lit("if"), lit("while"), lit("switch"), lit(":="), lit(""),
};
U64 vals[] = {
42524, 4294967295, 18446744073709551615llu
@@ -563,6 +570,7 @@ global const char *token_kind_string[] = {
[TK_GreaterThen] = ">",
[TK_Colon] = ":",
[TK_Assign] = "=",
[TK_ColonAssign] = ":=",
[TK_DivAssign] = "/=",
[TK_MulAssign] = "*=",
[TK_ModAssign] = "%=",

View File

@@ -110,13 +110,15 @@ atom_expr = Int
| String
| Identifier
| 'cast' '(' typespec ',' expr ')'
| 'size_type' '(' typespec ')'
| 'size_expr' '(' expr ')'
postfix_expr = atom_expr ('[' expr ']' | '.' Identifier | ++ | -- | '(' expr_list ')')*
unary_expr = unary ? unary_expr : atom_expr
mul_expr = atom_expr (mul atom_expr)*
add_expr = mul_expr (add mul_expr)*
compare_expr = add_expr (compare add_expr)*
logical_expr = compare_expr (logical compare_expr)*
ternary_expr = logical_expr ('?' ternary_expr ':' ternary_expr)?
logical_expr = add_expr (logical add_expr)*
compare_expr = logical_expr (compare logical_expr)*
ternary_expr = compare_expr ('?' ternary_expr ':' ternary_expr)?
expr = logical_expr
*/
function Expr *parse_expr(Parser *p);
@@ -167,6 +169,51 @@ token_is_postfix(Parser *p){
return result;
}
function Expr_Compound_Field *
parse_expr_compound(Parser *p){
Token *token = token_get(p);
Expr_Compound_Field *result = 0;
if(token_match(p, TK_OpenBracket)){
Expr *index = parse_expr(p);
token_expect(p, TK_CloseBracket);
token_expect(p, TK_Assign);
Expr *expr = parse_expr(p);
result = expr_compound_index(p->arena, token, index, expr);
}
else{
Expr *expr = parse_expr(p);
if((token = token_match(p, TK_Assign))){
if(expr->kind != EK_Identifier){
parser_push_error(p, token, "Failed to parse compound literal, required identifier as left value");
}
result = expr_compound_named(p->arena, token, expr->intern_val, parse_expr(p));
}
else{
result = expr_compound_default(p->arena, token, expr);
}
}
return result;
}
function Expr_Compound_Field *
parse_expr_function_argument(Parser *p){
Token *token = token_get(p);
Expr_Compound_Field *result = 0;
Expr *expr1 = parse_expr(p);
if(token_match(p, TK_Assign)){
if(expr1->kind != EK_Identifier){
parser_push_error(p, token, "Failed to parse named function argument, required identifier as left value");
}
Expr *expr2 = parse_expr(p);
result = expr_compound_named(p->arena, token, expr1->intern_val, expr2);
}
else{
result = expr_compound_default(p->arena, token, expr1);
}
return result;
}
function Expr *
parse_expr_postfix(Parser *p){
Expr *left = parse_expr_atom(p);
@@ -180,10 +227,10 @@ parse_expr_postfix(Parser *p){
else if((token = token_match(p, TK_OpenParen))){
left = expr_call(p->arena, token, left);
if(!token_is(p, TK_CloseParen)){
expr_call_push(left, parse_expr(p));
while(token_match(p, TK_Comma)){
expr_call_push(left, parse_expr(p));
}
do {
Expr_Compound_Field *field = parse_expr_function_argument(p);
expr_call_push(left, field);
} while(token_match(p, TK_Comma));
}
token_expect(p, TK_CloseParen);
}
@@ -263,24 +310,6 @@ parse_expr_add(Parser *p){
return left;
}
function B32
token_is_compare(Parser *p){
Token *token = token_get(p);
B32 result = token->kind >= TK_FirstCompare && token->kind <= TK_LastCompare;
return result;
}
function Expr *
parse_expr_compare(Parser *p){
Expr *left = parse_expr_add(p);
while(token_is_compare(p)){
Token *op = token_next(p);
Expr *right = parse_expr_add(p);
left = expr_binary(p->arena, op, left, right);
}
return left;
}
function B32
token_is_logical(Parser *p){
Token *token = token_get(p);
@@ -290,10 +319,28 @@ token_is_logical(Parser *p){
function Expr *
parse_expr_logical(Parser *p){
Expr *left = parse_expr_compare(p);
Expr *left = parse_expr_add(p);
while(token_is_logical(p)){
Token *op = token_next(p);
Expr *right = parse_expr_compare(p);
Expr *right = parse_expr_add(p);
left = expr_binary(p->arena, op, left, right);
}
return left;
}
function B32
token_is_compare(Parser *p){
Token *token = token_get(p);
B32 result = token->kind >= TK_FirstCompare && token->kind <= TK_LastCompare;
return result;
}
function Expr *
parse_expr_compare(Parser *p){
Expr *left = parse_expr_logical(p);
while(token_is_compare(p)){
Token *op = token_next(p);
Expr *right = parse_expr_logical(p);
left = expr_binary(p->arena, op, left, right);
}
return left;
@@ -301,7 +348,7 @@ parse_expr_logical(Parser *p){
function Expr *
parse_expr_ternary(Parser *p){
Expr *cond = parse_expr_logical(p);
Expr *cond = parse_expr_compare(p);
Token *token = 0;
if((token = token_match(p, TK_Question))){
Expr *on_true = parse_expr_ternary(p);
@@ -321,11 +368,32 @@ parse_expr(Parser *p){
//-----------------------------------------------------------------------------
// Test code
//-----------------------------------------------------------------------------
function void expr_print(Expr *expr);
function void
token_print(Token *token){
printf("%.*s", (S32)token->len, token->str);
}
function void
expr_compound_print(Expr_Compound_Field *field){
switch(field->kind){
case COMPOUND_Default: {
expr_print(field->init);
}break;
case COMPOUND_Named: {
printf("[%s] = ", field->name.s.str);
expr_print(field->init);
}break;
case COMPOUND_Index: {
printf("[");
expr_print(field->index);
printf("] = ");
expr_print(field->init);
}break;
default: invalid_codepath;
}
}
function void
expr_print(Expr *expr){
switch(expr->kind) {
@@ -333,15 +401,24 @@ expr_print(Expr *expr){
token_print(expr->token);
} break;
case EK_Sizeof:{
printf("sizeof(");
if(expr->size_of.kind == SIZEOF_Expr){
expr_print(expr->size_of.expr);
}
else{
assert(expr->size_of.kind == SIZEOF_Type);
//print_typespec(expr->size_of.type);
case EK_SizeExpr:{
printf("size_expr(");
expr_print(expr->size_expr.expr);
printf(")");
}break;
case EK_Compound:{
// typespec_print(p);
printf("{");
for(Expr_Compound_Field *n = expr->compound.first; n; n=n->next){
expr_compound_print(n);
if(n!=expr->compound.last) printf(",");
}
printf("}");
} break;
case EK_SizeType:{
printf("size_type(");
printf(")");
}break;
@@ -407,8 +484,8 @@ expr_print(Expr *expr){
case EK_Call:{
expr_print(expr->call.atom);
printf("(");
for(Expr *n = expr->call.first; n; n=n->next){
expr_print(n);
for(Expr_Compound_Field *n = expr->call.first; n; n=n->next){
expr_compound_print(n);
if(n!=expr->call.last) printf(",");
}
printf(")");
@@ -474,13 +551,14 @@ parse_test(){
String test_case = lit("32+52-242*2/424%5-23"
" 1<<5>>6<<2 "
" 5*(4/3)*(2+5) "
" 0&1 == 1&0 "
" 1&&5*3 "
" 1&&5||0 "
" 1>5>=5==0 "
" 1>5 ? 1 : 2 "
" !!!!!1 "
" ~~1 + -!2 "
" 1 + ++Thing[12]++ + ++Thing[12].expr + --Not_Thing[156](Thing) + test_func(func1, func2, func3)"
" 1 + ++Thing[12]++ + ++Thing[12].expr + --Not_Thing[156](Thing) + test_func(asd=func1, af=func2, gg=func3)"
);
Parser parser = {
.tokens = lex_stream(scratch, test_case, lit("expr_test")),
@@ -493,6 +571,7 @@ parse_test(){
(32+52-242*2/424%5-23),
(((1<<5)>>6)<<2),
5*(4/3)*(2+5),
(0&1) == (1&0),
1&&(t*3),
(1&&t)||0,
1>t>=t==0,