]> git.corax.cc Git - ccc/commitdiff
parser: Implement parsing of integer, character, and floating point constants
authorMatthias Kruk <m@m10k.eu>
Sat, 4 Jul 2020 08:50:22 +0000 (17:50 +0900)
committerMatthias Kruk <m@m10k.eu>
Sat, 4 Jul 2020 08:50:22 +0000 (17:50 +0900)
src/grammar.c
src/grammar.h
src/parser.c

index a41f21b6b7c0c919e5114140e5137567d6262694..612357b24dfd679c94ca89fc399144752b2a1002 100644 (file)
@@ -204,3 +204,138 @@ void declaration_specifiers_debug(struct declaration_specifiers *declspec)
 
        return;
 }
+
+struct primary_expression *primary_expression_new(void)
+{
+       struct primary_expression *pexp;
+
+       pexp = malloc(sizeof(*pexp));
+
+       if(pexp) {
+               memset(pexp, 0, sizeof(*pexp));
+       }
+
+       return(pexp);
+}
+
+struct integer_constant *integer_constant_new(void)
+{
+       struct integer_constant *iconst;
+
+       iconst = malloc(sizeof(*iconst));
+
+       if(iconst) {
+               memset(iconst, 0, sizeof(*iconst));
+       }
+
+       return(iconst);
+}
+
+struct character_constant *character_constant_new(void)
+{
+       struct character_constant *cconst;
+
+       cconst = malloc(sizeof(*cconst));
+
+       if(cconst) {
+               memset(cconst, 0, sizeof(*cconst));
+       }
+
+       return(cconst);
+}
+
+struct floating_constant *floating_constant_new(void)
+{
+       struct floating_constant *fconst;
+
+       fconst = malloc(sizeof(*fconst));
+
+       if(fconst) {
+               memset(fconst, 0, sizeof(*fconst));
+       }
+
+       return(fconst);
+}
+
+struct enumeration_constant *enumeration_constant_new(void)
+{
+       struct enumeration_constant *econst;
+
+       econst = malloc(sizeof(*econst));
+
+       if(econst) {
+               memset(econst, 0, sizeof(*econst));
+       }
+
+       return(econst);
+}
+
+struct constant *constant_new(void)
+{
+       struct constant *c;
+
+       c = malloc(sizeof(*c));
+
+       if(c) {
+               memset(c, 0, sizeof(*c));
+       }
+
+       return(c);
+}
+
+struct argument_expression_list* argument_expression_list_new(void)
+{
+       struct argument_expression_list *aelist;
+
+       aelist = malloc(sizeof(*aelist));
+
+       if(aelist) {
+               memset(aelist, 0, sizeof(*aelist));
+       }
+
+       return(aelist);
+}
+
+void constant_debug(struct constant *cnst)
+{
+       static const char *_const_type_str[] = {
+               "INVALID",
+               "integer",
+               "character",
+               "floating",
+               "enumeration"
+       };
+       char data[128];
+
+       switch(cnst->type) {
+       case CONST_TYPE_INVALID:
+               data[0] = 0;
+               break;
+
+       case CONST_TYPE_INTEGER:
+               snprintf(data, sizeof(data), "%s%s",
+                        cnst->data.iconst->token ? token_value(cnst->data.iconst->token) : "",
+                        cnst->data.iconst->suffix ? token_value(cnst->data.iconst->suffix) : "");
+               break;
+
+       case CONST_TYPE_CHARACTER:
+               snprintf(data, sizeof(data), "%s%s",
+                        cnst->data.cconst->prefix ? token_value(cnst->data.cconst->prefix) : "",
+                        cnst->data.cconst->token ? token_value(cnst->data.cconst->token) : "");
+               break;
+
+       case CONST_TYPE_FLOATING:
+               snprintf(data, sizeof(data), "%s%s",
+                        cnst->data.fconst->token ? token_value(cnst->data.fconst->token) : "",
+                        cnst->data.fconst->suffix ? token_value(cnst->data.fconst->suffix) : "");
+               break;
+
+       case CONST_TYPE_ENUMERATION:
+               snprintf(data, sizeof(data), "%s",
+                        cnst->data.econst->token ? token_value(cnst->data.econst->token) : "");
+               break;
+       }
+
+       printf("CONSTANT { %s, %s }\n", _const_type_str[cnst->type], data);
+       return;
+}
index 38ece37c8b9d1c09a186c774183335a495519054..b6208d389bc54cdd1556262a93c41eb457f7bec1 100644 (file)
@@ -3,6 +3,83 @@
 
 struct token;
 
