harec

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

commit 54c3867be78c112abbaf77e08dd561c3b9db48e6
parent 7a275078087af0782ffed4c1cc7871aa986646eb
Author: Eyal Sawady <ecs@d2evs.net>
Date:   Fri, 25 Dec 2020 17:10:58 -0500

parse: implement struct and union types

Diffstat:
Minclude/ast.h | 17+++++++++++++++--
Msrc/parse.c | 88++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-
2 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/include/ast.h b/include/ast.h @@ -62,10 +62,23 @@ struct ast_tagged_union_type { struct ast_tagged_union_type *next; }; +enum struct_union_member_type { + MEMBER_TYPE_FIELD, + MEMBER_TYPE_EMBEDDED, + MEMBER_TYPE_ALIAS, +}; + struct ast_struct_union_type { - const char *name; - struct ast_type *type; + enum struct_union_member_type member_type; struct ast_struct_union_type *next; + union { + struct { + char *name; + struct ast_type *type; + } field; + struct ast_type *embedded; + struct identifier alias; + }; }; struct ast_type { diff --git a/src/parse.c b/src/parse.c @@ -367,6 +367,90 @@ parse_enum_type(struct parser *par) if (lex(par->lex, &tok) != T_RBRACE) { unlex(par->lex, &tok); } + break; + case T_RBRACE: + break; + default: + synassert(false, &tok, T_COMMA, T_RBRACE, T_EOF); + } + } + trleave(TR_PARSE, NULL); + return type; +} + +static struct ast_type * +parse_struct_union_type(struct parser *par) +{ + struct token tok = {0}; + struct ast_type *type = xcalloc(sizeof(struct ast_type), 1); + struct ast_struct_union_type *next; + switch (lex(par->lex, &tok)) { + case T_STRUCT: + trenter(TR_PARSE, "struct"); + type->storage = TYPE_STORAGE_STRUCT; + next = &type->_struct; + break; + case T_UNION: + trenter(TR_PARSE, "union"); + type->storage = TYPE_STORAGE_UNION; + next = &type->_union; + break; + default: + synassert(false, &tok, T_STRUCT, T_UNION, T_EOF); + break; + } + want(par, T_LBRACE, NULL); + while (tok.token != T_RBRACE) { + char *name; + switch (lex(par->lex, &tok)) { + case T_NAME: + name = tok.name; + struct identifier *i; + switch (lex(par->lex, &tok)) { + case T_COLON: + next->member_type = MEMBER_TYPE_FIELD; + next->field.name = name; + next->field.type = parse_type(par); + trace(TR_PARSE, "%s: [type]", name); + break; + case T_DOUBLE_COLON: + next->member_type = MEMBER_TYPE_ALIAS; + i = &next->alias; + parse_identifier(par, i); + while (i->ns != NULL) { + i = i->ns; + } + i->ns = xcalloc(sizeof(struct identifier), 1); + i->ns->name = name; + trace(TR_PARSE, "[embedded alias %s]", + identifier_unparse(&next->alias)); + break; + default: + unlex(par->lex, &tok); + next->member_type = MEMBER_TYPE_ALIAS; + next->alias.name = name; + trace(TR_PARSE, "[embedded alias %s]", name); + break; + } + break; + case T_STRUCT: + case T_UNION: + unlex(par->lex, &tok); + next->embedded = parse_struct_union_type(par); + trace(TR_PARSE, "[embedded struct/union]"); + break; + default: + synassert(false, &tok, T_NAME, T_STRUCT, T_UNION, T_EOF); + } + switch (lex(par->lex, &tok)) { + case T_COMMA: + if (lex(par->lex, &tok) != T_RBRACE) { + unlex(par->lex, &tok); + next->next = xcalloc(1, + sizeof(struct ast_struct_union_type)); + next = next->next; + } + break; case T_RBRACE: break; default: @@ -435,7 +519,9 @@ parse_type(struct parser *par) break; case T_STRUCT: case T_UNION: - assert(0); // TODO: Structs/unions + unlex(par->lex, &tok); + type = parse_struct_union_type(par); + break; case T_LPAREN: assert(0); // TODO: Tagged unions case T_LBRACKET: