From 4a2588a169e412a188b53819bbf7d7423e558904 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Sat, 20 Jun 2020 16:47:02 +0900 Subject: [PATCH] parser: Implement parsing of declaration-specifiers --- src/grammar.c | 135 ++++++++++++++++++++++++++++++++++++++++++++++++++ src/grammar.h | 55 +++++++++++++++++--- src/parser.c | 117 +++++++++++++++++++++++++++++++++++++++---- 3 files changed, 292 insertions(+), 15 deletions(-) diff --git a/src/grammar.c b/src/grammar.c index 71d049f..a41f21b 100644 --- a/src/grammar.c +++ b/src/grammar.c @@ -1,6 +1,21 @@ #include #include +#include #include "grammar.h" +#include "token.h" + +struct function_definition *function_definition_new(void) +{ + struct function_definition *fd; + + fd = malloc(sizeof(*fd)); + + if(fd) { + memset(fd, 0, sizeof(*fd)); + } + + return(fd); +} struct type_qualifier *type_qualifier_new(struct token *tok) { @@ -16,6 +31,15 @@ struct type_qualifier *type_qualifier_new(struct token *tok) return(tq); } +int type_qualifier_to_string(struct type_qualifier *tq, char *dst, size_t n) +{ + int ret_val; + + ret_val = snprintf(dst, sizeof(dst), "%s", tq->token ? token_value(tq->token) : "(null)"); + + return(ret_val); +} + struct storage_class_specifier *storage_class_specifier_new(struct token *tok) { struct storage_class_specifier *sp; @@ -69,3 +93,114 @@ struct external_declaration *external_declaration_new(void) return(ed); } + +struct declaration_specifiers *declaration_specifiers_new(void) +{ + struct declaration_specifiers *ds; + + ds = malloc(sizeof(*ds)); + + if(ds) { + memset(ds, 0, sizeof(*ds)); + } + + return(ds); +} + +int storage_class_specifier_to_string(struct storage_class_specifier *scspec, char *dst, size_t n) +{ + int ret_val; + + ret_val = snprintf(dst, n, "%s", scspec->token ? token_value(scspec->token) : "(null)"); + + return(ret_val); +} + +int type_specifier_to_string(struct type_specifier *tspec, char *dst, size_t n) +{ + char datastr[512]; + int ret_val; + + static const char *tspec_typestr[] = { + "TYPE_SPECIFIER_INVALID", + "TYPE_SPECIFIER_PRIMITIVE", + "TYPE_SPECIFIER_STRUCT", + "TYPE_SPECIFIER_UNION", + "TYPE_SPECIFIER_ENUM", + "TYPE_SPECIFIER_TYPEDEF" + }; + + switch(tspec->type) { + case TYPE_SPECIFIER_PRIMITIVE: + snprintf(datastr, sizeof(datastr), "%s", + tspec->data.token ? token_value(tspec->data.token) : "(null)"); + break; + + case TYPE_SPECIFIER_STRUCT: + case TYPE_SPECIFIER_UNION: + case TYPE_SPECIFIER_ENUM: + case TYPE_SPECIFIER_TYPEDEF: + snprintf(datastr, sizeof(datastr), "(not implemented)"); + break; + + default: + snprintf(datastr, sizeof(datastr), "(inv)"); + break; + } + + ret_val = snprintf(dst, n, + "type_specifier {\n" + "\ttype = %s\n" + "\tdata = %s\n" + "}\n", + tspec_typestr[tspec->type], + datastr); + + return(ret_val); +} + +void declaration_specifiers_debug(struct declaration_specifiers *declspec) +{ + static const char *declspec_typestr[] = { + "DECL_SPEC_INVALID", + "DECL_SPEC_STORAGE_CLASS", + "DECL_SPEC_TYPE_SPEC", + "DECL_SPEC_TYPE_QUALIFIER" + }; + + char datastr[512]; + + switch(declspec->type) { + case DECL_SPEC_STORAGE_CLASS: + storage_class_specifier_to_string(declspec->data.scspec, datastr, sizeof(datastr)); + break; + + case DECL_SPEC_TYPE_SPEC: + type_specifier_to_string(declspec->data.tspec, datastr, sizeof(datastr)); + break; + + case DECL_SPEC_TYPE_QUALIFIER: + type_qualifier_to_string(declspec->data.tqual, datastr, sizeof(datastr)); + break; + + default: + snprintf(datastr, sizeof(datastr), "(invalid)"); + break; + } + + printf("decl_spec %p {\n" + "\ttype = %s [%s],\n" + "\tdata = %p [%s],\n" + "\tnext = %p\n" + "}", + declspec, + declspec_typestr[declspec->type], + datastr, + declspec->next); + + if(declspec->next) { + declaration_specifiers_debug(declspec->next); + } + + return; +} diff --git a/src/grammar.h b/src/grammar.h index 051263e..38ece37 100644 --- a/src/grammar.h +++ b/src/grammar.h @@ -39,16 +39,52 @@ struct typedef_name { struct type_specifier { enum type_specifier_type type; - struct token *token; - struct struct_specifier *ss; - struct union_specifier *us; - struct enum_specifier *es; - struct typedef_name *tn; + union { + struct token *token; + struct struct_specifier *ss; + struct union_specifier *us; + struct enum_specifier *es; + struct typedef_name *tn; + } data; }; -struct function_definition { +enum declaration_specifier_type { + DECL_SPEC_INVALID = 0, + DECL_SPEC_STORAGE_CLASS, + DECL_SPEC_TYPE_SPEC, + DECL_SPEC_TYPE_QUALIFIER +}; + +struct declaration_specifiers { + enum declaration_specifier_type type; + + union { + struct storage_class_specifier *scspec; + struct type_specifier *tspec; + struct type_qualifier *tqual; + } data; + + struct declaration_specifiers *next; +}; + +struct declarator { + +}; +struct declaration_list { + +}; + +struct compound_statement { + +}; + +struct function_definition { + struct declaration_specifiers *decl_specs; + struct declarator *decl; + struct declaration_list *decl_list; + struct compound_statement *stmts; }; struct declaration { @@ -65,10 +101,17 @@ struct translation_unit { struct external_declaration *decl; }; +struct function_definition *function_definition_new(void); + struct type_qualifier *type_qualifier_new(struct token*); +int type_qualifier_to_string(struct type_qualifier*, char*, size_t); + struct storage_class_specifier *storage_class_specifier_new(struct token*); struct type_specifier *type_specifier_new(void); struct translation_unit *translation_unit_new(struct external_declaration*); struct external_declaration *external_declaration_new(void); +struct declaration_specifiers* declaration_specifiers_new(void); +void declaration_specifiers_debug(struct declaration_specifiers*); + #endif /* GRAMMAR_H */ diff --git a/src/parser.c b/src/parser.c index f3fb35d..b329521 100644 --- a/src/parser.c +++ b/src/parser.c @@ -4,6 +4,7 @@ #include "token.h" #include "lex.h" #include "grammar.h" +#include "parser.h" struct type_qualifier *parse_type_qualifier(void) { @@ -105,71 +106,79 @@ struct type_specifier *parse_type_specifier(void) case TOKEN_SIGNED: case TOKEN_UNSIGNED: ret_val->type = TYPE_SPECIFIER_PRIMITIVE; - ret_val->token = tok; + ret_val->data.token = tok; break; case TOKEN_STRUCT: ret_val->type = TYPE_SPECIFIER_STRUCT; lex_setpos(pos); - ret_val->ss = parse_struct_specifier(); + ret_val->data.ss = parse_struct_specifier(); break; case TOKEN_UNION: ret_val->type = TYPE_SPECIFIER_UNION; lex_setpos(pos); - ret_val->us = parse_union_specifier(); + ret_val->data.us = parse_union_specifier(); break; case TOKEN_ENUM: ret_val->type = TYPE_SPECIFIER_ENUM; lex_setpos(pos); - ret_val->es = parse_enum_specifier(); + ret_val->data.es = parse_enum_specifier(); break; default: ret_val->type = TYPE_SPECIFIER_TYPEDEF; lex_setpos(pos); - ret_val->tn = parse_typedef_name(); + ret_val->data.tn = parse_typedef_name(); break; } switch(ret_val->type) { case TYPE_SPECIFIER_STRUCT: - if(!ret_val->ss) { + if(!ret_val->data.ss) { /* syntax error */ +#if 0 fprintf(stderr, "%s:%d:%d [E] Expected struct-specifier\n", tok->file, tok->line, tok->column); +#endif ret_val->type = TYPE_SPECIFIER_INVALID; } break; case TYPE_SPECIFIER_UNION: - if(!ret_val->us) { + if(!ret_val->data.us) { /* syntax error */ +#if 0 fprintf(stderr, "%s:%d:%d [E] Expected union-specifier\n", tok->file, tok->line, tok->column); +#endif ret_val->type = TYPE_SPECIFIER_INVALID; } break; case TYPE_SPECIFIER_ENUM: - if(!ret_val->es) { + if(!ret_val->data.es) { /* syntax error */ +#if 0 fprintf(stderr, "%s:%d:%d [E] Expected enum-specifier\n", tok->file, tok->line, tok->column); +#endif ret_val->type = TYPE_SPECIFIER_INVALID; } break; case TYPE_SPECIFIER_TYPEDEF: - if(!ret_val->tn) { + if(!ret_val->data.tn) { /* syntax error */ +#if 0 fprintf(stderr, "%s:%d:%d [E] Expected typedef-name\n", tok->file, tok->line, tok->column); +#endif ret_val->type = TYPE_SPECIFIER_INVALID; } break; @@ -177,9 +186,11 @@ struct type_specifier *parse_type_specifier(void) default: if(ret_val->type != TYPE_SPECIFIER_PRIMITIVE) { /* syntax error */ +#if 0 fprintf(stderr, "%s:%d:%d [E] Expected type-specifier\n", tok->file, tok->line, tok->column); +#endif ret_val->type = TYPE_SPECIFIER_INVALID; } @@ -196,7 +207,95 @@ struct type_specifier *parse_type_specifier(void) return(ret_val); } +struct declaration_specifiers *parse_declaration_specifiers(void) +{ + struct declaration_specifiers *ds; + int pos; + + pos = lex_getpos(); + ds = declaration_specifiers_new(); + + ds->data.scspec = parse_storage_class_specifier(); + + if(ds->data.scspec) { + ds->type = DECL_SPEC_STORAGE_CLASS; + goto parse_next; + } + + ds->data.tspec = parse_type_specifier(); + + if(ds->data.tspec) { + ds->type = DECL_SPEC_TYPE_SPEC; + goto parse_next; + } + + ds->data.tqual = parse_type_qualifier(); + + if(ds->data.tqual) { + ds->type = DECL_SPEC_TYPE_QUALIFIER; + } + +parse_next: + if(ds->type != DECL_SPEC_INVALID) { + ds->next = parse_declaration_specifiers(); + } else { + free(ds); + ds = NULL; + } + + return(ds); +} + struct function_definition *parse_function_definition(void) +{ + struct function_definition *fdef; + int pos; + + /* + * function-definition: + * declaration-specifiers_opt declarator declaration-list_opt compound-statement + */ + + pos = lex_getpos(); + fdef = function_definition_new(); + + if(fdef) { + fdef->decl_specs = parse_declaration_specifiers(); + fdef->decl = parse_declarator(); + + if(!fdef->decl) { + free(fdef); + fdef = NULL; + goto gtfo; + } + + fdef->decl_list = parse_declaration_list(); + fdef->stmts = parse_compound_statement(); + + if(!fdef->stmts) { + free(fdef); + fdef = NULL; + } + } + + if(!fdef) { + lex_setpos(pos); + } +gtfo: + return(fdef); +} + +struct declaration_list *parse_declaration_list(void) +{ + return(NULL); +} + +struct compound_statement *parse_compound_statement(void) +{ + return(NULL); +} + +struct declarator *parse_declarator(void) { return(NULL); } -- 2.47.3