parser rewrite according to ANSI C grammar

same problem as before - conflict in IDENTIFIER as a type name versus an actual identifier
This commit is contained in:
Josh Holtrop 2018-05-07 23:48:08 -04:00
parent a7d63e51e5
commit 895ea27016
2 changed files with 587 additions and 504 deletions

View File

@ -31,111 +31,111 @@ void handle_loc(const char * input);
%% %%
\+ return TOK_PLUS; \+ return PLUS;
- return TOK_MINUS; - return MINUS;
\* return TOK_TIMES; \* return TIMES;
\/ return TOK_DIVIDE; \/ return DIVIDE;
% return TOK_MOD; % return MOD;
\^ return TOK_XOR; \^ return XOR;
= return TOK_ASSIGN; = return ASSIGN;
== return TOK_EQUALS; == return EQUALS;
!= return TOK_NOTEQUALS; != return NOTEQUALS;
\< return TOK_LESS; \< return LESS;
\<= return TOK_LESSEQ; \<= return LESSEQ;
\> return TOK_GREATER; \> return GREATER;
\>= return TOK_GREATEREQ; \>= return GREATEREQ;
&& return TOK_AND; && return AND;
\|\| return TOK_OR; \|\| return OR;
! return TOK_NOT; ! return NOT;
& return TOK_BITAND; & return BITAND;
\| return TOK_BITOR; \| return BITOR;
~ return TOK_BITNOT; ~ return BITNOT;
\+\+ return TOK_INCREMENT; \+\+ return INCREMENT;
-- return TOK_DECREMENT; -- return DECREMENT;
\<\< return TOK_LSHIFT; \<\< return LSHIFT;
\>\> return TOK_RSHIFT; \>\> return RSHIFT;
\+= return TOK_PLUSEQUALS; \+= return ADD_ASSIGN;
-= return TOK_MINUSEQUALS; -= return SUB_ASSIGN;
\*= return TOK_TIMESEQUALS; \*= return MUL_ASSIGN;
\/= return TOK_DIVIDEEQUALS; \/= return DIV_ASSIGN;
%= return TOK_MODEQUALS; %= return MOD_ASSIGN;
\^= return TOK_XOREQUALS; \^= return XOR_ASSIGN;
\<\<= return TOK_LSHIFTEQUALS; \<\<= return LEFT_ASSIGN;
\>\>= return TOK_RSHIFTEQUALS; \>\>= return RIGHT_ASSIGN;
&= return TOK_BITANDEQUALS; &= return AND_ASSIGN;
\|= return TOK_BITOREQUALS; \|= return OR_ASSIGN;
; return TOK_SEMICOLON; ; return SEMICOLON;
: return TOK_COLON; : return COLON;
\? return TOK_QUESTION; \? return QUESTION;
\. return TOK_DOT; \. return DOT;
-\> return TOK_ARROW; -\> return ARROW;
, return TOK_COMMA; , return COMMA;
\.\.\. return TOK_ELLIPSES; \.\.\. return ELLIPSIS;
\{ return TOK_LCURLY; \{ return LCURLY;
\} return TOK_RCURLY; \} return RCURLY;
\[ return TOK_LBRACKET; \[ return LBRACKET;
\] return TOK_RBRACKET; \] return RBRACKET;
\( return TOK_LPAREN; \( return LPAREN;
\) return TOK_RPAREN; \) return RPAREN;
void return TOK_VOID; void return VOID;
char return TOK_CHAR; char return CHAR;
short return TOK_SHORT; short return SHORT;
int return TOK_INT; int return INT;
long return TOK_LONG; long return LONG;
float return TOK_FLOAT; float return FLOAT;
double return TOK_DOUBLE; double return DOUBLE;
signed return TOK_SIGNED; signed return SIGNED;
unsigned return TOK_UNSIGNED; unsigned return UNSIGNED;
volatile return TOK_VOLATILE; volatile return VOLATILE;
static return TOK_STATIC; static return STATIC;
const return TOK_CONST; const return CONST;
extern return TOK_EXTERN; extern return EXTERN;
auto return TOK_AUTO; auto return AUTO;
register return TOK_REGISTER; register return REGISTER;
inline return TOK_INLINE; inline return INLINE;
struct return TOK_STRUCT; struct return STRUCT;
union return TOK_UNION; union return UNION;
enum return TOK_ENUM; enum return ENUM;
typedef return TOK_TYPEDEF; typedef return TYPEDEF;
if return TOK_IF; if return IF;
else return TOK_ELSE; else return ELSE;
while return TOK_WHILE; while return WHILE;
for return TOK_FOR; for return FOR;
do return TOK_DO; do return DO;
goto return TOK_GOTO; goto return GOTO;
return return TOK_RETURN; return return RETURN;
switch return TOK_SWITCH; switch return SWITCH;
case return TOK_CASE; case return CASE;
default return TOK_DEFAULT; default return DEFAULT;
break return TOK_BREAK; break return BREAK;
continue return TOK_CONTINUE; continue return CONTINUE;
sizeof return TOK_SIZEOF; sizeof return SIZEOF;
L?'[^\\]' return TOK_CHAR_CONST; L?'[^\\]' return CHAR_CONST;
L?'\\.' return TOK_CHAR_CONST; L?'\\.' return CHAR_CONST;
L?'\\a' (void)'\a'; return TOK_CHAR_CONST; L?'\\a' (void)'\a'; return CHAR_CONST;
L?'\\b' (void)'\b'; return TOK_CHAR_CONST; L?'\\b' (void)'\b'; return CHAR_CONST;
L?'\\f' (void)'\f'; return TOK_CHAR_CONST; L?'\\f' (void)'\f'; return CHAR_CONST;
L?'\\n' (void)'\n'; return TOK_CHAR_CONST; L?'\\n' (void)'\n'; return CHAR_CONST;
L?'\\r' (void)'\r'; return TOK_CHAR_CONST; L?'\\r' (void)'\r'; return CHAR_CONST;
L?'\\t' (void)'\t'; return TOK_CHAR_CONST; L?'\\t' (void)'\t'; return CHAR_CONST;
L?'\\v' (void)'\v'; return TOK_CHAR_CONST; L?'\\v' (void)'\v'; return CHAR_CONST;
L?'\\x[0-9A-Fa-f]{2}' return TOK_CHAR_CONST; L?'\\x[0-9A-Fa-f]{2}' return CHAR_CONST;
L?'\\[0-7]{1,3}' return TOK_CHAR_CONST; L?'\\[0-7]{1,3}' return CHAR_CONST;
[0-9]+([uU][lL]?[lL]?)? return TOK_INT_CONST; [0-9]+([uU][lL]?[lL]?)? return INT_CONST;
0[xX][0-9a-fA-F]+([uU][lL]?[lL]?)? return TOK_INT_CONST; 0[xX][0-9a-fA-F]+([uU][lL]?[lL]?)? return INT_CONST;
([0-9]+\.[0-9]*|\.[0-9]+)([eE][-+]?[0-9]+)?[fFlL]? return TOK_FLOAT_CONST; ([0-9]+\.[0-9]*|\.[0-9]+)([eE][-+]?[0-9]+)?[fFlL]? return FLOAT_CONST;
L?\" { L?\" {
if (build_string != NULL) if (build_string != NULL)
@ -148,7 +148,7 @@ L?\" {
<str>{ <str>{
\" { \" {
BEGIN(INITIAL); BEGIN(INITIAL);
return TOK_STR_CONST; return STRING_LITERAL;
} }
\\x[0-9A-Fa-f]{2} { \\x[0-9A-Fa-f]{2} {
/* hexadecimal escape code */ /* hexadecimal escape code */
@ -175,7 +175,7 @@ L?\" {
[^\\\"]+ String_concat(build_string, yytext); [^\\\"]+ String_concat(build_string, yytext);
} }
[a-zA-Z_][a-zA-Z_0-9]* return TOK_IDENTIFIER; [a-zA-Z_][a-zA-Z_0-9]* return IDENTIFIER;
^[ ]*#[ ]+[0-9]+[ ]+\".+\".*$ { ^[ ]*#[ ]+[0-9]+[ ]+\".+\".*$ {
handle_loc(yytext); handle_loc(yytext);

View File

@ -13,429 +13,512 @@ int yylex(YYSTYPE *, YYLTYPE *);
%locations %locations
%error-verbose %error-verbose
%token TOK_PLUS; %token PLUS;
%token TOK_MINUS; %token MINUS;
%token TOK_TIMES; %token TIMES;
%token TOK_DIVIDE; %token DIVIDE;
%token TOK_MOD; %token MOD;
%token TOK_XOR; %token XOR;
%token TOK_ASSIGN; %token ASSIGN;
%token TOK_EQUALS; %token EQUALS;
%token TOK_NOTEQUALS; %token NOTEQUALS;
%token TOK_LESS; %token LESS;
%token TOK_LESSEQ; %token LESSEQ;
%token TOK_GREATER; %token GREATER;
%token TOK_GREATEREQ; %token GREATEREQ;
%token TOK_AND; %token AND;
%token TOK_OR; %token OR;
%token TOK_NOT; %token NOT;
%token TOK_BITAND; %token BITAND;
%token TOK_BITOR; %token BITOR;
%token TOK_BITNOT; %token BITNOT;
%token TOK_INCREMENT %token INCREMENT
%token TOK_DECREMENT %token DECREMENT
%token TOK_LSHIFT %token LSHIFT
%token TOK_RSHIFT %token RSHIFT
%token TOK_PLUSEQUALS; %token ADD_ASSIGN;
%token TOK_MINUSEQUALS; %token SUB_ASSIGN;
%token TOK_TIMESEQUALS; %token MUL_ASSIGN;
%token TOK_DIVIDEEQUALS; %token DIV_ASSIGN;
%token TOK_MODEQUALS; %token MOD_ASSIGN;
%token TOK_XOREQUALS; %token XOR_ASSIGN;
%token TOK_LSHIFTEQUALS; %token LEFT_ASSIGN;
%token TOK_RSHIFTEQUALS; %token RIGHT_ASSIGN;
%token TOK_BITANDEQUALS; %token AND_ASSIGN;
%token TOK_BITOREQUALS; %token OR_ASSIGN;
%token TOK_SEMICOLON; %token SEMICOLON;
%token TOK_COLON; %token COLON;
%token TOK_QUESTION; %token QUESTION;
%token TOK_DOT; %token DOT;
%token TOK_ARROW; %token ARROW;
%token TOK_COMMA; %token COMMA;
%token TOK_ELLIPSES; %token ELLIPSIS;
%token TOK_LCURLY; %token LCURLY;
%token TOK_RCURLY; %token RCURLY;
%token TOK_LBRACKET; %token LBRACKET;
%token TOK_RBRACKET; %token RBRACKET;
%token TOK_LPAREN; %token LPAREN;
%token TOK_RPAREN; %token RPAREN;
%token TOK_VOID; %token VOID;
%token TOK_CHAR; %token CHAR;
%token TOK_SHORT; %token SHORT;
%token TOK_INT; %token INT;
%token TOK_LONG; %token LONG;
%token TOK_FLOAT; %token FLOAT;
%token TOK_DOUBLE; %token DOUBLE;
%token TOK_SIGNED; %token SIGNED;
%token TOK_UNSIGNED; %token UNSIGNED;
%token TOK_VOLATILE; %token VOLATILE;
%token TOK_STATIC; %token STATIC;
%token TOK_CONST; %token CONST;
%token TOK_EXTERN; %token EXTERN;
%token TOK_AUTO; %token AUTO;
%token TOK_REGISTER; %token REGISTER;
%token TOK_INLINE; %token INLINE;
%token TOK_STRUCT; %token STRUCT;
%token TOK_UNION; %token UNION;
%token TOK_ENUM; %token ENUM;
%token TOK_TYPEDEF; %token TYPEDEF;
%token TOK_IF; %token IF;
%token TOK_ELSE; %token ELSE;
%token TOK_WHILE; %token WHILE;
%token TOK_FOR; %token FOR;
%token TOK_DO; %token DO;
%token TOK_GOTO; %token GOTO;
%token TOK_RETURN; %token RETURN;
%token TOK_SWITCH; %token SWITCH;
%token TOK_CASE; %token CASE;
%token TOK_DEFAULT; %token DEFAULT;
%token TOK_BREAK; %token BREAK;
%token TOK_CONTINUE; %token CONTINUE;
%token TOK_SIZEOF; %token SIZEOF;
%token TOK_CHAR_CONST; %token CHAR_CONST;
%token TOK_INT_CONST; %token INT_CONST;
%token TOK_FLOAT_CONST; %token FLOAT_CONST;
%token TOK_STR_CONST; %token STRING_LITERAL;
%token TOK_IDENTIFIER; %token IDENTIFIER;
%start translation_unit
%% %%
translation_unit : constant
| external_decl : INT_CONST
| translation_unit external_decl | FLOAT_CONST
; | CHAR_CONST
;
external_decl : function_definition
| decl primary_expression
; : IDENTIFIER
| constant
function_definition : decl_specs declarator decl_list compound_stat | STRING_LITERAL
| declarator decl_list compound_stat | LPAREN expression RPAREN
| decl_specs declarator compound_stat ;
| declarator compound_stat
; postfix_expression
: primary_expression
decl : decl_specs init_declarator_list TOK_SEMICOLON | postfix_expression LBRACKET expression RBRACKET
| decl_specs TOK_SEMICOLON | postfix_expression LPAREN RPAREN
; | postfix_expression LPAREN argument_expression_list RPAREN
| postfix_expression DOT IDENTIFIER
decl_list : decl | postfix_expression ARROW IDENTIFIER
| decl_list decl | postfix_expression INCREMENT
; | postfix_expression DECREMENT
;
decl_specs : storage_class_spec decl_specs
| storage_class_spec argument_expression_list
| type_spec decl_specs : assignment_expression
| type_spec | argument_expression_list COMMA assignment_expression
| type_qualifier decl_specs ;
| type_qualifier
; unary_expression
: postfix_expression
storage_class_spec : TOK_AUTO | TOK_REGISTER | TOK_STATIC | TOK_EXTERN | TOK_TYPEDEF | INCREMENT unary_expression
; | DECREMENT unary_expression
| unary_operator cast_expression
type_spec : TOK_VOID | TOK_CHAR | TOK_SHORT | TOK_INT | TOK_LONG | TOK_FLOAT | SIZEOF unary_expression
| TOK_DOUBLE | TOK_SIGNED | TOK_UNSIGNED | SIZEOF LPAREN type_name RPAREN
| struct_or_union_spec ;
| enum_spec
| typedef_name unary_operator
; : BITAND
| TIMES
type_qualifier : TOK_CONST | TOK_VOLATILE | PLUS
; | MINUS
| BITNOT
struct_or_union_spec : struct_or_union TOK_IDENTIFIER TOK_LCURLY struct_decl_list TOK_RCURLY | NOT
| struct_or_union TOK_LCURLY struct_decl_list TOK_RCURLY ;
| struct_or_union TOK_IDENTIFIER
; cast_expression
: unary_expression
struct_or_union : TOK_STRUCT | TOK_UNION | LPAREN type_name RPAREN cast_expression
; ;
struct_decl_list : struct_decl multiplicative_expression
| struct_decl_list struct_decl : cast_expression
; | multiplicative_expression TIMES cast_expression
| multiplicative_expression DIVIDE cast_expression
init_declarator_list : init_declarator | multiplicative_expression MOD cast_expression
| init_declarator_list TOK_COMMA init_declarator ;
;
additive_expression
init_declarator : declarator : multiplicative_expression
| declarator TOK_ASSIGN initializer | additive_expression PLUS multiplicative_expression
; | additive_expression MINUS multiplicative_expression
;
struct_decl : spec_qualifier_list struct_declarator_list TOK_SEMICOLON
; shift_expression
: additive_expression
| shift_expression LSHIFT additive_expression
spec_qualifier_list : type_spec spec_qualifier_list | shift_expression RSHIFT additive_expression
| type_spec ;
| type_qualifier spec_qualifier_list
| type_qualifier relational_expression
; : shift_expression
| relational_expression LESS shift_expression
struct_declarator_list : struct_declarator | relational_expression GREATER shift_expression
| struct_declarator_list TOK_COMMA struct_declarator | relational_expression LESSEQ shift_expression
; | relational_expression GREATEREQ shift_expression
;
struct_declarator : declarator
| declarator TOK_COLON const_exp equality_expression
| TOK_COLON const_exp : relational_expression
; | equality_expression EQUALS relational_expression
| equality_expression NOTEQUALS relational_expression
enum_spec : TOK_ENUM TOK_IDENTIFIER TOK_LCURLY enumerator_list TOK_RCURLY ;
| TOK_ENUM TOK_LCURLY enumerator_list TOK_RCURLY
| TOK_ENUM TOK_IDENTIFIER and_expression
; : equality_expression
| and_expression BITAND equality_expression
enumerator_list : enumerator ;
| enumerator_list TOK_COMMA enumerator
; exclusive_or_expression
: and_expression
enumerator : TOK_IDENTIFIER | exclusive_or_expression XOR and_expression
| TOK_IDENTIFIER TOK_ASSIGN const_exp ;
;
inclusive_or_expression
declarator : pointer direct_declarator : exclusive_or_expression
| direct_declarator | inclusive_or_expression BITOR exclusive_or_expression
; ;
direct_declarator : TOK_IDENTIFIER logical_and_expression
| TOK_LPAREN declarator TOK_RPAREN : inclusive_or_expression
| direct_declarator TOK_LBRACKET const_exp TOK_RBRACKET | logical_and_expression AND inclusive_or_expression
| direct_declarator TOK_LBRACKET TOK_RBRACKET ;
| direct_declarator TOK_LPAREN param_type_list TOK_RPAREN
| direct_declarator TOK_LPAREN id_list TOK_RPAREN logical_or_expression
| direct_declarator TOK_LPAREN TOK_RPAREN : logical_and_expression
; | logical_or_expression OR logical_and_expression
;
pointer : TOK_TIMES type_qualifier_list
| TOK_TIMES conditional_expression
| TOK_TIMES type_qualifier_list pointer : logical_or_expression
| TOK_TIMES pointer | logical_or_expression QUESTION expression COLON conditional_expression
; ;
type_qualifier_list : type_qualifier assignment_expression
| type_qualifier_list type_qualifier : conditional_expression
; | unary_expression assignment_operator assignment_expression
;
param_type_list : param_list
| param_list TOK_COMMA TOK_ELLIPSES assignment_operator
; : ASSIGN
| MUL_ASSIGN
param_list : param_decl | DIV_ASSIGN
| param_list TOK_COMMA param_decl | MOD_ASSIGN
; | ADD_ASSIGN
| SUB_ASSIGN
param_decl : decl_specs declarator | LEFT_ASSIGN
| decl_specs abstract_declarator | RIGHT_ASSIGN
| decl_specs | AND_ASSIGN
; | XOR_ASSIGN
| OR_ASSIGN
id_list : TOK_IDENTIFIER ;
| id_list TOK_COMMA TOK_IDENTIFIER
; expression
: assignment_expression
initializer : assignment_exp | expression COMMA assignment_expression
| TOK_LCURLY initializer_list TOK_RCURLY ;
| TOK_LCURLY initializer_list TOK_COMMA TOK_RCURLY
; constant_expression
: conditional_expression
initializer_list : initializer ;
| initializer_list TOK_COMMA initializer
; declaration
: declaration_specifiers SEMICOLON
type_name : spec_qualifier_list abstract_declarator | declaration_specifiers init_declarator_list SEMICOLON
| spec_qualifier_list ;
;
declaration_specifiers
abstract_declarator : pointer : storage_class_specifier
| pointer direct_abstract_declarator | storage_class_specifier declaration_specifiers
| direct_abstract_declarator | type_specifier
; | type_specifier declaration_specifiers
| type_qualifier
direct_abstract_declarator: TOK_LPAREN abstract_declarator TOK_RPAREN | type_qualifier declaration_specifiers
| direct_abstract_declarator TOK_LBRACKET const_exp TOK_RBRACKET ;
| TOK_LBRACKET const_exp TOK_RBRACKET
| direct_abstract_declarator TOK_LBRACKET TOK_RBRACKET init_declarator_list
| TOK_LBRACKET TOK_RBRACKET : init_declarator
| direct_abstract_declarator TOK_LPAREN param_type_list TOK_RPAREN | init_declarator_list COMMA init_declarator
| TOK_LPAREN param_type_list TOK_RPAREN ;
| direct_abstract_declarator TOK_LPAREN TOK_RPAREN
| TOK_LPAREN TOK_RPAREN init_declarator
; : declarator
| declarator ASSIGN initializer
typedef_name : TOK_IDENTIFIER ;
;
storage_class_specifier
stat : labeled_stat : TYPEDEF
| exp_stat | EXTERN
| compound_stat | STATIC
| selection_stat | AUTO
| iteration_stat | REGISTER
| jump_stat ;
;
type_specifier
labeled_stat : TOK_IDENTIFIER TOK_COLON stat : VOID
| TOK_CASE const_exp TOK_COLON stat | CHAR
| TOK_DEFAULT TOK_COLON stat | SHORT
; | INT
| LONG
exp_stat : exp TOK_SEMICOLON | FLOAT
| TOK_SEMICOLON | DOUBLE
; | SIGNED
| UNSIGNED
compound_stat : TOK_LCURLY decl_list stat_list TOK_RCURLY | struct_or_union_specifier
| TOK_LCURLY stat_list TOK_RCURLY | enum_specifier
| TOK_LCURLY decl_list TOK_RCURLY | IDENTIFIER
| TOK_LCURLY TOK_RCURLY ;
;
struct_or_union_specifier
stat_list : stat : struct_or_union IDENTIFIER LCURLY struct_declaration_list RCURLY
| stat_list stat | struct_or_union LCURLY struct_declaration_list RCURLY
; | struct_or_union IDENTIFIER
;
selection_stat : TOK_IF TOK_LPAREN exp TOK_RPAREN stat
| TOK_IF TOK_LPAREN exp TOK_RPAREN stat TOK_ELSE stat struct_or_union
| TOK_SWITCH TOK_LPAREN exp TOK_RPAREN stat : STRUCT
; | UNION
;
iteration_stat : TOK_WHILE TOK_LPAREN exp TOK_RPAREN stat
| TOK_DO stat TOK_WHILE TOK_LPAREN exp TOK_RPAREN TOK_SEMICOLON struct_declaration_list
| TOK_FOR TOK_LPAREN exp TOK_SEMICOLON exp TOK_SEMICOLON exp TOK_RPAREN stat : struct_declaration
| TOK_FOR TOK_LPAREN exp TOK_SEMICOLON exp TOK_SEMICOLON TOK_RPAREN stat | struct_declaration_list struct_declaration
| TOK_FOR TOK_LPAREN exp TOK_SEMICOLON TOK_SEMICOLON exp TOK_RPAREN stat ;
| TOK_FOR TOK_LPAREN exp TOK_SEMICOLON TOK_SEMICOLON TOK_RPAREN stat
| TOK_FOR TOK_LPAREN TOK_SEMICOLON exp TOK_SEMICOLON exp TOK_RPAREN stat struct_declaration
| TOK_FOR TOK_LPAREN TOK_SEMICOLON exp TOK_SEMICOLON TOK_RPAREN stat : specifier_qualifier_list struct_declarator_list SEMICOLON
| TOK_FOR TOK_LPAREN TOK_SEMICOLON TOK_SEMICOLON exp TOK_RPAREN stat ;
| TOK_FOR TOK_LPAREN TOK_SEMICOLON TOK_SEMICOLON TOK_RPAREN stat
; specifier_qualifier_list
: type_specifier specifier_qualifier_list
jump_stat : TOK_GOTO TOK_IDENTIFIER TOK_SEMICOLON | type_specifier
| TOK_CONTINUE TOK_SEMICOLON | type_qualifier specifier_qualifier_list
| TOK_BREAK TOK_SEMICOLON | type_qualifier
| TOK_RETURN exp TOK_SEMICOLON ;
| TOK_RETURN TOK_SEMICOLON
; struct_declarator_list
: struct_declarator
exp : assignment_exp | struct_declarator_list COMMA struct_declarator
| exp TOK_COMMA assignment_exp ;
;
struct_declarator
assignment_exp : conditional_exp : declarator
| unary_exp assignment_operator assignment_exp | COLON constant_expression
; | declarator COLON constant_expression
;
assignment_operator : TOK_ASSIGN | TOK_TIMESEQUALS | TOK_DIVIDEEQUALS | TOK_MODEQUALS | TOK_PLUSEQUALS | TOK_MINUSEQUALS | TOK_LSHIFTEQUALS
| TOK_RSHIFTEQUALS | TOK_BITANDEQUALS | TOK_XOREQUALS | TOK_BITOREQUALS enum_specifier
; : ENUM LCURLY enumerator_list RCURLY
| ENUM IDENTIFIER LCURLY enumerator_list RCURLY
conditional_exp : logical_or_exp | ENUM IDENTIFIER
| logical_or_exp TOK_QUESTION exp TOK_COLON conditional_exp ;
;
enumerator_list
const_exp : conditional_exp : enumerator
; | enumerator_list COMMA enumerator
;
logical_or_exp : logical_and_exp
| logical_or_exp TOK_OR logical_and_exp enumerator
; : IDENTIFIER
| IDENTIFIER ASSIGN constant_expression
logical_and_exp : inclusive_or_exp ;
| logical_and_exp TOK_AND inclusive_or_exp
; type_qualifier
: CONST
inclusive_or_exp : exclusive_or_exp | VOLATILE
| inclusive_or_exp TOK_BITOR exclusive_or_exp ;
;
declarator
exclusive_or_exp : and_exp : pointer direct_declarator
| exclusive_or_exp TOK_XOR and_exp | direct_declarator
; ;
and_exp : equality_exp direct_declarator
| and_exp TOK_BITAND equality_exp : IDENTIFIER
; | LPAREN declarator RPAREN
| direct_declarator LBRACKET constant_expression RBRACKET
equality_exp : relational_exp | direct_declarator LBRACKET RBRACKET
| equality_exp TOK_EQUALS relational_exp | direct_declarator LPAREN parameter_type_list RPAREN
| equality_exp TOK_NOTEQUALS relational_exp | direct_declarator LPAREN identifier_list RPAREN
; | direct_declarator LPAREN RPAREN
;
relational_exp : shift_expression
| relational_exp TOK_LESS shift_expression pointer
| relational_exp TOK_GREATER shift_expression : TIMES
| relational_exp TOK_LESSEQ shift_expression | TIMES type_qualifier_list
| relational_exp TOK_GREATEREQ shift_expression | TIMES pointer
; | TIMES type_qualifier_list pointer
;
shift_expression : additive_exp
| shift_expression TOK_LSHIFT additive_exp type_qualifier_list
| shift_expression TOK_RSHIFT additive_exp : type_qualifier
; | type_qualifier_list type_qualifier
;
additive_exp : mult_exp
| additive_exp TOK_PLUS mult_exp
| additive_exp TOK_MINUS mult_exp parameter_type_list
; : parameter_list
| parameter_list COMMA ELLIPSIS
mult_exp : cast_exp ;
| mult_exp TOK_TIMES cast_exp
| mult_exp TOK_DIVIDE cast_exp parameter_list
| mult_exp TOK_MOD cast_exp : parameter_declaration
; | parameter_list COMMA parameter_declaration
;
cast_exp : unary_exp
| TOK_LPAREN type_name TOK_RPAREN cast_exp parameter_declaration
; : declaration_specifiers declarator
| declaration_specifiers abstract_declarator
unary_exp : postfix_exp | declaration_specifiers
| TOK_INCREMENT unary_exp ;
| TOK_DECREMENT unary_exp
| unary_operator cast_exp identifier_list
| TOK_SIZEOF unary_exp : IDENTIFIER
| TOK_SIZEOF TOK_LPAREN type_name TOK_RPAREN | identifier_list COMMA IDENTIFIER
; ;
unary_operator : TOK_BITAND | TOK_TIMES | TOK_PLUS | TOK_MINUS | TOK_BITNOT | TOK_NOT type_name
; : specifier_qualifier_list
| specifier_qualifier_list abstract_declarator
postfix_exp : primary_exp ;
| postfix_exp TOK_LBRACKET exp TOK_RBRACKET
| postfix_exp TOK_LPAREN argument_exp_list TOK_RPAREN abstract_declarator
| postfix_exp TOK_LPAREN TOK_RPAREN : pointer
| postfix_exp TOK_DOT TOK_IDENTIFIER | direct_abstract_declarator
| postfix_exp TOK_ARROW TOK_IDENTIFIER | pointer direct_abstract_declarator
| postfix_exp TOK_INCREMENT ;
| postfix_exp TOK_DECREMENT
; direct_abstract_declarator
: LPAREN abstract_declarator RPAREN
primary_exp : const | LBRACKET RBRACKET
| TOK_STR_CONST | LBRACKET constant_expression RBRACKET
| TOK_LPAREN exp TOK_RPAREN | direct_abstract_declarator LBRACKET RBRACKET
; | direct_abstract_declarator LBRACKET constant_expression RBRACKET
| LPAREN RPAREN
argument_exp_list : assignment_exp | LPAREN parameter_type_list RPAREN
| argument_exp_list TOK_COMMA assignment_exp | direct_abstract_declarator LPAREN RPAREN
; | direct_abstract_declarator LPAREN parameter_type_list RPAREN
;
const : TOK_INT_CONST
| TOK_CHAR_CONST initializer
| TOK_FLOAT_CONST : assignment_expression
| TOK_IDENTIFIER | LCURLY initializer_list RCURLY
; | LCURLY initializer_list COMMA RCURLY
;
initializer_list
: initializer
| initializer_list COMMA initializer
;
statement
: labeled_statement
| compound_statement
| expression_statement
| selection_statement
| iteration_statement
| jump_statement
;
labeled_statement
: IDENTIFIER COLON statement
| CASE constant_expression COLON statement
| DEFAULT COLON statement
;
compound_statement
: LCURLY RCURLY
| LCURLY statement_list RCURLY
| LCURLY declaration_list RCURLY
| LCURLY declaration_list statement_list RCURLY
;
declaration_list
: declaration
| declaration_list declaration
;
statement_list
: statement
| statement_list statement
;
expression_statement
: SEMICOLON
| expression SEMICOLON
;
selection_statement
: IF LPAREN expression RPAREN statement
| IF LPAREN expression RPAREN statement ELSE statement
| SWITCH LPAREN expression RPAREN statement
;
iteration_statement
: WHILE LPAREN expression RPAREN statement
| DO statement WHILE LPAREN expression RPAREN SEMICOLON
| FOR LPAREN expression_statement expression_statement RPAREN statement
| FOR LPAREN expression_statement expression_statement expression RPAREN statement
;
jump_statement
: GOTO IDENTIFIER SEMICOLON
| CONTINUE SEMICOLON
| BREAK SEMICOLON
| RETURN SEMICOLON
| RETURN expression SEMICOLON
;
translation_unit
: external_declaration
| translation_unit external_declaration
;
external_declaration
: function_definition
| declaration
;
function_definition
: declaration_specifiers declarator declaration_list compound_statement
| declaration_specifiers declarator compound_statement
| declarator declaration_list compound_statement
| declarator compound_statement
;
%% %%