From: Matthias Kruk Date: Sun, 12 Jul 2020 10:01:35 +0000 (+0900) Subject: parser: Implement parsing of direct-abstract-declarators, parameter-type-lists, param... X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=94917f19ad0f92b903aafced196224c09b9f9b5c;p=ccc parser: Implement parsing of direct-abstract-declarators, parameter-type-lists, parameter-lists, parameter-declarations, declarators, direct-declarators, constant-expressions, and identifier-lists --- diff --git a/src/grammar.c b/src/grammar.c index d092852..70590c6 100644 --- a/src/grammar.c +++ b/src/grammar.c @@ -54,6 +54,14 @@ struct storage_class_specifier *storage_class_specifier_new(struct token *tok) return(sp); } +void storage_class_specifier_free(struct storage_class_specifier *spec) +{ + memset(spec, 0, sizeof(*spec)); + free(spec); + + return; +} + struct type_specifier *type_specifier_new(void) { struct type_specifier *ts; @@ -107,6 +115,40 @@ struct declaration_specifiers *declaration_specifiers_new(void) return(ds); } +void declaration_specifiers_free(struct declaration_specifiers *specs) +{ + switch(specs->type) { + case DECL_SPEC_STORAGE_CLASS: + if(specs->data.scspec) { + storage_class_specifier_free(specs->data.scspec); + } + + break; + + case DECL_SPEC_TYPE_SPEC: + if(specs->data.tspec) { + type_specifier_free(specs->data.tspec); + } + + break; + + case DECL_SPEC_TYPE_QUALIFIER: + if(specs->data.tqual) { + type_qualifier_free(specs->data.tqual); + } + + break; + + default: + break; + } + + memset(specs, 0, sizeof(*specs)); + free(specs); + + return; +} + int storage_class_specifier_to_string(struct storage_class_specifier *scspec, char *dst, size_t n) { int ret_val; @@ -1397,7 +1439,43 @@ struct direct_abstract_declarator *direct_abstract_declarator_new(void) void direct_abstract_declarator_free(struct direct_abstract_declarator *decl) { - fprintf(stderr, "FIXME: %s() not implemented\n", __func__); + switch(decl->type) { + case DIRECT_ABSTRACT_DECL_ABS: + if(decl->data.abs.decl) { + abstract_declarator_free(decl->data.abs.decl); + } + + break; + + case DIRECT_ABSTRACT_DECL_CNST: + if(decl->data.cnst.next) { + direct_abstract_declarator_free(decl->data.cnst.next); + } + + if(decl->data.cnst.cexpr) { + constant_expression_free(decl->data.cnst.cexpr); + } + + break; + + case DIRECT_ABSTRACT_DECL_PARAM: + if(decl->data.param.next) { + direct_abstract_declarator_free(decl->data.param.next); + } + + if(decl->data.param.params) { + parameter_type_list_free(decl->data.param.params); + } + + break; + + default: + break; + } + + memset(decl, 0, sizeof(*decl)); + free(decl); + return; } @@ -1445,6 +1523,14 @@ struct pointer *pointer_new(void) void pointer_free(struct pointer *ptr) { + if(ptr->ptr) { + pointer_free(ptr->ptr); + } + + if(ptr->tqual) { + type_qualifier_list_free(ptr->tqual); + } + memset(ptr, 0, sizeof(*ptr)); free(ptr); } @@ -1514,6 +1600,14 @@ struct declarator *declarator_new(void) void declarator_free(struct declarator *decl) { + if(decl->ptr) { + pointer_free(decl->ptr); + } + + if(decl->ddecl) { + direct_declarator_free(decl->ddecl); + } + memset(decl, 0, sizeof(*decl)); free(decl); @@ -1577,3 +1671,189 @@ void enumerator_free(struct enumerator *en) return; } + +struct type_qualifier_list *type_qualifier_list_new(void) +{ + struct type_qualifier_list *list; + + list = malloc(sizeof(*list)); + + if(list) { + memset(list, 0, sizeof(*list)); + } + + return(list); +} + +void type_qualifier_list_free(struct type_qualifier_list *list) +{ + if(list->tqual) { + type_qualifier_free(list->tqual); + } + + if(list->next) { + type_qualifier_list_free(list->next); + } + + memset(list, 0, sizeof(*list)); + free(list); + + return; +} + +struct parameter_type_list *parameter_type_list_new(void) +{ + struct parameter_type_list *list; + + list = malloc(sizeof(*list)); + + if(list) { + memset(list, 0, sizeof(*list)); + } + + return(list); +} + +void parameter_type_list_free(struct parameter_type_list *list) +{ + if(list->params) { + parameter_list_free(list->params); + } + + memset(list, 0, sizeof(*list)); + free(list); + + return; +} + +struct parameter_list *parameter_list_new(void) +{ + struct parameter_list *list; + + list = malloc(sizeof(*list)); + + if(list) { + memset(list, 0, sizeof(*list)); + } + + return(list); +} + +void parameter_list_free(struct parameter_list *list) +{ + if(list->decl) { + parameter_declaration_free(list->decl); + } + + if(list->next) { + parameter_list_free(list->next); + } + + memset(list, 0, sizeof(*list)); + free(list); + + return; +} + +struct parameter_declaration *parameter_declaration_new(void) +{ + struct parameter_declaration *decl; + + decl = malloc(sizeof(*decl)); + + if(decl) { + memset(decl, 0, sizeof(*decl)); + } + + return(decl); +} + +void parameter_declaration_free(struct parameter_declaration *decl) +{ + if(decl->specs) { + declaration_specifiers_free(decl->specs); + } + + if(decl->decl) { + declarator_free(decl->decl); + } + + if(decl->adecl) { + abstract_declarator_free(decl->adecl); + } + + memset(decl, 0, sizeof(*decl)); + free(decl); + + return; +} + +struct direct_declarator *direct_declarator_new(void) +{ + struct direct_declarator *decl; + + decl = malloc(sizeof(*decl)); + + if(decl) { + memset(decl, 0, sizeof(*decl)); + } + + return(decl); +} + +void direct_declarator_free(struct direct_declarator *decl) +{ + if(decl->identifier) { + identifier_free(decl->identifier); + } + + if(decl->decl) { + declarator_free(decl->decl); + } + + if(decl->cexpr) { + constant_expression_free(decl->cexpr); + } + + if(decl->params) { + parameter_type_list_free(decl->params); + } + + if(decl->ids) { + identifier_list_free(decl->ids); + } + + memset(decl, 0, sizeof(*decl)); + free(decl); + + return; +} + +struct identifier_list *identifier_list_new(void) +{ + struct identifier_list *list; + + list = malloc(sizeof(*list)); + + if(list) { + memset(list, 0, sizeof(*list)); + } + + return(list); +} + +void identifier_list_free(struct identifier_list *list) +{ + if(list->identifier) { + identifier_free(list->identifier); + } + + if(list->next) { + identifier_list_free(list->next); + } + + memset(list, 0, sizeof(*list)); + free(list); + + return; +} diff --git a/src/grammar.h b/src/grammar.h index dbb7723..1ba60c1 100644 --- a/src/grammar.h +++ b/src/grammar.h @@ -89,11 +89,60 @@ enum unary_expression_type { }; struct pointer { + struct token *op; + struct type_qualifier_list *tqual; + struct pointer *ptr; +}; + +enum direct_abstract_declarator_type { + DIRECT_ABSTRACT_DECL_INVALID, + DIRECT_ABSTRACT_DECL_ABS, + DIRECT_ABSTRACT_DECL_CNST, + DIRECT_ABSTRACT_DECL_PARAM +}; +struct parameter_declaration { + struct declaration_specifiers *specs; + struct declarator *decl; + struct abstract_declarator *adecl; +}; + +struct parameter_list { + struct parameter_declaration *decl; + struct token *comma; + struct parameter_list *next; +}; + +struct parameter_type_list { + struct parameter_list *params; + struct token *comma; + struct token *dots; }; struct direct_abstract_declarator { + enum direct_abstract_declarator_type type; + union { + struct { + struct token *lparen; + struct abstract_declarator *decl; + struct token *rparen; + } abs; + + struct { + struct direct_abstract_declarator *next; + struct token *lbracket; + struct constant_expression *cexpr; + struct token *rbracket; + } cnst; + + struct { + struct direct_abstract_declarator *next; + struct token *lparen; + struct parameter_type_list *params; + struct token *rparen; + } param; + } data; }; struct abstract_declarator { @@ -304,6 +353,11 @@ struct type_qualifier { struct token *token; }; +struct type_qualifier_list { + struct type_qualifier *tqual; + struct type_qualifier_list *next; +}; + struct storage_class_specifier { struct token *token; }; @@ -402,8 +456,26 @@ struct declaration_specifiers { struct declaration_specifiers *next; }; -struct declarator { +struct identifier_list { + struct identifier *identifier; + struct token *comma; + struct identifier_list *next; +}; +struct direct_declarator { + struct identifier *identifier; + struct declarator *decl; + struct direct_declarator *ddecl; + struct constant_expression *cexpr; + struct parameter_type_list *params; + struct identifier_list *ids; + struct token *ltok; + struct token *rtok; +}; + +struct declarator { + struct pointer *ptr; + struct direct_declarator *ddecl; }; struct declaration_list { @@ -461,6 +533,7 @@ void type_qualifier_free(struct type_qualifier*); int type_qualifier_to_string(struct type_qualifier*, char*, size_t); struct storage_class_specifier *storage_class_specifier_new(struct token*); +void storage_class_specifier_free(struct storage_class_specifier*); struct translation_unit *translation_unit_new(struct external_declaration*); struct external_declaration *external_declaration_new(void); @@ -566,6 +639,9 @@ void struct_declaration_free(struct struct_declaration*); struct struct_declaration_list *struct_declaration_list_new(void); void struct_declaration_list_free(struct struct_declaration_list*); +struct direct_declarator *direct_declarator_new(void); +void direct_declarator_free(struct direct_declarator*); + struct declarator *declarator_new(void); void declarator_free(struct declarator*); @@ -578,4 +654,19 @@ void enumerator_list_free(struct enumerator_list*); struct expression *expression_new(void); void expression_free(struct expression*); +struct type_qualifier_list *type_qualifier_list_new(void); +void type_qualifier_list_free(struct type_qualifier_list*); + +struct parameter_type_list *parameter_type_list_new(void); +void parameter_type_list_free(struct parameter_type_list*); + +struct parameter_list *parameter_list_new(void); +void parameter_list_free(struct parameter_list*); + +struct parameter_declaration *parameter_declaration_new(void); +void parameter_declaration_free(struct parameter_declaration*); + +struct identifier_list *identifier_list_new(void); +void identifier_list_free(struct identifier_list*); + #endif /* GRAMMAR_H */ diff --git a/src/parser.c b/src/parser.c index 0859d4a..c7e82be 100644 --- a/src/parser.c +++ b/src/parser.c @@ -295,12 +295,132 @@ struct compound_statement *parse_compound_statement(void) return(NULL); } -struct declarator *parse_declarator(void) +struct direct_declarator *parse_direct_declarator(void) { - fprintf(stderr, "FIXME: %s() is not implemented\n", __func__); + struct direct_declarator *decl; + int pos; + + decl = direct_declarator_new(); + + if(!decl) { + return(NULL); + } + + if((decl->identifier = parse_identifier())) { + return(decl); + } + + pos = lex_getpos(); + + decl->ltok = lex_gettoken(); + decl->decl = parse_declarator(); + decl->rtok = lex_gettoken(); + + if(decl->ltok && decl->decl && decl->rtok && + decl->ltok->type == TOKEN_LPAREN && decl->rtok->type == TOKEN_RPAREN) { + return(decl); + } else { + decl->ltok = NULL; + decl->rtok = NULL; + + if(decl->decl) { + declarator_free(decl->decl); + decl->decl = NULL; + } + + lex_setpos(pos); + } + + decl->ddecl = parse_direct_declarator(); + decl->ltok = lex_gettoken(); + decl->cexpr = parse_constant_expression(); + decl->rtok = lex_gettoken(); + + if(decl->ddecl && decl->ltok && decl->rtok && decl->ltok->type == TOKEN_LBRACKET && + decl->rtok->type == TOKEN_RBRACKET) { + return(decl); + } else { + if(decl->ddecl) { + direct_declarator_free(decl->ddecl); + decl->ddecl = NULL; + } + + if(decl->cexpr) { + constant_expression_free(decl->cexpr); + decl->cexpr = NULL; + } + + decl->ltok = NULL; + decl->rtok = NULL; + + lex_setpos(pos); + } + + decl->ddecl = parse_direct_declarator(); + decl->ltok = lex_gettoken(); + decl->params = parse_parameter_type_list(); + decl->rtok = lex_gettoken(); + + if(decl->ddecl && decl->ltok && decl->params && decl->rtok && + decl->ltok->type == TOKEN_LPAREN && decl->rtok->type == TOKEN_RPAREN) { + return(decl); + } else { + if(decl->ddecl) { + direct_declarator_free(decl->ddecl); + decl->ddecl = NULL; + } + + if(decl->params) { + parameter_type_list_free(decl->params); + decl->params = NULL; + } + + decl->ltok = NULL; + decl->rtok = NULL; + + lex_setpos(pos); + } + + decl->ddecl = parse_direct_declarator(); + decl->ltok = lex_gettoken(); + decl->ids = parse_identifier_list(); + decl->rtok = lex_gettoken(); + + if(decl->ddecl && decl->ltok && decl->rtok && + decl->ltok->type == TOKEN_LPAREN && + decl->rtok->type == TOKEN_RPAREN) { + return(decl); + } + + direct_declarator_free(decl); + lex_setpos(pos); + return(NULL); } +struct declarator *parse_declarator(void) +{ + struct declarator *decl; + int pos; + + decl = declarator_new(); + pos = lex_getpos(); + + if(decl) { + decl->ptr = parse_pointer(); + decl->ddecl = parse_direct_declarator(); + + if(!decl->ddecl) { + lex_setpos(pos); + + declarator_free(decl); + decl = NULL; + } + } + + return(decl); +} + struct declaration *parse_declaration(void) { fprintf(stderr, "FIXME: %s() is not implemented\n", __func__); @@ -911,6 +1031,37 @@ struct abstract_declarator *parse_abstract_declarator(void) return(decl); } +struct pointer *parse_pointer(void) +{ + struct pointer *ptr; + int pos; + + ptr = pointer_new(); + + /* + * pointer: + * * type-qualifier-list_opt + * * type-qualifier-list_opt pointer + */ + + if(ptr) { + pos = lex_getpos(); + + ptr->op = lex_gettoken(); + ptr->tqual = parse_type_qualifier_list(); + ptr->ptr = parse_pointer(); + + if(!ptr->op || ptr->op->type != TOKEN_MUL) { + pointer_free(ptr); + lex_setpos(pos); + + ptr = NULL; + } + } + + return(ptr); +} + struct logical_or_expression *parse_logical_or_expression(void) { struct logical_or_expression *expr; @@ -1399,3 +1550,257 @@ struct specifier_qualifier_list *parse_specifier_qualifier_list(void) return(sql); } + +struct type_qualifier_list *parse_type_qualifier_list(void) +{ + struct type_qualifier_list *list; + int pos; + + list = type_qualifier_list_new(); + + if(!list) { + return(NULL); + } + + if((list->tqual = parse_type_qualifier())) { + return(list); + } + + pos = lex_getpos(); + + list->next = parse_type_qualifier_list(); + list->tqual = parse_type_qualifier(); + + if(list->next && list->tqual) { + return(list); + } + + type_qualifier_list_free(list); + lex_setpos(pos); + + return(NULL); +} + +struct direct_abstract_declarator *parse_direct_abstract_declarator(void) +{ + struct direct_abstract_declarator *decl; + int pos; + + decl = direct_abstract_declarator_new(); + + if(!decl) { + return(NULL); + } + + pos = lex_getpos(); + + decl->data.abs.lparen = lex_gettoken(); + decl->data.abs.decl = parse_abstract_declarator(); + decl->data.abs.rparen = lex_gettoken(); + + if(decl->data.abs.lparen && decl->data.abs.decl && decl->data.abs.rparen && + decl->data.abs.lparen->type == TOKEN_LPAREN && decl->data.abs.rparen->type == TOKEN_RPAREN) { + decl->type = DIRECT_ABSTRACT_DECL_ABS; + return(decl); + } + + if(decl->data.abs.decl) { + abstract_declarator_free(decl->data.abs.decl); + decl->data.abs.decl = NULL; + } + + decl->data.abs.lparen = NULL; + decl->data.abs.rparen = NULL; + + lex_setpos(pos); + + decl->data.cnst.next = parse_direct_abstract_declarator(); + decl->data.cnst.lbracket = lex_gettoken(); + decl->data.cnst.cexpr = parse_constant_expression(); + decl->data.cnst.rbracket = lex_gettoken(); + + if(decl->data.cnst.lbracket && decl->data.cnst.rbracket && + decl->data.cnst.lbracket->type == TOKEN_LBRACKET && + decl->data.cnst.rbracket->type == TOKEN_RBRACKET) { + decl->type = DIRECT_ABSTRACT_DECL_CNST; + return(decl); + } + + if(decl->data.cnst.next) { + direct_abstract_declarator_free(decl->data.cnst.next); + decl->data.cnst.next = NULL; + } + + if(decl->data.cnst.cexpr) { + constant_expression_free(decl->data.cnst.cexpr); + decl->data.cnst.cexpr = NULL; + } + + decl->data.cnst.lbracket = NULL; + decl->data.cnst.rbracket = NULL; + + lex_setpos(pos); + + decl->data.param.next = parse_direct_abstract_declarator(); + decl->data.param.lparen = lex_gettoken(); + decl->data.param.params = parse_parameter_type_list(); + decl->data.param.rparen = lex_gettoken(); + + decl->type = DIRECT_ABSTRACT_DECL_PARAM; + + if(decl->data.param.lparen && decl->data.param.rparen && + decl->data.param.lparen->type == TOKEN_LPAREN && + decl->data.param.rparen->type == TOKEN_RPAREN) { + return(decl); + } + + direct_abstract_declarator_free(decl); + lex_setpos(pos); + + return(NULL); +} + +struct constant_expression *parse_constant_expression(void) +{ + struct constant_expression *expr; + + expr = constant_expression_new(); + + if(expr) { + expr->cexpr = parse_conditional_expression(); + + if(!expr->cexpr) { + constant_expression_free(expr); + expr = NULL; + } + } + + return(expr); +} + +struct parameter_type_list *parse_parameter_type_list(void) +{ + struct parameter_type_list *list; + + list = parameter_type_list_new(); + + if(!list) { + return(NULL); + } + + list->params = parse_parameter_list(); + + if(list->params) { + int pos; + + pos = lex_getpos(); + + list->comma = lex_gettoken(); + list->dots = lex_gettoken(); + + if(!(list->comma && list->dots && + list->comma->type == TOKEN_COMMA && + list->dots->type == TOKEN_DOTS)) { + list->comma = NULL; + list->dots = NULL; + + lex_setpos(pos); + } + + return(list); + } + + parameter_type_list_free(list); + + return(NULL); +} + +struct parameter_list *parse_parameter_list(void) +{ + struct parameter_list *list; + int pos; + + list = parameter_list_new(); + + if(!list) { + return(NULL); + } + + if((list->decl = parse_parameter_declaration())) { + /* FIXME: should we be matching the second case first? */ + return(list); + } + + pos = lex_getpos(); + + list->next = parse_parameter_list(); + list->comma = lex_gettoken(); + list->decl = parse_parameter_declaration(); + + if(list->next && list->comma && list->decl && list->comma->type == TOKEN_COMMA) { + return(list); + } + + parameter_list_free(list); + lex_setpos(pos); + + return(NULL); +} + +struct parameter_declaration *parse_parameter_declaration(void) +{ + struct parameter_declaration *decl; + + decl = parameter_declaration_new(); + + if(!decl) { + return(NULL); + } + + decl->specs = parse_declaration_specifiers(); + + if(decl->specs) { + decl->decl = parse_declarator(); + + if(!decl->decl) { + decl->adecl = parse_abstract_declarator(); + } + + return(decl); + } + + parameter_declaration_free(decl); + + return(NULL); +} + +struct identifier_list *parse_identifier_list(void) +{ + struct identifier_list *list; + int pos; + + list = identifier_list_new(); + + if(!list) { + return(NULL); + } + + if((list->identifier = parse_identifier())) { + return(list); + } + + pos = lex_getpos(); + + list->next = parse_identifier_list(); + list->comma = lex_gettoken(); + list->identifier = parse_identifier(); + + if(list->next && list->comma && list->identifier && list->comma->type == TOKEN_COMMA) { + return(list); + } + + identifier_list_free(list); + lex_setpos(pos); + + return(NULL); +} diff --git a/src/parser.h b/src/parser.h index fc09c09..93660e5 100644 --- a/src/parser.h +++ b/src/parser.h @@ -10,7 +10,9 @@ struct enumeration_constant *parse_enumeration_constant(void); struct constant *parse_constant(void); struct string *parse_string(void); struct type_name *parse_type_name(void); +struct pointer *parse_pointer(void); +struct specifier_qualifier_list *parse_specifier_qualifier_list(void); struct abstract_declarator *parse_abstract_declarator(void); struct assignment_expression *parse_assignment_expression(void); struct logical_or_expression *parse_logical_or_expression(void); @@ -42,9 +44,16 @@ struct declaration_list *parse_declaration_list(void); struct declaration_specifiers *parse_declaration_specifiers(void); struct function_definition *parse_function_definition(void); struct compound_statement *parse_compound_statement(void); +struct direct_abstract_declarator *parse_direct_abstract_declarator(void); +struct type_qualifier_list *parse_type_qualifier_list(void); struct declarator *parse_declarator(void); struct declaration *parse_declaration(void); struct external_declaration *parse_external_declaration(void); struct translation_unit *parse_translation_unit(struct translation_unit*); +struct constant_expression *parse_constant_expression(void); +struct parameter_type_list *parse_parameter_type_list(void); +struct parameter_list *parse_parameter_list(void); +struct parameter_declaration *parse_parameter_declaration(void); +struct identifier_list *parse_identifier_list(void); #endif /* PARSER_H */