+struct integer_constant {
+       /*
+        * 0[0-9]           \
+        * 0[xX][0-9a-fA-F] | ([uUlL]|ll|LL|ul|uL|ull|uLL|Ul|UL|Ull|ULL|lu|Lu|llu|LLu|lU|LU|llU|LLU)
+        * [1-9][0-9]*      /
+        */
+       struct token *token;
+       struct token *suffix;
+};
+
+struct character_constant {
+       /* L'x' */
+       struct token *prefix;
+       struct token *token;
+};
+
+struct floating_constant {
+       /* [0-9]*.[0-9]*([eE][0-9]*)[fFlL] */
+       struct token *token;
+       struct token *suffix;
+};
+
+struct enumeration_constant {
+       struct token *token;
+};
+
+struct argument_expression_list {
+       struct assigment_expression *aexpr;
+       struct argument_expression_list *next;
+};
+
+enum primary_expression_type {
+        PEXPR_INVALID = 0,
+       PEXPR_IDENTIFIER,
+       PEXPR_CONSTANT,
+       PEXPR_STRING,
+       PEXPR_EXPR
+};
+
+struct primary_expression {
+       enum primary_expression_type type;
+
+       union {
+               struct identifier *identifier;
+               struct constant *constant;
+               struct string *string;
+               struct {
+                       struct token *oparen;
+                       struct expression *expr;
+                       struct token *cparen;
+               } expr;
+       } data;
+};
+
+enum constant_type {
+       CONST_TYPE_INVALID = 0,
+       CONST_TYPE_INTEGER,
+       CONST_TYPE_CHARACTER,
+       CONST_TYPE_FLOATING,
+       CONST_TYPE_ENUMERATION
+};
+
+struct constant {
+       enum constant_type type;
+
+       union {
+               struct integer_constant *iconst;
+               struct character_constant *cconst;
+               struct floating_constant *fconst;
+               struct enumeration_constant *econst;
+       } data;
+};
+
+struct identifier {
+       struct token *token;
+};
+
 struct type_qualifier {
         struct token *token;
 };
@@ -20,16 +97,59 @@ enum type_specifier_type {
         TYPE_SPECIFIER_TYPEDEF
 };
 
