Trying to disambiguate labels

This commit is contained in:
Pierre Pronchery 2008-06-12 05:40:21 +00:00
parent 50693c80b8
commit 8c15dc13e9
2 changed files with 70 additions and 92 deletions

View File

@ -40,14 +40,14 @@
/* private */ /* private */
/* prototypes */ /* 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, static int _parse_check_set(C99 * c99, TokenSet set, char const * name,
int (*callback)(C99 * c99)); int (*callback)(C99 * c99));
static int _parse_error(C99 * c99, char const * format, ...); static int _parse_error(C99 * c99, char const * format, ...);
static int _parse_get_code(C99 * c99); static int _parse_get_code(C99 * c99);
static char const * _parse_get_string(C99 * c99); static char const * _parse_get_string(C99 * c99);
static int _parse_in_set(C99 * c99, TokenSet set); 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); static int _parse_skip(C99 * c99, TokenSet set);
/* grammar */ /* grammar */
@ -126,7 +126,7 @@ static int _designator(C99 * c99);
/* functions */ /* functions */
/* parse_check */ /* parse_check */
static int _parse_check(C99 * c99, TokenCode code) static int _parse_check(C99 * c99, C99Code code)
{ {
int ret = 0; int ret = 0;
@ -202,7 +202,7 @@ static int _parse_in_set(C99 * c99, TokenSet set)
/* parse_is_code */ /* 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) if(c99->token == NULL)
return 0; return 0;
@ -357,23 +357,6 @@ static int _declaration_do(C99 * c99)
{ {
int ret; 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 = _parse_check(c99, C99_CODE_OPERATOR_SEMICOLON);
ret |= code_context_set(c99->code, CODE_CONTEXT_DECLARATION_END); ret |= code_context_set(c99->code, CODE_CONTEXT_DECLARATION_END);
return ret; return ret;
@ -416,19 +399,31 @@ static int _declaration_specifiers(C99 * c99)
static int _storage_class_specifier(C99 * c99) static int _storage_class_specifier(C99 * c99)
/* "typedef" | "extern" | "static" | "auto" | "register" */ /* "typedef" | "extern" | "static" | "auto" | "register" */
{ {
int ret = 0; int ret;
CodeStorage storage = CODE_STORAGE_NULL;
DEBUG_GRAMMAR(); DEBUG_GRAMMAR();
switch(_parse_get_code(c99)) switch(_parse_get_code(c99))
{ {
case C99_CODE_KEYWORD_TYPEDEF: case C99_CODE_KEYWORD_TYPEDEF:
ret |= code_context_set_storage(c99->code, storage = CODE_STORAGE_TYPEDEF;
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; break;
/* FIXME implement the others */
default: default:
break; break;
} }
ret = code_context_set_storage(c99->code, storage);
ret |= scan(c99); ret |= scan(c99);
return ret; return ret;
} }
@ -464,7 +459,7 @@ static int _struct_or_union_specifier(C99 * c99)
{ {
int ret; int ret;
CodeContext context; CodeContext context;
TokenCode code; C99Code code;
DEBUG_GRAMMAR(); DEBUG_GRAMMAR();
context = code_context_get(c99->code); context = code_context_get(c99->code);
@ -869,10 +864,6 @@ static int _abstract_or_declarator(C99 * c99)
DEBUG_GRAMMAR(); DEBUG_GRAMMAR();
if(_parse_in_set(c99, c99set_pointer)) if(_parse_in_set(c99, c99set_pointer))
ret |= _pointer(c99); 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)) if(_parse_is_code(c99, C99_CODE_IDENTIFIER))
return ret | _direct_declarator(c99); return ret | _direct_declarator(c99);
/* FIXME there is still an ambiguity with "(" */ /* FIXME there is still an ambiguity with "(" */
@ -906,7 +897,7 @@ static int _direct_abstract_declarator(C99 * c99)
{ {
int ret = 0; int ret = 0;
TokenCode code; C99Code code;
/* FIXME verify if correct */ /* FIXME verify if correct */
DEBUG_GRAMMAR(); DEBUG_GRAMMAR();
@ -953,19 +944,7 @@ static int _assignment_expr(C99 * c99)
int ret = 0; int ret = 0;
DEBUG_GRAMMAR(); DEBUG_GRAMMAR();
/* FIXME conflict between unary and conditional */ /* FIXME hack around the 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 */
for(;;) for(;;)
{ {
ret |= _conditional_expr(c99); ret |= _conditional_expr(c99);
@ -973,15 +952,6 @@ static int _assignment_expr(C99 * c99)
return ret; return ret;
ret |= _assignment_operator(c99); 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; return ret;
} }
@ -1022,7 +992,7 @@ static int _unary_expr(C99 * c99)
if(_parse_is_code(c99, C99_CODE_OPERATOR_LPAREN)) if(_parse_is_code(c99, C99_CODE_OPERATOR_LPAREN))
{ {
ret |= scan(c99); 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)) if(_parse_in_set(c99, c99set_type_name))
ret |= _type_name(c99); ret |= _type_name(c99);
else else
@ -1050,8 +1020,7 @@ static int _postfix_expr(C99 * c99)
* postfix-expr "->" identifier * postfix-expr "->" identifier
* postfix-expr "++" * postfix-expr "++"
* postfix-expr "--" * postfix-expr "--"
* "(" type-name ")" "{" initializer-list "}" * "(" type-name ")" "{" initializer-list [ "," ] "}" */
* "(" type-name ")" "{" initializer-list "," "}" */
{ {
int ret = 0; int ret = 0;
int code; int code;
@ -1140,24 +1109,27 @@ static int _primary_expr(C99 * c99)
int ret; int ret;
int code; int code;
/* FIXME complete */
DEBUG_GRAMMAR(); DEBUG_GRAMMAR();
code_context_set(c99->code, CODE_CONTEXT_PRIMARY_EXPR); code_context_set(c99->code, CODE_CONTEXT_PRIMARY_EXPR);
/* FIXME use _parse_get_code() */ if((code = token_get_code(c99->token)) == C99_CODE_IDENTIFIER)
if(c99->token == NULL) {
return _parse_error(c99, "Unexpected end of file"); ret |= _identifier(c99);
else if((code = token_get_code(c99->token)) == C99_CODE_IDENTIFIER) if(c99->can_label && _parse_is_code(c99,
return _identifier(c99); C99_CODE_OPERATOR_COLON))
/* handle this as a labeled_statement */
c99->is_label = 1;
}
else if(code == C99_CODE_OPERATOR_LPAREN) else if(code == C99_CODE_OPERATOR_LPAREN)
{ {
ret = scan(c99); ret = scan(c99);
ret |= _parse_check_set(c99, c99set_expression, "expression", ret |= _parse_check_set(c99, c99set_expression, "expression",
_expression); _expression);
ret |= _parse_check(c99, C99_CODE_OPERATOR_RPAREN); ret |= _parse_check(c99, C99_CODE_OPERATOR_RPAREN);
return ret;
} }
else /* constant or string-litteral */ 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 */ * jump-statement */
{ {
DEBUG_GRAMMAR(); DEBUG_GRAMMAR();
#if 0 if(_parse_in_set(c99, c99set_labeled_statement))
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))
return _labeled_statement(c99); return _labeled_statement(c99);
else if(_parse_in_set(c99, c99set_compound_statement)) else if(_parse_in_set(c99, c99set_compound_statement))
return _compound_statement(c99); return _compound_statement(c99);
@ -1542,25 +1509,27 @@ static int _statement(C99 * c99)
* PRE the first token starts a labeled-statement */ * PRE the first token starts a labeled-statement */
static int _labeled_statement(C99 * c99) static int _labeled_statement(C99 * c99)
/* identifier ":" statement /* identifier ":" statement
* case constant-expr ":" statement * "case" constant-expr ":" statement
* default ":" statement */ * "default" ":" statement */
{ {
int ret; int ret = 0;
int code; C99Code code;
DEBUG_GRAMMAR(); DEBUG_GRAMMAR();
/* FIXME use _parse_get_code() */ if((code = _parse_get_code(c99)) == C99_CODE_IDENTIFIER)
if(c99->token == NULL) ret |= _identifier(c99);
return _parse_error(c99, "Unexpected end of file"); else
if((code = token_get_code(c99->token)) == C99_CODE_IDENTIFIER)
ret = _identifier(c99);
else if(code == C99_CODE_KEYWORD_CASE)
{ {
ret = scan(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); ret |= _constant_expr(c99);
} }
else /* default */ else /* default */
ret = scan(c99); ret |= scan(c99);
}
ret |= _parse_check(c99, C99_CODE_OPERATOR_COLON); ret |= _parse_check(c99, C99_CODE_OPERATOR_COLON);
ret |= _parse_check_set(c99, c99set_statement, "statement", _statement); ret |= _parse_check_set(c99, c99set_statement, "statement", _statement);
return ret; return ret;
@ -1577,15 +1546,27 @@ static int _constant_expr(C99 * c99)
/* expression-statement /* 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) static int _expression_statement(C99 * c99)
/* [ expression ] ";" */ /* [ expression ] ";"
* identifier ":" */
{ {
int ret = 0; int ret = 0;
DEBUG_GRAMMAR(); DEBUG_GRAMMAR();
if(_parse_in_set(c99, c99set_expression)) if(_parse_in_set(c99, c99set_expression))
{
c99->can_label = 1;
c99->is_label = 0;
ret = _expression(c99); ret = _expression(c99);
}
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); ret |= _parse_check(c99, C99_CODE_OPERATOR_SEMICOLON);
return ret; return ret;
} }
@ -1709,10 +1690,7 @@ static int _jump_statement(C99 * c99)
int code; int code;
DEBUG_GRAMMAR(); DEBUG_GRAMMAR();
/* FIXME use _parse_get_code() */ if((code = token_get_code(c99->token)) == C99_CODE_KEYWORD_GOTO)
if(c99->token == NULL)
return _parse_error(c99, "Unexpected end of file");
else if((code = token_get_code(c99->token)) == C99_CODE_KEYWORD_GOTO)
{ {
ret = scan(c99); ret = scan(c99);
ret |= _parse_check_set(c99, c99set_identifier, "identifier", ret |= _parse_check_set(c99, c99set_identifier, "identifier",

View File

@ -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_CASE,
C99_CODE_KEYWORD_DEFAULT, C99_CODE_KEYWORD_DEFAULT,