From 8c15dc13e9bae6849eecae6907e4fcc618325206 Mon Sep 17 00:00:00 2001 From: Pierre Pronchery Date: Thu, 12 Jun 2008 05:40:21 +0000 Subject: [PATCH] Trying to disambiguate labels --- src/parser.c | 160 ++++++++++++++------------------- src/sets/labeled_statement.set | 2 +- 2 files changed, 70 insertions(+), 92 deletions(-) diff --git a/src/parser.c b/src/parser.c index eb48cbb..ef841b1 100644 --- a/src/parser.c +++ b/src/parser.c @@ -40,14 +40,14 @@ /* private */ /* prototypes */ -static int _parse_check(C99 * c99, TokenCode code); +static int _parse_check(C99 * c99, C99Code code); static int _parse_check_set(C99 * c99, TokenSet set, char const * name, int (*callback)(C99 * c99)); static int _parse_error(C99 * c99, char const * format, ...); static int _parse_get_code(C99 * c99); static char const * _parse_get_string(C99 * c99); static int _parse_in_set(C99 * c99, TokenSet set); -static int _parse_is_code(C99 * c99, TokenCode code); +static int _parse_is_code(C99 * c99, C99Code code); static int _parse_skip(C99 * c99, TokenSet set); /* grammar */ @@ -126,7 +126,7 @@ static int _designator(C99 * c99); /* functions */ /* parse_check */ -static int _parse_check(C99 * c99, TokenCode code) +static int _parse_check(C99 * c99, C99Code code) { int ret = 0; @@ -202,7 +202,7 @@ static int _parse_in_set(C99 * c99, TokenSet set) /* parse_is_code */ -static int _parse_is_code(C99 * c99, TokenCode code) +static int _parse_is_code(C99 * c99, C99Code code) { if(c99->token == NULL) return 0; @@ -357,23 +357,6 @@ static int _declaration_do(C99 * c99) { int ret; -#if 0 - if(c99->typedef_flag) - { - c99->typedef_flag = 0; - if(c99->identifier == NULL) - return _parse_error(c99, "%s", "DEBUG: typedef without" - " identifier"); - /* FIXME keep the actual token */ - if(code_type_add(c99->code, token_get_filename(c99->token), - token_get_line(c99->token), - c99->identifier) < 0) - return _parse_error(c99, "%s", error_get()); - } - else if(code_variable_add(c99->code, c99->identifier) != 0) - return _parse_error(c99, "%s", error_get()); - return 0; -#endif ret = _parse_check(c99, C99_CODE_OPERATOR_SEMICOLON); ret |= code_context_set(c99->code, CODE_CONTEXT_DECLARATION_END); return ret; @@ -416,19 +399,31 @@ static int _declaration_specifiers(C99 * c99) static int _storage_class_specifier(C99 * c99) /* "typedef" | "extern" | "static" | "auto" | "register" */ { - int ret = 0; + int ret; + CodeStorage storage = CODE_STORAGE_NULL; DEBUG_GRAMMAR(); switch(_parse_get_code(c99)) { case C99_CODE_KEYWORD_TYPEDEF: - ret |= code_context_set_storage(c99->code, - CODE_STORAGE_TYPEDEF); + storage = CODE_STORAGE_TYPEDEF; + break; + case C99_CODE_KEYWORD_EXTERN: + storage = CODE_STORAGE_EXTERN; + break; + case C99_CODE_KEYWORD_STATIC: + storage = CODE_STORAGE_STATIC; + break; + case C99_CODE_KEYWORD_AUTO: + storage = CODE_STORAGE_AUTO; + break; + case C99_CODE_KEYWORD_REGISTER: + storage = CODE_STORAGE_REGISTER; break; - /* FIXME implement the others */ default: break; } + ret = code_context_set_storage(c99->code, storage); ret |= scan(c99); return ret; } @@ -464,7 +459,7 @@ static int _struct_or_union_specifier(C99 * c99) { int ret; CodeContext context; - TokenCode code; + C99Code code; DEBUG_GRAMMAR(); context = code_context_get(c99->code); @@ -869,10 +864,6 @@ static int _abstract_or_declarator(C99 * c99) DEBUG_GRAMMAR(); if(_parse_in_set(c99, c99set_pointer)) ret |= _pointer(c99); -#if 0 - fprintf(stderr, "DEBUG: before 4, %d %d\n", C99_CODE_IDENTIFIER, - token_get_code(c99->token)); -#endif if(_parse_is_code(c99, C99_CODE_IDENTIFIER)) return ret | _direct_declarator(c99); /* FIXME there is still an ambiguity with "(" */ @@ -906,7 +897,7 @@ static int _direct_abstract_declarator(C99 * c99) { int ret = 0; - TokenCode code; + C99Code code; /* FIXME verify if correct */ DEBUG_GRAMMAR(); @@ -953,19 +944,7 @@ static int _assignment_expr(C99 * c99) int ret = 0; DEBUG_GRAMMAR(); - /* FIXME conflict between unary and conditional */ -#if 0 - while(_parse_in_set(c99, c99set_unary_expr)) - { - ret |= _unary_expr(c99); - ret |= _assignment_operator(c99); - } -#endif -#if 0 - ret |= _conditional_expr(c99); -#endif -#if 0 - /* FIXME check is this solves the conflict somehow */ + /* FIXME hack around the conflict between unary and conditional */ for(;;) { ret |= _conditional_expr(c99); @@ -973,15 +952,6 @@ static int _assignment_expr(C99 * c99) return ret; ret |= _assignment_operator(c99); } -#endif - for(;;) - { - ret |= _conditional_expr(c99); - if(!_parse_in_set(c99, c99set_assignment_operator)) - return ret; - ret |= _parse_check_set(c99, c99set_assignment_operator, - "assignment operator", _assignment_operator); - } return ret; } @@ -1022,7 +992,7 @@ static int _unary_expr(C99 * c99) if(_parse_is_code(c99, C99_CODE_OPERATOR_LPAREN)) { ret |= scan(c99); - /* FIXME it may still be an unary-expr */ + /* FIXME it may still be an unary-expr ("{") */ if(_parse_in_set(c99, c99set_type_name)) ret |= _type_name(c99); else @@ -1050,8 +1020,7 @@ static int _postfix_expr(C99 * c99) * postfix-expr "->" identifier * postfix-expr "++" * postfix-expr "--" - * "(" type-name ")" "{" initializer-list "}" - * "(" type-name ")" "{" initializer-list "," "}" */ + * "(" type-name ")" "{" initializer-list [ "," ] "}" */ { int ret = 0; int code; @@ -1140,24 +1109,27 @@ static int _primary_expr(C99 * c99) int ret; int code; - /* FIXME complete */ DEBUG_GRAMMAR(); code_context_set(c99->code, CODE_CONTEXT_PRIMARY_EXPR); - /* FIXME use _parse_get_code() */ - if(c99->token == NULL) - return _parse_error(c99, "Unexpected end of file"); - else if((code = token_get_code(c99->token)) == C99_CODE_IDENTIFIER) - return _identifier(c99); + if((code = token_get_code(c99->token)) == C99_CODE_IDENTIFIER) + { + ret |= _identifier(c99); + if(c99->can_label && _parse_is_code(c99, + C99_CODE_OPERATOR_COLON)) + /* handle this as a labeled_statement */ + c99->is_label = 1; + } else if(code == C99_CODE_OPERATOR_LPAREN) { ret = scan(c99); ret |= _parse_check_set(c99, c99set_expression, "expression", _expression); ret |= _parse_check(c99, C99_CODE_OPERATOR_RPAREN); - return ret; } else /* constant or string-litteral */ - return scan(c99); + ret = scan(c99); + c99->can_label = 0; + return ret; } @@ -1516,12 +1488,7 @@ static int _statement(C99 * c99) * jump-statement */ { DEBUG_GRAMMAR(); -#if 0 - fprintf(stderr, "DEBUG: in_switch=%d %d case=%d\n", c99->in_switch, - _parse_get_code(c99), C99_CODE_KEYWORD_CASE); -#endif - /* FIXME labeled and expression statements conflict */ - if(c99->in_switch && _parse_in_set(c99, c99set_labeled_statement)) + if(_parse_in_set(c99, c99set_labeled_statement)) return _labeled_statement(c99); else if(_parse_in_set(c99, c99set_compound_statement)) return _compound_statement(c99); @@ -1542,25 +1509,27 @@ static int _statement(C99 * c99) * PRE the first token starts a labeled-statement */ static int _labeled_statement(C99 * c99) /* identifier ":" statement - * case constant-expr ":" statement - * default ":" statement */ + * "case" constant-expr ":" statement + * "default" ":" statement */ { - int ret; - int code; + int ret = 0; + C99Code code; DEBUG_GRAMMAR(); - /* FIXME use _parse_get_code() */ - if(c99->token == NULL) - return _parse_error(c99, "Unexpected end of file"); - if((code = token_get_code(c99->token)) == C99_CODE_IDENTIFIER) - ret = _identifier(c99); - else if(code == C99_CODE_KEYWORD_CASE) + if((code = _parse_get_code(c99)) == C99_CODE_IDENTIFIER) + ret |= _identifier(c99); + else { - ret = scan(c99); - ret |= _constant_expr(c99); + if(!c99->in_switch) + ret |= _parse_error(c99, "Not in a switch"); + if(code == C99_CODE_KEYWORD_CASE) + { + ret |= scan(c99); + ret |= _constant_expr(c99); + } + else /* default */ + ret |= scan(c99); } - else /* default */ - ret = scan(c99); ret |= _parse_check(c99, C99_CODE_OPERATOR_COLON); ret |= _parse_check_set(c99, c99set_statement, "statement", _statement); return ret; @@ -1577,16 +1546,28 @@ static int _constant_expr(C99 * c99) /* expression-statement - * PRE the first token starts an expression-statement */ + * PRE the first token starts an expression-statement or a label */ static int _expression_statement(C99 * c99) - /* [ expression ] ";" */ + /* [ expression ] ";" + * identifier ":" */ { int ret = 0; DEBUG_GRAMMAR(); if(_parse_in_set(c99, c99set_expression)) + { + c99->can_label = 1; + c99->is_label = 0; ret = _expression(c99); - ret |= _parse_check(c99, C99_CODE_OPERATOR_SEMICOLON); + } + if(c99->is_label) + { + ret |= code_context_set(c99->code, CODE_CONTEXT_LABEL); + ret |= _parse_check(c99, C99_CODE_OPERATOR_COLON); + c99->is_label = 0; + } + else + ret |= _parse_check(c99, C99_CODE_OPERATOR_SEMICOLON); return ret; } @@ -1709,10 +1690,7 @@ static int _jump_statement(C99 * c99) int code; DEBUG_GRAMMAR(); - /* FIXME use _parse_get_code() */ - if(c99->token == NULL) - return _parse_error(c99, "Unexpected end of file"); - else if((code = token_get_code(c99->token)) == C99_CODE_KEYWORD_GOTO) + if((code = token_get_code(c99->token)) == C99_CODE_KEYWORD_GOTO) { ret = scan(c99); ret |= _parse_check_set(c99, c99set_identifier, "identifier", diff --git a/src/sets/labeled_statement.set b/src/sets/labeled_statement.set index 0cbf8ad..c23e176 100644 --- a/src/sets/labeled_statement.set +++ b/src/sets/labeled_statement.set @@ -1,3 +1,3 @@ -#include "identifier.set" +/* XXX "identifier.set" is handled in expression_or_labeled_statement instead */ C99_CODE_KEYWORD_CASE, C99_CODE_KEYWORD_DEFAULT,