-struct struct_specifier {
-        struct token *token;
+enum sq_list_type {
+       SQ_LIST_TYPE_INVALID,
+       SQ_LIST_TYPE_SPECIFIER_LIST,
+       SQ_LIST_TYPE_QUALIFIER_LIST
+};
+
+struct specifier_qualifier_list {
+       enum sq_list_type type;
+
+       union {
+               struct type_specifier *tspec;
+               struct type_qualifier *tqual;
+       } data;
+
+       struct specifier_qualifier_list *next;
+};
+
+struct struct_declarator_list {
+       struct struct_declarator *sdecl;
+       struct struct_declarator_list *next;
+};
+
+struct struct_declaration {
+       struct specifier_qualifier_list *sqlist;
+       struct struct_declarator_list *sdecl;
 };
 
-struct union_specifier {
+struct struct_declaration_list {
+       struct struct_declaration *decl;
+       struct struct_declaration_list *next;
+};
+
+struct struct_union_specifier {
         struct token *token;
+       struct identifier *identifier;
+       struct struct_declaration_list *sdecl;
+};
+
+struct enumerator {
+       struct identifier *identifier;
+       struct token *eq;
+       struct constant_expression *cexpr;
+};
+
+struct enumerator_list {
+       struct enumerator *en;
+       struct enumerator_list *next;
 };
 
 struct enum_specifier {
         struct token *token;
+       struct identifier *identifier;
+       struct enumerator_list *enum_list;
 };
 
 struct typedef_name {
@@ -101,6 +221,13 @@ struct translation_unit {
         struct external_declaration *decl;
 };
 
+struct primary_expression *primary_expression_new(void);
+struct integer_constant *integer_constant_new(void);
+struct character_constant *character_constant_new(void);
+struct floating_constant *floating_constant_new(void);
+struct enumeration_constant *enumeration_constant_new(void);
+struct argument_expression_list *argument_expression_list_new(void);
+
 struct function_definition *function_definition_new(void);
 
 struct type_qualifier *type_qualifier_new(struct token*);
@@ -114,4 +241,12 @@ struct external_declaration *external_declaration_new(void);
 struct declaration_specifiers* declaration_specifiers_new(void);
 void declaration_specifiers_debug(struct declaration_specifiers*);
 
+struct constant *constant_new(void);
+struct integer_constant *integer_constant_new(void);
+struct character_constant *character_constant_new(void);
+struct floating_constant *floating_constant_new(void);
+struct enumeration_constant *enueration_constant_new(void);
+
+void constant_debug(struct constant*);
+
 #endif /* GRAMMAR_H */
index b3295212584f310509224fa9bccfbc5d4262f6e7..af8d58948db03b21f8fdd0265c80b963558efdb5 100644 (file)
@@ -354,3 +354,154 @@ struct translation_unit *parse_translation_unit(struct translation_unit *unit)
 
        return(ret_val);
 }
+
+struct constant *parse_constant(void)
+{
+       struct constant *c;
+
+       c = constant_new();
+
+       if(!c) {
+               goto gtfo;
+       }
+
+       if((c->data.iconst = parse_integer_constant())) {
+               c->type = CONST_TYPE_INTEGER;
+               goto gtfo;
+       }
+
+       if((c->data.cconst = parse_character_constant())) {
+               c->type = CONST_TYPE_CHARACTER;
+               goto gtfo;
+       }
+
+       if((c->data.fconst = parse_floating_constant())) {
+               c->type = CONST_TYPE_FLOATING;
+               goto gtfo;
+       }
+
+       if((c->data.econst = parse_enumeration_constant())) {
+               c->type = CONST_TYPE_ENUMERATION;
+               goto gtfo;
+       }
+
+       /* couldn't parse any of the constant types */
+       free(c);
+       c = NULL;
+
+gtfo:
+       return(c);
+}
+
+struct integer_constant *parse_integer_constant(void)
+{
+       struct integer_constant *ic;
+       int pos;
+
+       ic = integer_constant_new();
+       pos = lex_getpos();
+
+       if(!ic) {
+               return(NULL);
+       }
+
+       ic->token = lex_gettoken();
+
+       if(!ic->token || ic->token->type != TOKEN_NUMBER) {
+               lex_setpos(pos);
+               free(ic);
+               return(NULL);
+       }
+
+       /* we have a valid integer constant - check if there is a suffix */
+
+       pos = lex_getpos();
+       ic->suffix = lex_gettoken();
+
+       if(ic->suffix &&
+          token_cmp(ic->suffix, "U") != 0 &&
+          token_cmp(ic->suffix, "L") != 0 &&
+          token_cmp(ic->suffix, "UL") != 0 &&
+          token_cmp(ic->suffix, "LL") != 0 &&
+          token_cmp(ic->suffix, "ULL") != 0) {
+               /*
+                * We have a token, but it's neither U, L, UL, LL, nor ULL,
+                * so we return what we had without the suffix
+                */
+               ic->suffix = NULL;
+               lex_setpos(pos);
+       }
+
+       return(ic);
+}
+
+struct character_constant *parse_character_constant(void)
+{
+       struct character_constant *cc;
+       int pos;
+
+       cc = character_constant_new();
+
+       if(!cc) {
+               return(NULL);
+       }
+
+       pos = lex_getpos();
+       cc->prefix = lex_gettoken();
+
+       if(!cc->prefix || cc->prefix->type != TOKEN_IDENTIFIER ||
+          token_cmp(cc->prefix, "L") != 0) {
+               lex_setpos(pos);
+               cc->prefix = NULL;
+       }
+
+       cc->token = lex_gettoken();
+
+       if(!cc->token || cc->token->type != TOKEN_CHAR_LITERAL) {
+               lex_setpos(pos);
+               free(cc);
+               cc = NULL;
+       }
+
+       return(cc);
+}
+
+struct floating_constant *parse_floating_constant(void)
+{
+       struct floating_constant *fc;
+       int pos;
+
+       fc = floating_constant_new();
+
+       if(!fc) {
+               return(NULL);
+       }
+
+       pos = lex_getpos();
+       fc->token = lex_gettoken();
+
+       if(!fc->token || fc->token->type != TOKEN_FLOAT_LITERAL) {
+               lex_setpos(pos);
+               free(fc);
+               fc = NULL;
+       } else {
+               pos = lex_getpos();
+               fc->suffix = lex_gettoken();
+
+               if(fc->suffix &&
+                  token_cmp(fc->suffix, "f") != 0 &&
+                  token_cmp(fc->suffix, "l") != 0 &&
+                  token_cmp(fc->suffix, "F") != 0 &&
+                  token_cmp(fc->suffix, "L") != 0) {
+                       lex_setpos(pos);
+                       fc->suffix = NULL;
+               }
+       }
+
+       return(fc);
+}
+
+struct enumeration_constant *parse_enumeration_constant(void)
+{
+       return(NULL);
+}