]> git.corax.cc Git - ccc/commitdiff
parser: Implement parsing of declaration-specifiers
authorMatthias Kruk <m@m10k.eu>
Sat, 20 Jun 2020 07:47:02 +0000 (16:47 +0900)
committerMatthias Kruk <m@m10k.eu>
Sat, 20 Jun 2020 07:47:02 +0000 (16:47 +0900)
src/grammar.c
src/grammar.h
src/parser.c

index 71d049f1afe5a8ba8395c1d512fe337f7d404787..a41f21b6b7c0c919e5114140e5137567d6262694 100644 (file)
@@ -1,6 +1,21 @@
 #include <stdlib.h>
 #include <string.h>
+#include <stdio.h>
 #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;
+}
index 051263e49baaa1a0fcce0a1da56467b7059acd79..38ece37c8b9d1c09a186c774183335a495519054 100644 (file)
@@ -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 */
index f3fb35dcc6e7328ea563a21d298e5a4f848ae3ab..b3295212584f310509224fa9bccfbc5d4262f6e7 100644 (file)
@@ -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);
 }