From ee7fe757cfef58eb38195c775abcc5f82240c6d3 Mon Sep 17 00:00:00 2001 From: Matthias Kruk Date: Sat, 4 Jul 2020 17:50:22 +0900 Subject: [PATCH] parser: Implement parsing of integer, character, and floating point constants --- src/grammar.c | 135 ++++++++++++++++++++++++++++++++++++++++++++ src/grammar.h | 141 +++++++++++++++++++++++++++++++++++++++++++++- src/parser.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 424 insertions(+), 3 deletions(-) diff --git a/src/grammar.c b/src/grammar.c index a41f21b..612357b 100644 --- a/src/grammar.c +++ b/src/grammar.c @@ -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; +} diff --git a/src/grammar.h b/src/grammar.h index 38ece37..b6208d3 100644 --- a/src/grammar.h +++ b/src/grammar.h @@ -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 */ diff --git a/src/parser.c b/src/parser.c index b329521..af8d589 100644 --- a/src/parser.c +++ b/src/parser.c @@ -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); +} -- 2.47.3