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;
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;
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;
}
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);
}
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);
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;
+}
};
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 {
struct token *token;
};
+struct type_qualifier_list {
+ struct type_qualifier *tqual;
+ struct type_qualifier_list *next;
+};
+
struct storage_class_specifier {
struct token *token;
};
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 {
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);
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*);
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 */
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__);
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;
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);
+}
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);
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 */