From: Matthias Kruk Date: Sun, 7 Jun 2020 09:52:36 +0000 (+0900) Subject: parser: Implement parsing of translation units, external declarations, storage class... X-Git-Url: https://git.corax.cc/?a=commitdiff_plain;h=3d6402ec2997f777157c7ff6872f03ddeb391888;p=ccc parser: Implement parsing of translation units, external declarations, storage class specifiers, type specifiers, and type qualifiers --- diff --git a/src/parser.c b/src/parser.c index 493e65d..d25dd5c 100644 --- a/src/parser.c +++ b/src/parser.c @@ -1,5 +1,6 @@ #include #include +#include #include "token.h" #include "lex.h" @@ -9,62 +10,63 @@ struct type_qualifier { struct token *token; }; -const char *_type_qualifiers[] = { - "const", - "volatile", - "restrict", - NULL +struct storage_class_specifier { + struct token *token; }; -#if 0 -struct translation_unit { - struct translation_unit *tunit; - struct external_declaration *edecl; +enum type_specifier_type { + TYPE_SPECIFIER_INVALID, + TYPE_SPECIFIER_PRIMITIVE, + TYPE_SPECIFIER_STRUCT, + TYPE_SPECIFIER_UNION, + TYPE_SPECIFIER_ENUM, + TYPE_SPECIFIER_TYPEDEF }; -struct external_declaration { - external_declaration_type type; +struct struct_specifier { + struct token *token; }; -struct function_definition { - struct external_declaration parent; +struct union_specifier { + struct token *token; }; -struct declaration { - struct external_declaration parent; +struct enum_specifier { + struct token *token; }; -struct translation_unit *parse_translation_unit(void) -{ - struct translation_unit *tu; - struct token *tok; +struct typedef_name { + /* add a reference to the typedef? */ + struct token *token; +}; - tu = translation_unit_new(); +struct type_specifier { + enum type_specifier_type type; + struct token *token; - if(tu) { - tu->edecx = parse_external_declaration(void); + struct struct_specifier *ss; + struct union_specifier *us; + struct enum_specifier *es; + struct typedef_name *tn; +}; - if(lex_peek()) { - tu->tunit = parse_translation_unit(); - } - } +struct function_definition { - return(tu); -} +}; -struct external_declaration *parse_external_declaration(void) -{ - struct external_declaration *ed; +struct declaration { - ed = (struct external_declaration*)parse_function_definition(); +}; - if(!ed) { - ed = (struct external_declaration*)parse_declaration(); - } +struct external_declaration { + struct function_definition *fdef; + struct declaration *decl; +}; - return(ed); -} -#endif +struct translation_unit { + struct translation_unit *unit; + struct external_declaration *decl; +}; struct type_qualifier *type_qualifier_new(struct token *tok) { @@ -80,6 +82,20 @@ struct type_qualifier *type_qualifier_new(struct token *tok) return(tq); } +struct storage_class_specifier *storage_class_specifier_new(struct token *tok) +{ + struct storage_class_specifier *sp; + + sp = malloc(sizeof(*sp)); + + if(sp) { + memset(sp, 0, sizeof(*sp)); + sp->token = tok; + } + + return(sp); +} + struct type_qualifier *parse_type_qualifier(void) { struct type_qualifier *ret_val; @@ -106,3 +122,262 @@ struct type_qualifier *parse_type_qualifier(void) return(ret_val); } + +struct storage_class_specifier *parse_storage_class_specifier(void) +{ + struct storage_class_specifier *ret_val; + struct token *tok; + int pos; + + ret_val = NULL; + pos = lex_getpos(); + tok = lex_gettoken(); + + if(tok) { + switch(tok->type) { + case TOKEN_AUTO: + case TOKEN_REGISTER: + case TOKEN_STATIC: + case TOKEN_EXTERN: + case TOKEN_TYPEDEF: + ret_val = storage_class_specifier_new(tok); + break; + + default: + lex_setpos(pos); + break; + } + } + + return(ret_val); +} + +struct type_specifier *type_specifier_new(void) +{ + struct type_specifier *ts; + + ts = malloc(sizeof(*ts)); + + if(ts) { + memset(ts, 0, sizeof(*ts)); + } + + return(ts); +} + +struct translation_unit *translation_unit_new(struct external_declaration *edecl) +{ + struct translation_unit *tu; + + tu = malloc(sizeof(*tu)); + + if(tu) { + memset(tu, 0, sizeof(*tu)); + tu->decl = edecl; + } + + return(tu); +} + +struct struct_specifier *parse_struct_specifier(void) +{ + return(NULL); +} + +struct union_specifier *parse_union_specifier(void) +{ + return(NULL); +} + +struct enum_specifier *parse_enum_specifier(void) +{ + return(NULL); +} + +struct typedef_name *parse_typedef_name(void) +{ + return(NULL); +} + +struct type_specifier *parse_type_specifier(void) +{ + struct type_specifier *ret_val; + struct token *tok; + int pos; + + ret_val = type_specifier_new(); + + if(ret_val) { + pos = lex_getpos(); + tok = lex_gettoken(); + + if(tok) { + switch(tok->type) { + case TOKEN_VOID: + case TOKEN_CHAR: + case TOKEN_SHORT: + case TOKEN_INT: + case TOKEN_LONG: + case TOKEN_FLOAT: + case TOKEN_DOUBLE: + case TOKEN_SIGNED: + case TOKEN_UNSIGNED: + ret_val->type = TYPE_SPECIFIER_PRIMITIVE; + ret_val->token = tok; + break; + + case TOKEN_STRUCT: + ret_val->type = TYPE_SPECIFIER_STRUCT; + lex_setpos(pos); + ret_val->ss = parse_struct_specifier(); + break; + + case TOKEN_UNION: + ret_val->type = TYPE_SPECIFIER_UNION; + lex_setpos(pos); + ret_val->us = parse_union_specifier(); + break; + + case TOKEN_ENUM: + ret_val->type = TYPE_SPECIFIER_ENUM; + lex_setpos(pos); + ret_val->es = parse_enum_specifier(); + break; + + default: + ret_val->type = TYPE_SPECIFIER_TYPEDEF; + lex_setpos(pos); + ret_val->tn = parse_typedef_name(); + break; + } + + switch(ret_val->type) { + case TYPE_SPECIFIER_STRUCT: + if(!ret_val->ss) { + /* syntax error */ + fprintf(stderr, "%s:%d:%d [E] Expected struct-specifier\n", + tok->file, tok->line, tok->column); + ret_val->type = TYPE_SPECIFIER_INVALID; + } + break; + + case TYPE_SPECIFIER_UNION: + if(!ret_val->us) { + /* syntax error */ + fprintf(stderr, "%s:%d:%d [E] Expected union-specifier\n", + tok->file, tok->line, tok->column); + ret_val->type = TYPE_SPECIFIER_INVALID; + } + break; + + case TYPE_SPECIFIER_ENUM: + if(!ret_val->es) { + /* syntax error */ + fprintf(stderr, "%s:%d:%d [E] Expected enum-specifier\n", + tok->file, tok->line, tok->column); + ret_val->type = TYPE_SPECIFIER_INVALID; + } + break; + + case TYPE_SPECIFIER_TYPEDEF: + if(!ret_val->tn) { + /* syntax error */ + fprintf(stderr, "%s:%d:%d [E] Expected typedef-name\n", + tok->file, tok->line, tok->column); + ret_val->type = TYPE_SPECIFIER_INVALID; + } + break; + + default: + if(ret_val->type != TYPE_SPECIFIER_PRIMITIVE) { + /* syntax error */ + fprintf(stderr, "%s:%d:%d [E] Expected type-specifier\n", + tok->file, tok->line, tok->column); + ret_val->type = TYPE_SPECIFIER_INVALID; + } + + break; + } + } + + if(ret_val->type == TYPE_SPECIFIER_INVALID) { + free(ret_val); + ret_val = NULL; + } + } + + return(ret_val); +} + +struct external_declaration *external_declaration_new(void) +{ + struct external_declaration *ed; + + ed = malloc(sizeof(*ed)); + + if(ed) { + memset(ed, 0, sizeof(*ed)); + } + + return(ed); +} + +struct function_definition *parse_function_definition(void) +{ + return(NULL); +} + +struct declaration *parse_declaration(void) +{ + return(NULL); +} + +struct external_declaration *parse_external_declaration(void) +{ + struct external_declaration *ret_val; + + ret_val = external_declaration_new(); + + if(ret_val) { + ret_val->fdef = parse_function_definition(); + + if(!ret_val->fdef) { + ret_val->decl = parse_declaration(); + } + } + + return(ret_val); +} + +struct translation_unit *parse_translation_unit(struct translation_unit *unit) +{ + struct translation_unit *ret_val; + struct token *tok; + int pos; + + ret_val = NULL; + pos = lex_getpos(); + tok = lex_gettoken(); + + if(tok) { + struct external_declaration *ed; + + ed = parse_external_declaration(); + + if(ed) { + ret_val = translation_unit_new(ed); + + if(ret_val) { + if(lex_peek()) { + /* need to next this external declaration */ + ret_val = parse_translation_unit(ret_val); + } + } + } else { + /* is this necessary? */ + lex_setpos(pos); + } + } + + return(ret_val); +}