Pretty printing, parsing structs
This commit is contained in:
@@ -2,5 +2,5 @@
|
|||||||
|
|
||||||
rem clang generate.c -fdiagnostics-absolute-paths -std=c99 -g -o generate.exe -Wl,user32.lib
|
rem clang generate.c -fdiagnostics-absolute-paths -std=c99 -g -o generate.exe -Wl,user32.lib
|
||||||
rem generate.exe
|
rem generate.exe
|
||||||
clang main.c -Wall -Wno-unused-function -fdiagnostics-absolute-paths -std=c99 -g -o main.exe -Wl,user32.lib
|
clang main.c -Wall -Wno-unused-function -fdiagnostics-absolute-paths -std=c17 -g -o main.exe -Wl,user32.lib
|
||||||
rem cl main.c -std:c17
|
rem cl main.c -std:c17
|
||||||
|
|||||||
1
main.c
1
main.c
@@ -13,6 +13,7 @@
|
|||||||
|
|
||||||
#include "new_lex.c"
|
#include "new_lex.c"
|
||||||
#include "new_ast.c"
|
#include "new_ast.c"
|
||||||
|
#include "new_print.c"
|
||||||
#include "new_parse.c"
|
#include "new_parse.c"
|
||||||
|
|
||||||
int main(){
|
int main(){
|
||||||
|
|||||||
54
new_ast.c
54
new_ast.c
@@ -164,6 +164,8 @@ typedef enum Decl_Kind{
|
|||||||
DECL_None,
|
DECL_None,
|
||||||
DECL_Struct,
|
DECL_Struct,
|
||||||
DECL_Union,
|
DECL_Union,
|
||||||
|
DECL_SubStruct,
|
||||||
|
DECL_SubUnion,
|
||||||
DECL_Enum,
|
DECL_Enum,
|
||||||
DECL_Variable,
|
DECL_Variable,
|
||||||
DECL_Typedef,
|
DECL_Typedef,
|
||||||
@@ -497,6 +499,54 @@ function void
|
|||||||
typespec_function_push(Typespec *func, Typespec *arg){
|
typespec_function_push(Typespec *func, Typespec *arg){
|
||||||
SLLQueuePush(func->func.first, func->func.last, arg);
|
SLLQueuePush(func->func.first, func->func.last, arg);
|
||||||
}
|
}
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Notes
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
function void
|
||||||
|
decl_pass_notes(Decl *a, Note *b){
|
||||||
|
a->first_note = b->first;
|
||||||
|
a->last_note = b->last;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Note *
|
||||||
|
note_push_new(Arena *p, Note *parent, Token *pos, Intern_String name, Expr *expr){
|
||||||
|
Note *result = arena_push_struct(p, Note);
|
||||||
|
result->pos = pos;
|
||||||
|
result->name = name;
|
||||||
|
result->expr = expr;
|
||||||
|
SLLQueuePush(parent->first, parent->last, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Note *
|
||||||
|
find_note(Note *first, String string){
|
||||||
|
for(Note *n = first; n; n=n->next){
|
||||||
|
if(string_compare(string, n->name.s)){
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function String
|
||||||
|
find_string_note(Note *first, String string, String default_string){
|
||||||
|
Note *note = find_note(first, string);
|
||||||
|
if(note){
|
||||||
|
return note->expr->token->intern_val.s;
|
||||||
|
}
|
||||||
|
return default_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Note *
|
||||||
|
decl_find_note(Decl *decl, String string){
|
||||||
|
return find_note(decl->first_note, string);
|
||||||
|
}
|
||||||
|
|
||||||
|
function String
|
||||||
|
decl_find_string_note(Decl *decl, String string, String default_string){
|
||||||
|
return find_string_note(decl->first_note, string, default_string);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Declarations
|
// Declarations
|
||||||
@@ -512,7 +562,7 @@ decl_new(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){
|
|||||||
|
|
||||||
function Decl *
|
function Decl *
|
||||||
decl_struct(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){
|
decl_struct(Arena *p, Decl_Kind kind, Token *pos, Intern_String name){
|
||||||
assert(kind == DECL_Struct || kind == DECL_Union);
|
assert(kind == DECL_Struct || kind == DECL_Union || kind == DECL_SubUnion || kind == DECL_SubStruct);
|
||||||
Decl *result = decl_new(p, kind, pos, name);
|
Decl *result = decl_new(p, kind, pos, name);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
@@ -570,7 +620,7 @@ decl_enum_push(Arena *p, Decl *parent, Token *pos, Intern_String name, Expr *exp
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
decl_struct_push(Decl *parent, Decl *child){
|
decl_struct_push(Decl *parent, Decl *child){
|
||||||
assert(parent->kind == DECL_Struct || parent->kind == DECL_Union);
|
assert(parent->kind == DECL_Struct || parent->kind == DECL_Union || parent->kind == DECL_SubUnion || parent->kind == DECL_SubStruct);
|
||||||
SLLQueuePush(parent->struct_decl.first, parent->struct_decl.last, child);
|
SLLQueuePush(parent->struct_decl.first, parent->struct_decl.last, child);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
345
new_parse.c
345
new_parse.c
@@ -78,6 +78,15 @@ token_peek_is(Parser *p, Token_Kind kind, S64 i){
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function Token *
|
||||||
|
token_peek_is_keyword(Parser *p, Intern_String keyword, S64 i){
|
||||||
|
assert(lex_is_keyword(keyword));
|
||||||
|
Token *result = token_peek(p, i);
|
||||||
|
if(result->kind == TK_Keyword && intern_compare(result->intern_val, keyword))
|
||||||
|
return result;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
function Token *
|
function Token *
|
||||||
token_is(Parser *p, Token_Kind kind){
|
token_is(Parser *p, Token_Kind kind){
|
||||||
Token *result = token_get(p);
|
Token *result = token_get(p);
|
||||||
@@ -536,35 +545,155 @@ name::enum{}
|
|||||||
name::typedef = name2;
|
name::typedef = name2;
|
||||||
name::const = 4254;
|
name::const = 4254;
|
||||||
|
|
||||||
|
// Thing::struct{
|
||||||
|
// var1, var2: U32;
|
||||||
|
// union {
|
||||||
|
// thing: *S64;
|
||||||
|
// }
|
||||||
|
// named: union {
|
||||||
|
// data: [24]U32;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
*/
|
*/
|
||||||
function Decl *
|
function void
|
||||||
parse_enum(Parser *p, Token *name){
|
parse_note_list(Parser *p, Note *parent) {
|
||||||
Typespec *typespec = 0;
|
if(token_match(p, TK_OpenParen)) {
|
||||||
|
if(token_match(p, TK_CloseParen)){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
do {
|
||||||
|
Token *name = token_expect(p, TK_Identifier);
|
||||||
|
Note *current = note_push_new(p->arena, parent, name, name->intern_val, 0);
|
||||||
|
parse_note_list(p, current);
|
||||||
|
if(token_match(p, TK_Assign)) {
|
||||||
|
current->expr = parse_expr(p);
|
||||||
|
}
|
||||||
|
} while(token_match(p, TK_Comma));
|
||||||
|
token_expect(p, TK_CloseParen);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
parse__notes(Parser *p, Note *result) {
|
||||||
|
while(token_match(p, TK_At)) {
|
||||||
|
Token *name = token_expect(p, TK_Identifier);
|
||||||
|
Note *current = note_push_new(p->arena, result, name, name->intern_val, 0);
|
||||||
|
parse_note_list(p, current);
|
||||||
|
if(token_match(p, TK_Assign)) {
|
||||||
|
current->expr = parse_expr(p);
|
||||||
|
}
|
||||||
|
token_match(p, TK_Semicolon);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Note
|
||||||
|
parse_notes(Parser *p){
|
||||||
|
Note result = {0};
|
||||||
|
parse__notes(p, &result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Expr *
|
||||||
|
parse_assign_expr(Parser *p){
|
||||||
|
if(token_match(p, TK_Assign))
|
||||||
|
return parse_expr(p);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Typespec *
|
||||||
|
parse_optional_type(Parser *p){
|
||||||
|
Typespec *result = 0;
|
||||||
if(token_match(p, TK_Colon)){
|
if(token_match(p, TK_Colon)){
|
||||||
typespec = parse_typespec(p);
|
result = parse_typespec(p);
|
||||||
}
|
}
|
||||||
else{
|
else{
|
||||||
typespec = typespec_name(p->arena, token_get(p), intern_int);
|
result = typespec_name(p->arena, token_get(p), intern_int);
|
||||||
}
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
function Decl *
|
||||||
|
parse_enum(Parser *p, Token *name){
|
||||||
|
Typespec *typespec = parse_optional_type(p);
|
||||||
Decl *result = decl_enum(p->arena, name, name->intern_val, typespec);
|
Decl *result = decl_enum(p->arena, name, name->intern_val, typespec);
|
||||||
token_expect(p, TK_OpenBrace);
|
token_expect(p, TK_OpenBrace);
|
||||||
do{
|
do{
|
||||||
|
Note notes = parse_notes(p);
|
||||||
Token *val = token_expect(p, TK_Identifier);
|
Token *val = token_expect(p, TK_Identifier);
|
||||||
Expr *expr = 0;
|
Expr *expr = parse_assign_expr(p);
|
||||||
if(token_match(p, TK_Assign)){
|
decl_enum_push(p->arena, result, val, val->intern_val, expr, ¬es);
|
||||||
expr = parse_expr(p);
|
} while(token_match(p, TK_Comma));
|
||||||
}
|
|
||||||
decl_enum_push(p->arena, result, val, val->intern_val, expr, 0);
|
|
||||||
} while(token_is(p, TK_Comma));
|
|
||||||
token_expect(p, TK_CloseBrace);
|
token_expect(p, TK_CloseBrace);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
parse_var_decl(Parser *p, Decl *parent, Token *name){
|
||||||
|
Token *name_stack[64];
|
||||||
|
S64 name_stack_len = 0;
|
||||||
|
name_stack[name_stack_len++] = name;
|
||||||
|
while(token_match(p, TK_Comma))
|
||||||
|
name_stack[name_stack_len++] = token_expect(p, TK_Identifier);
|
||||||
|
token_expect(p, TK_Colon);
|
||||||
|
Typespec *typespec = parse_typespec(p);
|
||||||
|
token_expect(p, TK_Semicolon);
|
||||||
|
for(S64 i = 0; i < name_stack_len; i++){
|
||||||
|
Decl *decl = decl_variable(p->arena, name_stack[i], name_stack[i]->intern_val, typespec, 0);
|
||||||
|
decl_struct_push(parent, decl);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function Decl *
|
||||||
|
parse_struct(Parser *p, Token *name, Decl_Kind struct_kind){
|
||||||
|
Intern_String intern_name = name ? name->intern_val : (Intern_String){0};
|
||||||
|
Token *token = name ? name : token_get(p);
|
||||||
|
Decl *result = decl_struct(p->arena, struct_kind, token, intern_name);
|
||||||
|
token_expect(p, TK_OpenBrace);
|
||||||
|
do {
|
||||||
|
Token *token = token_get(p);
|
||||||
|
if(token_match_keyword(p, keyword_union)){
|
||||||
|
Decl *decl = parse_struct(p, 0, DECL_SubUnion);
|
||||||
|
decl_struct_push(result, decl);
|
||||||
|
}
|
||||||
|
else if(token_match_keyword(p, keyword_struct)){
|
||||||
|
Decl *decl = parse_struct(p, 0, DECL_SubStruct);
|
||||||
|
decl_struct_push(result, decl);
|
||||||
|
}
|
||||||
|
else if(token_match(p, TK_Identifier)){
|
||||||
|
if(token_is(p, TK_Colon)){
|
||||||
|
if(token_peek_is_keyword(p, keyword_union, 1)){
|
||||||
|
token_next(p);
|
||||||
|
token_next(p);
|
||||||
|
Decl *decl = parse_struct(p, token, DECL_SubUnion);
|
||||||
|
decl_struct_push(result, decl);
|
||||||
|
}
|
||||||
|
else if(token_peek_is_keyword(p, keyword_struct, 1)){
|
||||||
|
token_next(p);
|
||||||
|
token_next(p);
|
||||||
|
Decl *decl = parse_struct(p, token, DECL_SubStruct);
|
||||||
|
decl_struct_push(result, decl);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
parse_var_decl(p, result, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
parse_var_decl(p, result, token);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
parser_push_error(p, token, "Failed to parse struct, unexpected token of kind '%s'", token_kind_string[token->kind]);
|
||||||
|
}
|
||||||
|
} while(!token_match(p, TK_CloseBrace));
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
function Decl *
|
function Decl *
|
||||||
parse_decl(Parser *p){
|
parse_decl(Parser *p){
|
||||||
Decl *result = 0;
|
Decl *result = 0;
|
||||||
Token *name = 0;
|
Token *name = 0;
|
||||||
|
Note note = parse_notes(p);
|
||||||
if((name = token_match(p, TK_Identifier))){
|
if((name = token_match(p, TK_Identifier))){
|
||||||
if(token_match(p, TK_DoubleColon)){
|
if(token_match(p, TK_DoubleColon)){
|
||||||
Token *token = 0;
|
Token *token = 0;
|
||||||
@@ -572,10 +701,10 @@ parse_decl(Parser *p){
|
|||||||
result = parse_enum(p, name);
|
result = parse_enum(p, name);
|
||||||
}
|
}
|
||||||
else if((token = token_match_keyword(p, keyword_union))){
|
else if((token = token_match_keyword(p, keyword_union))){
|
||||||
// Union
|
result = parse_struct(p, name, DECL_Union);
|
||||||
}
|
}
|
||||||
else if((token = token_match_keyword(p, keyword_struct))){
|
else if((token = token_match_keyword(p, keyword_struct))){
|
||||||
// Struct
|
result = parse_struct(p, name, DECL_Struct);
|
||||||
}
|
}
|
||||||
else if((token = token_match_keyword(p, keyword_const))){
|
else if((token = token_match_keyword(p, keyword_const))){
|
||||||
// Const value
|
// Const value
|
||||||
@@ -591,183 +720,16 @@ parse_decl(Parser *p){
|
|||||||
parser_push_error(p, token_get(p), "Expected token of kind '::'");
|
parser_push_error(p, token_get(p), "Expected token of kind '::'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if(result){
|
||||||
|
decl_pass_notes(result, ¬e);
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
// Test code
|
// Test code
|
||||||
//-----------------------------------------------------------------------------
|
//-----------------------------------------------------------------------------
|
||||||
function void expr_print(Expr *expr);
|
|
||||||
function B32 typespec_print(Typespec *spec);
|
|
||||||
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) {
|
|
||||||
case EK_Int:case EK_String:case EK_Identifier: {
|
|
||||||
token_print(expr->token);
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case EK_SizeExpr:{
|
|
||||||
printf("size_expr(");
|
|
||||||
expr_print(expr->size_expr.expr);
|
|
||||||
printf(")");
|
|
||||||
}break;
|
|
||||||
|
|
||||||
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_SizeType:{
|
|
||||||
printf("size_type(");
|
|
||||||
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);
|
|
||||||
token_print(expr->token);
|
|
||||||
expr_print(expr->binary.right);
|
|
||||||
printf(")");
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case EK_PostfixUnary:{
|
|
||||||
printf("(");
|
|
||||||
expr_print(expr->unary.expr);
|
|
||||||
token_print(expr->token);
|
|
||||||
printf(")");
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case EK_Unary:{
|
|
||||||
printf("(");
|
|
||||||
token_print(expr->token);
|
|
||||||
expr_print(expr->unary.expr);
|
|
||||||
printf(")");
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case EK_Ternary:{
|
|
||||||
printf("(");
|
|
||||||
expr_print(expr->ternary.cond);
|
|
||||||
printf("?");
|
|
||||||
expr_print(expr->ternary.on_true);
|
|
||||||
printf(":");
|
|
||||||
expr_print(expr->ternary.on_false);
|
|
||||||
printf(")");
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case EK_Cast:{
|
|
||||||
printf("(");
|
|
||||||
printf("(");
|
|
||||||
typespec_print(expr->cast.typespec);
|
|
||||||
printf(")");
|
|
||||||
expr_print(expr->cast.expr);
|
|
||||||
printf(")");
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case EK_Index:{
|
|
||||||
expr_print(expr->index.atom);
|
|
||||||
printf("[");
|
|
||||||
expr_print(expr->index.index);
|
|
||||||
printf("]");
|
|
||||||
}break;
|
|
||||||
|
|
||||||
case EK_Call:{
|
|
||||||
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
|
|
||||||
typespec_print(Typespec *spec){
|
|
||||||
switch(spec->kind) {
|
|
||||||
case TS_Name: {
|
|
||||||
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: {
|
|
||||||
typespec_print(spec->base);
|
|
||||||
printf("*");
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case TS_Array: {
|
|
||||||
typespec_print(spec->arr.base);
|
|
||||||
printf("[");
|
|
||||||
expr_print(spec->arr.size);
|
|
||||||
printf("]");
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case TS_Function: {
|
|
||||||
printf("(");
|
|
||||||
for(Typespec *n = spec->func.first; n; n=n->next){
|
|
||||||
typespec_print(n);
|
|
||||||
if(n!=spec->func.last)
|
|
||||||
printf(", ");
|
|
||||||
}
|
|
||||||
|
|
||||||
printf(")");
|
|
||||||
typespec_print(spec->func.ret);
|
|
||||||
} break;
|
|
||||||
default: {invalid_codepath;} break;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
function S64
|
function S64
|
||||||
eval_expr(Expr *expr){
|
eval_expr(Expr *expr){
|
||||||
@@ -904,6 +866,19 @@ parse_test_expr(){
|
|||||||
|
|
||||||
function void
|
function void
|
||||||
parse_test_decls(){
|
parse_test_decls(){
|
||||||
|
Arena *scratch = arena_begin_scratch();
|
||||||
|
Parser p = parser_make(scratch);
|
||||||
|
|
||||||
|
String decls[] = {
|
||||||
|
lit("Thing::enum: U64{ Thing_1 = 1<<1, Thing_2 = 2 }"),
|
||||||
|
lit("Struct::struct{ thing, thing2: *S64; struct { thing:U32; thing2: [64]Vec2; } inner: struct {i:U32;} }"),
|
||||||
|
};
|
||||||
|
for(SizeU i = 0; i < buff_cap(decls); i++){
|
||||||
|
parser_restream(&p, decls[i], lit("Decl_Test"));
|
||||||
|
Decl *decl = parse_decl(&p);
|
||||||
|
assert(decl);
|
||||||
|
decl_print(decl);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
261
new_print.c
Normal file
261
new_print.c
Normal file
@@ -0,0 +1,261 @@
|
|||||||
|
function void expr_print(Expr *expr);
|
||||||
|
function B32 typespec_print(Typespec *spec);
|
||||||
|
|
||||||
|
global S64 indent;
|
||||||
|
|
||||||
|
#define println(...) do{ printf("\n"); print_indent(); printf(__VA_ARGS__); }while(0)
|
||||||
|
|
||||||
|
function void
|
||||||
|
print_indent(){
|
||||||
|
for(S64 i = 0; i < indent*2; i++)
|
||||||
|
printf(" ");
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
case EK_Int:case EK_String:case EK_Identifier: {
|
||||||
|
token_print(expr->token);
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case EK_SizeExpr:{
|
||||||
|
printf("size_expr(");
|
||||||
|
expr_print(expr->size_expr.expr);
|
||||||
|
printf(")");
|
||||||
|
}break;
|
||||||
|
|
||||||
|
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_SizeType:{
|
||||||
|
printf("size_type(");
|
||||||
|
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);
|
||||||
|
token_print(expr->token);
|
||||||
|
expr_print(expr->binary.right);
|
||||||
|
printf(")");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case EK_PostfixUnary:{
|
||||||
|
printf("(");
|
||||||
|
expr_print(expr->unary.expr);
|
||||||
|
token_print(expr->token);
|
||||||
|
printf(")");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case EK_Unary:{
|
||||||
|
printf("(");
|
||||||
|
token_print(expr->token);
|
||||||
|
expr_print(expr->unary.expr);
|
||||||
|
printf(")");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case EK_Ternary:{
|
||||||
|
printf("(");
|
||||||
|
expr_print(expr->ternary.cond);
|
||||||
|
printf("?");
|
||||||
|
expr_print(expr->ternary.on_true);
|
||||||
|
printf(":");
|
||||||
|
expr_print(expr->ternary.on_false);
|
||||||
|
printf(")");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case EK_Cast:{
|
||||||
|
printf("(");
|
||||||
|
printf("(");
|
||||||
|
typespec_print(expr->cast.typespec);
|
||||||
|
printf(")");
|
||||||
|
expr_print(expr->cast.expr);
|
||||||
|
printf(")");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case EK_Index:{
|
||||||
|
expr_print(expr->index.atom);
|
||||||
|
printf("[");
|
||||||
|
expr_print(expr->index.index);
|
||||||
|
printf("]");
|
||||||
|
}break;
|
||||||
|
|
||||||
|
case EK_Call:{
|
||||||
|
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
|
||||||
|
typespec_print(Typespec *spec){
|
||||||
|
switch(spec->kind) {
|
||||||
|
case TS_Name: {
|
||||||
|
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: {
|
||||||
|
typespec_print(spec->base);
|
||||||
|
printf("*");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TS_Array: {
|
||||||
|
typespec_print(spec->arr.base);
|
||||||
|
printf("[");
|
||||||
|
expr_print(spec->arr.size);
|
||||||
|
printf("]");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case TS_Function: {
|
||||||
|
printf("(");
|
||||||
|
for(Typespec *n = spec->func.first; n; n=n->next){
|
||||||
|
typespec_print(n);
|
||||||
|
if(n!=spec->func.last)
|
||||||
|
printf(", ");
|
||||||
|
}
|
||||||
|
|
||||||
|
printf(")");
|
||||||
|
typespec_print(spec->func.ret);
|
||||||
|
} break;
|
||||||
|
default: {invalid_codepath;} break;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
print_assign_expr(Expr *expr){
|
||||||
|
if(expr){
|
||||||
|
printf(" = ");
|
||||||
|
expr_print(expr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function void
|
||||||
|
decl_print(Decl *node){
|
||||||
|
//print_notes(p, node->first_note);
|
||||||
|
|
||||||
|
switch(node->kind) {
|
||||||
|
|
||||||
|
case DECL_List: {
|
||||||
|
for(Decl *n = node->list_decl.first; n; n=n->next){
|
||||||
|
decl_print(n);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DECL_Variable:{
|
||||||
|
println("%s: ", node->name.s.str);
|
||||||
|
B32 r = typespec_print(node->var_decl.type);
|
||||||
|
print_assign_expr(node->var_decl.expr);
|
||||||
|
if(r) printf(";");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DECL_Typedef:{
|
||||||
|
println("typedef %s ", node->name.s.str);
|
||||||
|
typespec_print(node->typedef_decl.type);
|
||||||
|
printf(";");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
|
||||||
|
case DECL_Struct:
|
||||||
|
case DECL_Union :{
|
||||||
|
const char *struct_name = node->kind==DECL_Struct ? "struct" : "union";
|
||||||
|
println("%s %s{", struct_name, node->name.s.str?(char*)node->name.s.str:"");
|
||||||
|
indent++;
|
||||||
|
for(Decl *n = node->struct_decl.first; n; n=n->next){
|
||||||
|
decl_print(n);
|
||||||
|
}
|
||||||
|
indent--;
|
||||||
|
println("};");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case DECL_SubStruct:
|
||||||
|
case DECL_SubUnion :{
|
||||||
|
const char *struct_name = node->kind==DECL_SubStruct ? "struct" : "union";
|
||||||
|
println("%s %s{", struct_name, node->name.s.str?(char*)node->name.s.str:"");
|
||||||
|
indent++;
|
||||||
|
for(Decl *n = node->struct_decl.first; n; n=n->next){
|
||||||
|
decl_print(n);
|
||||||
|
}
|
||||||
|
indent--;
|
||||||
|
println("};");
|
||||||
|
} break;
|
||||||
|
|
||||||
|
|
||||||
|
case DECL_Enum:{
|
||||||
|
println("enum %s : ", node->name.s.str);
|
||||||
|
typespec_print(node->enum_decl.typespec);
|
||||||
|
printf("{");
|
||||||
|
indent++;
|
||||||
|
for(Decl_Enum_Child *n = node->enum_decl.first; n; n=n->next){
|
||||||
|
//print_notes(p, n->first_note);
|
||||||
|
println("%s", n->name.s.str);
|
||||||
|
print_assign_expr(n->expr);
|
||||||
|
printf(",");
|
||||||
|
}
|
||||||
|
indent--;
|
||||||
|
println("};");
|
||||||
|
} break;
|
||||||
|
default: {invalid_codepath;} break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user