Parsing complete mostly, ordering, resolving, C++ tests
This commit is contained in:
434
print.c
434
print.c
@@ -1,212 +1,368 @@
|
||||
function void print_decl(Parser *p, Decl *node);
|
||||
function B32 print_typespec(Parser *p, Typespec *spec);
|
||||
function void expr_print(Expr *expr);
|
||||
function void typespec_print(Typespec *spec);
|
||||
|
||||
global S64 indent;
|
||||
|
||||
#define println(...) do{ printf("\n"); print_indent(); printf(__VA_ARGS__); }while(0)
|
||||
#define AST_CAST(item, T) T *item = (T *)item
|
||||
#define AST_IterT(parent, name, T) for(T *name = (T *)(parent)->first; name; name=(T *)name->next) // , assert(name->kind == AST_##type
|
||||
#define AST_Iter(parent,name) AST_IterT(parent,name,AST)
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
print_indent(){
|
||||
for(S64 i = 0; i < indent*2; i++)
|
||||
printf(" ");
|
||||
}
|
||||
|
||||
function void
|
||||
token_print(Token *token){
|
||||
lex_print("%.*s", (S32)token->len, token->str);
|
||||
printf("%.*s", (S32)token->len, token->str);
|
||||
}
|
||||
|
||||
function void
|
||||
expr_print(Parser *p, Expr *expr){
|
||||
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) {
|
||||
case EK_Atom: {
|
||||
case EK_Int:case EK_String:case EK_Identifier: {
|
||||
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(")");
|
||||
case EK_SizeExpr:{
|
||||
printf("sizeof(");
|
||||
expr_print(expr->size_expr.expr);
|
||||
printf(")");
|
||||
}break;
|
||||
|
||||
case EK_Binary:{
|
||||
lex_print("(");
|
||||
expr_print(p, expr->binary.left);
|
||||
token_print(expr->token);
|
||||
expr_print(p, expr->binary.right);
|
||||
lex_print(")");
|
||||
case EK_Compound:{
|
||||
if(expr->compound.typespec){
|
||||
printf("(");
|
||||
typespec_print(expr->compound.typespec);
|
||||
printf(")");
|
||||
}
|
||||
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_Unary:{
|
||||
lex_print("(");
|
||||
|
||||
case EK_SizeType:{
|
||||
printf("sizeof(");
|
||||
typespec_print(expr->size_type.typespec);
|
||||
printf(")");
|
||||
}break;
|
||||
|
||||
case EK_Paren:{
|
||||
printf("(");
|
||||
expr_print(expr->paren.expr);
|
||||
printf(")");
|
||||
} break;
|
||||
|
||||
case EK_Field:{
|
||||
expr_print(expr->field.expr);
|
||||
printf(".%s", expr->field.name.s.str);
|
||||
} break;
|
||||
|
||||
case EK_Binary:{
|
||||
printf("(");
|
||||
expr_print(expr->binary.left);
|
||||
printf("%s", token_kind_string[expr->binary.op]);
|
||||
expr_print(expr->binary.right);
|
||||
printf(")");
|
||||
} break;
|
||||
|
||||
case EK_PostfixUnary:{
|
||||
printf("(");
|
||||
expr_print(expr->unary.expr);
|
||||
token_print(expr->token);
|
||||
expr_print(p, expr->unary.expr);
|
||||
lex_print(")");
|
||||
printf(")");
|
||||
} break;
|
||||
|
||||
case EK_Unary:{
|
||||
printf("(");
|
||||
token_print(expr->token);
|
||||
expr_print(expr->unary.expr);
|
||||
printf(")");
|
||||
} 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(")");
|
||||
printf("(");
|
||||
expr_print(expr->ternary.cond);
|
||||
printf("?");
|
||||
expr_print(expr->ternary.on_true);
|
||||
printf(":");
|
||||
expr_print(expr->ternary.on_false);
|
||||
printf(")");
|
||||
} break;
|
||||
case EK_List:{
|
||||
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(")");
|
||||
printf("(");
|
||||
printf("(");
|
||||
typespec_print(expr->cast.typespec);
|
||||
printf(")");
|
||||
expr_print(expr->cast.expr);
|
||||
printf(")");
|
||||
} break;
|
||||
|
||||
case EK_Index:{
|
||||
expr_print(p, expr->index.atom);
|
||||
lex_print("[");
|
||||
expr_print(p, expr->index.index);
|
||||
lex_print("]");
|
||||
expr_print(expr->index.atom);
|
||||
printf("[");
|
||||
expr_print(expr->index.index);
|
||||
printf("]");
|
||||
}break;
|
||||
|
||||
case EK_Call:{
|
||||
expr_print(p, expr->call.atom);
|
||||
lex_print("(");
|
||||
expr_print(p, expr->call.list);
|
||||
lex_print(")");
|
||||
expr_print(expr->call.atom);
|
||||
printf("(");
|
||||
for(Expr_Compound_Field *n = expr->call.first; n; n=n->next){
|
||||
expr_compound_print(n);
|
||||
if(n!=expr->call.last) printf(",");
|
||||
}
|
||||
printf(")");
|
||||
}break;
|
||||
default: {invalid_codepath;} break;
|
||||
}
|
||||
}
|
||||
|
||||
function B32
|
||||
print_typespec(Parser *p, Typespec *spec){
|
||||
function void
|
||||
typespec_print(Typespec *spec){
|
||||
switch(spec->kind) {
|
||||
case TS_Name: {
|
||||
lex_print("%s", spec->name.s.str);
|
||||
printf("%s", spec->name.s.str);
|
||||
} break;
|
||||
|
||||
case TS_NamedArgument: {
|
||||
printf("%s: ", spec->named.name.s.str);
|
||||
typespec_print(spec->named.base);
|
||||
}break;
|
||||
|
||||
case TS_Pointer: {
|
||||
print_typespec(p, spec->base);
|
||||
lex_print("*");
|
||||
typespec_print(spec->base);
|
||||
printf("*");
|
||||
} break;
|
||||
|
||||
case TS_Array: {
|
||||
print_typespec(p, spec->array_spec.base);
|
||||
lex_print("[");
|
||||
expr_print(p, spec->array_spec.size);
|
||||
lex_print("]");
|
||||
typespec_print(spec->arr.base);
|
||||
printf("[");
|
||||
expr_print(spec->arr.size);
|
||||
printf("]");
|
||||
} 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(", ");
|
||||
printf("(");
|
||||
for(Typespec *n = spec->func.first; n; n=n->next){
|
||||
typespec_print(n);
|
||||
if(n!=spec->func.last)
|
||||
printf(", ");
|
||||
}
|
||||
|
||||
lex_print(")");
|
||||
print_typespec(p,spec->function_spec.ret);
|
||||
printf(")");
|
||||
typespec_print(spec->func.ret);
|
||||
} break;
|
||||
default: {invalid_codepath;} break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function void
|
||||
print_assign_expr(Parser *p, Expr *expr){
|
||||
print_assign_expr(Expr *expr){
|
||||
if(expr){
|
||||
lex_print(" = ");
|
||||
expr_print(p, expr);
|
||||
printf(" = ");
|
||||
expr_print(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();
|
||||
ast_print(AST *in){
|
||||
switch(in->kind) {
|
||||
case AST_Program: {
|
||||
Program *node = (Program *)in;
|
||||
for(AST *n = node->first; n; n=n->next){
|
||||
ast_print(n);
|
||||
printf("\n");
|
||||
}
|
||||
} 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(";");
|
||||
case AST_Decl_Const:
|
||||
case AST_Decl_Var:{
|
||||
Decl_Var *node = (Decl_Var *)in;
|
||||
println("");
|
||||
if(node->typespec) typespec_print(node->typespec);
|
||||
printf(" %s", node->name.s.str);
|
||||
print_assign_expr(node->expr);
|
||||
} break;
|
||||
|
||||
case DECL_Typedef:{
|
||||
lex_print("typedef %s ", node->name.s.str);
|
||||
print_typespec(p, node->typedef_decl.type);
|
||||
lex_print(";");
|
||||
case AST_Decl_Typedef:{
|
||||
Decl_Typedef *node = (Decl_Typedef *)in;
|
||||
println("typedef %s ", node->name.s.str);
|
||||
typespec_print(node->typespec);
|
||||
printf(";");
|
||||
} 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");
|
||||
case AST_Decl_Func:{
|
||||
Decl_Func *node = (Decl_Func *)in;
|
||||
println("function ");
|
||||
typespec_print(node->ret);
|
||||
printf("\n%s", node->name.s.str);
|
||||
printf("(");
|
||||
AST_IterT(node, arg, Decl_Func_Arg){
|
||||
typespec_print(arg->typespec);
|
||||
printf(" %s", arg->name.s.str);
|
||||
if((AST *)arg != node->last)
|
||||
printf(", ");
|
||||
}
|
||||
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");
|
||||
printf(")");
|
||||
if(!node->is_incomplete){
|
||||
ast_print((AST *)node->body);
|
||||
}
|
||||
lex_print("};\n");
|
||||
} break;
|
||||
|
||||
case AST_Decl_Struct:
|
||||
case AST_Decl_Union :{
|
||||
Decl_Struct *node = (Decl_Struct *)in;
|
||||
const char *struct_name = node->kind==AST_Decl_Struct ? "struct" : "union";
|
||||
println("%s %s{", struct_name, node->name.s.str?(char*)node->name.s.str:"");
|
||||
indent++;
|
||||
for(AST *n = node->first; n; n=n->next){
|
||||
ast_print(n);
|
||||
printf(";");
|
||||
}
|
||||
indent--;
|
||||
println("};");
|
||||
} break;
|
||||
|
||||
case AST_Decl_SubStruct:
|
||||
case AST_Decl_SubUnion :{
|
||||
Decl_Struct *node = (Decl_Struct *)in;
|
||||
const char *struct_name = node->kind==AST_Decl_Struct ? "struct" : "union";
|
||||
println("%s %s{", struct_name, node->name.s.str?(char*)node->name.s.str:"");
|
||||
indent++;
|
||||
for(AST *n = node->first; n; n=n->next){
|
||||
ast_print(n);
|
||||
}
|
||||
indent--;
|
||||
println("};");
|
||||
} break;
|
||||
|
||||
case AST_Decl_Enum:{
|
||||
Decl_Enum *node = (Decl_Enum *)in;
|
||||
println("enum %s : ", node->name.s.str);
|
||||
typespec_print(node->typespec);
|
||||
printf("{");
|
||||
indent++;
|
||||
AST_IterT(node, n, Decl_Enum_Child){
|
||||
//print_notes(p, n->first_note);
|
||||
println("%s", n->name.s.str);
|
||||
print_assign_expr(n->expr);
|
||||
printf(",");
|
||||
}
|
||||
indent--;
|
||||
println("};");
|
||||
} break;
|
||||
|
||||
case AST_Stmt_Init:{
|
||||
Stmt_Init *node = (Stmt_Init *)in;
|
||||
if(node->typespec) typespec_print(node->typespec);
|
||||
printf(" %s", node->name.s.str);
|
||||
print_assign_expr(node->expr);
|
||||
}break;
|
||||
|
||||
case AST_Stmt_Assign:{
|
||||
Stmt_Assign *node = (Stmt_Assign *)in;
|
||||
expr_print(node->left);
|
||||
token_print(node->pos);
|
||||
expr_print(node->right);
|
||||
}break;
|
||||
|
||||
case AST_Stmt_Expr:{
|
||||
Stmt_Expr *node = (Stmt_Expr *)in;
|
||||
expr_print(node->expr);
|
||||
}break;
|
||||
|
||||
case AST_Stmt_Defer:{
|
||||
Stmt_Defer *node = (Stmt_Defer *)in;
|
||||
printf("defer ");
|
||||
ast_print((AST *)node->body);
|
||||
}break;
|
||||
|
||||
case AST_Stmt_Return:{
|
||||
Stmt_Return *node = (Stmt_Return *)in;
|
||||
printf("return ");
|
||||
expr_print(node->expr);
|
||||
}break;
|
||||
|
||||
case AST_Stmt_Block:{
|
||||
Stmt_Block *node = (Stmt_Block *)in;
|
||||
printf(" {");
|
||||
indent++;
|
||||
AST_IterT(node, n, AST){
|
||||
println("");
|
||||
ast_print(n);
|
||||
if(n->kind != AST_Stmt_If && n->kind != AST_Stmt_For && n->kind != AST_Stmt_Else &&
|
||||
n->kind != AST_Stmt_ElseIf)
|
||||
printf(";");
|
||||
}
|
||||
indent--;
|
||||
println("}");
|
||||
}break;
|
||||
|
||||
|
||||
case AST_Stmt_Else:{
|
||||
Stmt_Else *node = (Stmt_Else *)in;
|
||||
printf("else ");
|
||||
ast_print((AST *)node->body);
|
||||
}break;
|
||||
|
||||
case AST_Stmt_ElseIf:{
|
||||
Stmt_ElseIf *node = (Stmt_ElseIf *)in;
|
||||
printf("else if ");
|
||||
expr_print(node->condition);
|
||||
ast_print((AST *)node->body);
|
||||
}break;
|
||||
|
||||
case AST_Stmt_If:{
|
||||
Stmt_If *node = (Stmt_If *)in;
|
||||
printf("if ");
|
||||
expr_print(node->condition);
|
||||
ast_print((AST *)node->body);
|
||||
AST_IterT(node, n, AST){
|
||||
ast_print(n);
|
||||
}
|
||||
}break;
|
||||
|
||||
case AST_Stmt_For:{
|
||||
Stmt_For *node = (Stmt_For *)in;
|
||||
printf("for(");
|
||||
if(node->on_begin) ast_print(node->on_begin);
|
||||
printf(";");
|
||||
if(node->condition) expr_print(node->condition);
|
||||
printf(";");
|
||||
if(node->on_iter) ast_print(node->on_iter);
|
||||
printf(")");
|
||||
ast_print((AST *)node->body);
|
||||
}break;
|
||||
|
||||
default: {invalid_codepath;} break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user