]> git.corax.cc Git - ccc/commitdiff
parser: Implement parsing of translation units, external declarations, storage class...
authorMatthias Kruk <m@m10k.eu>
Sun, 7 Jun 2020 09:52:36 +0000 (18:52 +0900)
committerMatthias Kruk <m@m10k.eu>
Sun, 7 Jun 2020 09:52:36 +0000 (18:52 +0900)
src/parser.c

index 493e65d298cf036d98b37f62cec0ee8194b5b235..d25dd5ca63e18fb063245eb73ee63740fa924492 100644 (file)
@@ -1,5 +1,6 @@
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
 #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);
+}