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; } } function B32 print_typespec(Parser *p, Typespec *spec){ switch(spec->kind) { case TS_Name: { lex_print("%s", spec->name.s.str); } 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; } }