Pretty printing, parsing structs

This commit is contained in:
Krzosa Karol
2022-05-07 09:47:11 +02:00
parent 501e42be19
commit d3ede16bab
5 changed files with 475 additions and 188 deletions

View File

@@ -78,6 +78,15 @@ token_peek_is(Parser *p, Token_Kind kind, S64 i){
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 *
token_is(Parser *p, Token_Kind kind){
Token *result = token_get(p);
@@ -536,35 +545,155 @@ name::enum{}
name::typedef = name2;
name::const = 4254;
// Thing::struct{
// var1, var2: U32;
// union {
// thing: *S64;
// }
// named: union {
// data: [24]U32;
// }
// }
*/
function Decl *
parse_enum(Parser *p, Token *name){
Typespec *typespec = 0;
function void
parse_note_list(Parser *p, Note *parent) {
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)){
typespec = parse_typespec(p);
result = parse_typespec(p);
}
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);
token_expect(p, TK_OpenBrace);
do{
Note notes = parse_notes(p);
Token *val = token_expect(p, TK_Identifier);
Expr *expr = 0;
if(token_match(p, TK_Assign)){
expr = parse_expr(p);
}
decl_enum_push(p->arena, result, val, val->intern_val, expr, 0);
} while(token_is(p, TK_Comma));
Expr *expr = parse_assign_expr(p);
decl_enum_push(p->arena, result, val, val->intern_val, expr, &notes);
} while(token_match(p, TK_Comma));
token_expect(p, TK_CloseBrace);
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 *
parse_decl(Parser *p){
Decl *result = 0;
Token *name = 0;
Note note = parse_notes(p);
if((name = token_match(p, TK_Identifier))){
if(token_match(p, TK_DoubleColon)){
Token *token = 0;
@@ -572,10 +701,10 @@ parse_decl(Parser *p){
result = parse_enum(p, name);
}
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))){
// Struct
result = parse_struct(p, name, DECL_Struct);
}
else if((token = token_match_keyword(p, keyword_const))){
// Const value
@@ -591,183 +720,16 @@ parse_decl(Parser *p){
parser_push_error(p, token_get(p), "Expected token of kind '::'");
}
}
if(result){
decl_pass_notes(result, &note);
}
return result;
}
//-----------------------------------------------------------------------------
// 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
eval_expr(Expr *expr){
@@ -904,6 +866,19 @@ parse_test_expr(){
function void
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);
}
}