From 895ea270160314b45418b2e8de3843c7a625a151 Mon Sep 17 00:00:00 2001 From: Josh Holtrop Date: Mon, 7 May 2018 23:48:08 -0400 Subject: [PATCH] parser rewrite according to ANSI C grammar same problem as before - conflict in IDENTIFIER as a type name versus an actual identifier --- src/parser/parser.l | 190 +++++----- src/parser/parser.y | 901 ++++++++++++++++++++++++-------------------- 2 files changed, 587 insertions(+), 504 deletions(-) diff --git a/src/parser/parser.l b/src/parser/parser.l index 519d8b4..2587fe8 100644 --- a/src/parser/parser.l +++ b/src/parser/parser.l @@ -31,111 +31,111 @@ void handle_loc(const char * input); %% -\+ return TOK_PLUS; -- return TOK_MINUS; -\* return TOK_TIMES; -\/ return TOK_DIVIDE; -% return TOK_MOD; -\^ return TOK_XOR; -= return TOK_ASSIGN; -== return TOK_EQUALS; -!= return TOK_NOTEQUALS; -\< return TOK_LESS; -\<= return TOK_LESSEQ; -\> return TOK_GREATER; -\>= return TOK_GREATEREQ; -&& return TOK_AND; -\|\| return TOK_OR; -! return TOK_NOT; -& return TOK_BITAND; -\| return TOK_BITOR; -~ return TOK_BITNOT; -\+\+ return TOK_INCREMENT; --- return TOK_DECREMENT; -\<\< return TOK_LSHIFT; -\>\> return TOK_RSHIFT; -\+= return TOK_PLUSEQUALS; --= return TOK_MINUSEQUALS; -\*= return TOK_TIMESEQUALS; -\/= return TOK_DIVIDEEQUALS; -%= return TOK_MODEQUALS; -\^= return TOK_XOREQUALS; -\<\<= return TOK_LSHIFTEQUALS; -\>\>= return TOK_RSHIFTEQUALS; -&= return TOK_BITANDEQUALS; -\|= return TOK_BITOREQUALS; +\+ return PLUS; +- return MINUS; +\* return TIMES; +\/ return DIVIDE; +% return MOD; +\^ return XOR; += return ASSIGN; +== return EQUALS; +!= return NOTEQUALS; +\< return LESS; +\<= return LESSEQ; +\> return GREATER; +\>= return GREATEREQ; +&& return AND; +\|\| return OR; +! return NOT; +& return BITAND; +\| return BITOR; +~ return BITNOT; +\+\+ return INCREMENT; +-- return DECREMENT; +\<\< return LSHIFT; +\>\> return RSHIFT; +\+= return ADD_ASSIGN; +-= return SUB_ASSIGN; +\*= return MUL_ASSIGN; +\/= return DIV_ASSIGN; +%= return MOD_ASSIGN; +\^= return XOR_ASSIGN; +\<\<= return LEFT_ASSIGN; +\>\>= return RIGHT_ASSIGN; +&= return AND_ASSIGN; +\|= return OR_ASSIGN; -; return TOK_SEMICOLON; -: return TOK_COLON; -\? return TOK_QUESTION; -\. return TOK_DOT; --\> return TOK_ARROW; -, return TOK_COMMA; -\.\.\. return TOK_ELLIPSES; +; return SEMICOLON; +: return COLON; +\? return QUESTION; +\. return DOT; +-\> return ARROW; +, return COMMA; +\.\.\. return ELLIPSIS; -\{ return TOK_LCURLY; -\} return TOK_RCURLY; -\[ return TOK_LBRACKET; -\] return TOK_RBRACKET; -\( return TOK_LPAREN; -\) return TOK_RPAREN; +\{ return LCURLY; +\} return RCURLY; +\[ return LBRACKET; +\] return RBRACKET; +\( return LPAREN; +\) return RPAREN; -void return TOK_VOID; -char return TOK_CHAR; -short return TOK_SHORT; -int return TOK_INT; -long return TOK_LONG; -float return TOK_FLOAT; -double return TOK_DOUBLE; +void return VOID; +char return CHAR; +short return SHORT; +int return INT; +long return LONG; +float return FLOAT; +double return DOUBLE; -signed return TOK_SIGNED; -unsigned return TOK_UNSIGNED; +signed return SIGNED; +unsigned return UNSIGNED; -volatile return TOK_VOLATILE; -static return TOK_STATIC; -const return TOK_CONST; -extern return TOK_EXTERN; -auto return TOK_AUTO; -register return TOK_REGISTER; -inline return TOK_INLINE; +volatile return VOLATILE; +static return STATIC; +const return CONST; +extern return EXTERN; +auto return AUTO; +register return REGISTER; +inline return INLINE; -struct return TOK_STRUCT; -union return TOK_UNION; -enum return TOK_ENUM; +struct return STRUCT; +union return UNION; +enum return ENUM; -typedef return TOK_TYPEDEF; +typedef return TYPEDEF; -if return TOK_IF; -else return TOK_ELSE; -while return TOK_WHILE; -for return TOK_FOR; -do return TOK_DO; -goto return TOK_GOTO; -return return TOK_RETURN; -switch return TOK_SWITCH; -case return TOK_CASE; -default return TOK_DEFAULT; -break return TOK_BREAK; -continue return TOK_CONTINUE; +if return IF; +else return ELSE; +while return WHILE; +for return FOR; +do return DO; +goto return GOTO; +return return RETURN; +switch return SWITCH; +case return CASE; +default return DEFAULT; +break return BREAK; +continue return CONTINUE; -sizeof return TOK_SIZEOF; +sizeof return SIZEOF; -L?'[^\\]' return TOK_CHAR_CONST; -L?'\\.' return TOK_CHAR_CONST; -L?'\\a' (void)'\a'; return TOK_CHAR_CONST; -L?'\\b' (void)'\b'; return TOK_CHAR_CONST; -L?'\\f' (void)'\f'; return TOK_CHAR_CONST; -L?'\\n' (void)'\n'; return TOK_CHAR_CONST; -L?'\\r' (void)'\r'; return TOK_CHAR_CONST; -L?'\\t' (void)'\t'; return TOK_CHAR_CONST; -L?'\\v' (void)'\v'; return TOK_CHAR_CONST; -L?'\\x[0-9A-Fa-f]{2}' return TOK_CHAR_CONST; -L?'\\[0-7]{1,3}' return TOK_CHAR_CONST; -[0-9]+([uU][lL]?[lL]?)? return TOK_INT_CONST; -0[xX][0-9a-fA-F]+([uU][lL]?[lL]?)? return TOK_INT_CONST; -([0-9]+\.[0-9]*|\.[0-9]+)([eE][-+]?[0-9]+)?[fFlL]? return TOK_FLOAT_CONST; +L?'[^\\]' return CHAR_CONST; +L?'\\.' return CHAR_CONST; +L?'\\a' (void)'\a'; return CHAR_CONST; +L?'\\b' (void)'\b'; return CHAR_CONST; +L?'\\f' (void)'\f'; return CHAR_CONST; +L?'\\n' (void)'\n'; return CHAR_CONST; +L?'\\r' (void)'\r'; return CHAR_CONST; +L?'\\t' (void)'\t'; return CHAR_CONST; +L?'\\v' (void)'\v'; return CHAR_CONST; +L?'\\x[0-9A-Fa-f]{2}' return CHAR_CONST; +L?'\\[0-7]{1,3}' return CHAR_CONST; +[0-9]+([uU][lL]?[lL]?)? return 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 FLOAT_CONST; L?\" { if (build_string != NULL) @@ -148,7 +148,7 @@ L?\" { { \" { BEGIN(INITIAL); - return TOK_STR_CONST; + return STRING_LITERAL; } \\x[0-9A-Fa-f]{2} { /* hexadecimal escape code */ @@ -175,7 +175,7 @@ L?\" { [^\\\"]+ 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]+[ ]+\".+\".*$ { handle_loc(yytext); diff --git a/src/parser/parser.y b/src/parser/parser.y index 816f8e5..35f3381 100644 --- a/src/parser/parser.y +++ b/src/parser/parser.y @@ -13,429 +13,512 @@ int yylex(YYSTYPE *, YYLTYPE *); %locations %error-verbose -%token TOK_PLUS; -%token TOK_MINUS; -%token TOK_TIMES; -%token TOK_DIVIDE; -%token TOK_MOD; -%token TOK_XOR; -%token TOK_ASSIGN; -%token TOK_EQUALS; -%token TOK_NOTEQUALS; -%token TOK_LESS; -%token TOK_LESSEQ; -%token TOK_GREATER; -%token TOK_GREATEREQ; -%token TOK_AND; -%token TOK_OR; -%token TOK_NOT; -%token TOK_BITAND; -%token TOK_BITOR; -%token TOK_BITNOT; -%token TOK_INCREMENT -%token TOK_DECREMENT -%token TOK_LSHIFT -%token TOK_RSHIFT -%token TOK_PLUSEQUALS; -%token TOK_MINUSEQUALS; -%token TOK_TIMESEQUALS; -%token TOK_DIVIDEEQUALS; -%token TOK_MODEQUALS; -%token TOK_XOREQUALS; -%token TOK_LSHIFTEQUALS; -%token TOK_RSHIFTEQUALS; -%token TOK_BITANDEQUALS; -%token TOK_BITOREQUALS; +%token PLUS; +%token MINUS; +%token TIMES; +%token DIVIDE; +%token MOD; +%token XOR; +%token ASSIGN; +%token EQUALS; +%token NOTEQUALS; +%token LESS; +%token LESSEQ; +%token GREATER; +%token GREATEREQ; +%token AND; +%token OR; +%token NOT; +%token BITAND; +%token BITOR; +%token BITNOT; +%token INCREMENT +%token DECREMENT +%token LSHIFT +%token RSHIFT +%token ADD_ASSIGN; +%token SUB_ASSIGN; +%token MUL_ASSIGN; +%token DIV_ASSIGN; +%token MOD_ASSIGN; +%token XOR_ASSIGN; +%token LEFT_ASSIGN; +%token RIGHT_ASSIGN; +%token AND_ASSIGN; +%token OR_ASSIGN; -%token TOK_SEMICOLON; -%token TOK_COLON; -%token TOK_QUESTION; -%token TOK_DOT; -%token TOK_ARROW; -%token TOK_COMMA; -%token TOK_ELLIPSES; +%token SEMICOLON; +%token COLON; +%token QUESTION; +%token DOT; +%token ARROW; +%token COMMA; +%token ELLIPSIS; -%token TOK_LCURLY; -%token TOK_RCURLY; -%token TOK_LBRACKET; -%token TOK_RBRACKET; -%token TOK_LPAREN; -%token TOK_RPAREN; +%token LCURLY; +%token RCURLY; +%token LBRACKET; +%token RBRACKET; +%token LPAREN; +%token RPAREN; -%token TOK_VOID; -%token TOK_CHAR; -%token TOK_SHORT; -%token TOK_INT; -%token TOK_LONG; -%token TOK_FLOAT; -%token TOK_DOUBLE; +%token VOID; +%token CHAR; +%token SHORT; +%token INT; +%token LONG; +%token FLOAT; +%token DOUBLE; -%token TOK_SIGNED; -%token TOK_UNSIGNED; +%token SIGNED; +%token UNSIGNED; -%token TOK_VOLATILE; -%token TOK_STATIC; -%token TOK_CONST; -%token TOK_EXTERN; -%token TOK_AUTO; -%token TOK_REGISTER; -%token TOK_INLINE; +%token VOLATILE; +%token STATIC; +%token CONST; +%token EXTERN; +%token AUTO; +%token REGISTER; +%token INLINE; -%token TOK_STRUCT; -%token TOK_UNION; -%token TOK_ENUM; +%token STRUCT; +%token UNION; +%token ENUM; -%token TOK_TYPEDEF; +%token TYPEDEF; -%token TOK_IF; -%token TOK_ELSE; -%token TOK_WHILE; -%token TOK_FOR; -%token TOK_DO; -%token TOK_GOTO; -%token TOK_RETURN; -%token TOK_SWITCH; -%token TOK_CASE; -%token TOK_DEFAULT; -%token TOK_BREAK; -%token TOK_CONTINUE; +%token IF; +%token ELSE; +%token WHILE; +%token FOR; +%token DO; +%token GOTO; +%token RETURN; +%token SWITCH; +%token CASE; +%token DEFAULT; +%token BREAK; +%token CONTINUE; -%token TOK_SIZEOF; +%token SIZEOF; -%token TOK_CHAR_CONST; -%token TOK_INT_CONST; -%token TOK_FLOAT_CONST; -%token TOK_STR_CONST; -%token TOK_IDENTIFIER; +%token CHAR_CONST; +%token INT_CONST; +%token FLOAT_CONST; +%token STRING_LITERAL; +%token IDENTIFIER; + +%start translation_unit %% -translation_unit : - | external_decl - | translation_unit external_decl - ; - -external_decl : function_definition - | decl - ; - -function_definition : decl_specs declarator decl_list compound_stat - | declarator decl_list compound_stat - | decl_specs declarator compound_stat - | declarator compound_stat - ; - -decl : decl_specs init_declarator_list TOK_SEMICOLON - | decl_specs TOK_SEMICOLON - ; - -decl_list : decl - | decl_list decl - ; - -decl_specs : storage_class_spec decl_specs - | storage_class_spec - | type_spec decl_specs - | type_spec - | type_qualifier decl_specs - | type_qualifier - ; - -storage_class_spec : TOK_AUTO | TOK_REGISTER | TOK_STATIC | TOK_EXTERN | TOK_TYPEDEF - ; - -type_spec : TOK_VOID | TOK_CHAR | TOK_SHORT | TOK_INT | TOK_LONG | TOK_FLOAT - | TOK_DOUBLE | TOK_SIGNED | TOK_UNSIGNED - | struct_or_union_spec - | enum_spec - | typedef_name - ; - -type_qualifier : TOK_CONST | TOK_VOLATILE - ; - -struct_or_union_spec : struct_or_union TOK_IDENTIFIER TOK_LCURLY struct_decl_list TOK_RCURLY - | struct_or_union TOK_LCURLY struct_decl_list TOK_RCURLY - | struct_or_union TOK_IDENTIFIER - ; - -struct_or_union : TOK_STRUCT | TOK_UNION - ; - -struct_decl_list : struct_decl - | struct_decl_list struct_decl - ; - -init_declarator_list : init_declarator - | init_declarator_list TOK_COMMA init_declarator - ; - -init_declarator : declarator - | declarator TOK_ASSIGN initializer - ; - -struct_decl : spec_qualifier_list struct_declarator_list TOK_SEMICOLON - ; - - -spec_qualifier_list : type_spec spec_qualifier_list - | type_spec - | type_qualifier spec_qualifier_list - | type_qualifier - ; - -struct_declarator_list : struct_declarator - | struct_declarator_list TOK_COMMA struct_declarator - ; - -struct_declarator : declarator - | declarator TOK_COLON const_exp - | TOK_COLON const_exp - ; - -enum_spec : TOK_ENUM TOK_IDENTIFIER TOK_LCURLY enumerator_list TOK_RCURLY - | TOK_ENUM TOK_LCURLY enumerator_list TOK_RCURLY - | TOK_ENUM TOK_IDENTIFIER - ; - -enumerator_list : enumerator - | enumerator_list TOK_COMMA enumerator - ; - -enumerator : TOK_IDENTIFIER - | TOK_IDENTIFIER TOK_ASSIGN const_exp - ; - -declarator : pointer direct_declarator - | direct_declarator - ; - -direct_declarator : TOK_IDENTIFIER - | TOK_LPAREN declarator TOK_RPAREN - | direct_declarator TOK_LBRACKET const_exp TOK_RBRACKET - | direct_declarator TOK_LBRACKET TOK_RBRACKET - | direct_declarator TOK_LPAREN param_type_list TOK_RPAREN - | direct_declarator TOK_LPAREN id_list TOK_RPAREN - | direct_declarator TOK_LPAREN TOK_RPAREN - ; - -pointer : TOK_TIMES type_qualifier_list - | TOK_TIMES - | TOK_TIMES type_qualifier_list pointer - | TOK_TIMES pointer - ; - -type_qualifier_list : type_qualifier - | type_qualifier_list type_qualifier - ; - -param_type_list : param_list - | param_list TOK_COMMA TOK_ELLIPSES - ; - -param_list : param_decl - | param_list TOK_COMMA param_decl - ; - -param_decl : decl_specs declarator - | decl_specs abstract_declarator - | decl_specs - ; - -id_list : TOK_IDENTIFIER - | id_list TOK_COMMA TOK_IDENTIFIER - ; - -initializer : assignment_exp - | TOK_LCURLY initializer_list TOK_RCURLY - | TOK_LCURLY initializer_list TOK_COMMA TOK_RCURLY - ; - -initializer_list : initializer - | initializer_list TOK_COMMA initializer - ; - -type_name : spec_qualifier_list abstract_declarator - | spec_qualifier_list - ; - -abstract_declarator : pointer - | pointer direct_abstract_declarator - | direct_abstract_declarator - ; - -direct_abstract_declarator: TOK_LPAREN abstract_declarator TOK_RPAREN - | direct_abstract_declarator TOK_LBRACKET const_exp TOK_RBRACKET - | TOK_LBRACKET const_exp TOK_RBRACKET - | direct_abstract_declarator TOK_LBRACKET TOK_RBRACKET - | TOK_LBRACKET TOK_RBRACKET - | direct_abstract_declarator TOK_LPAREN param_type_list TOK_RPAREN - | TOK_LPAREN param_type_list TOK_RPAREN - | direct_abstract_declarator TOK_LPAREN TOK_RPAREN - | TOK_LPAREN TOK_RPAREN - ; - -typedef_name : TOK_IDENTIFIER - ; - -stat : labeled_stat - | exp_stat - | compound_stat - | selection_stat - | iteration_stat - | jump_stat - ; - -labeled_stat : TOK_IDENTIFIER TOK_COLON stat - | TOK_CASE const_exp TOK_COLON stat - | TOK_DEFAULT TOK_COLON stat - ; - -exp_stat : exp TOK_SEMICOLON - | TOK_SEMICOLON - ; - -compound_stat : TOK_LCURLY decl_list stat_list TOK_RCURLY - | TOK_LCURLY stat_list TOK_RCURLY - | TOK_LCURLY decl_list TOK_RCURLY - | TOK_LCURLY TOK_RCURLY - ; - -stat_list : stat - | stat_list stat - ; - -selection_stat : TOK_IF TOK_LPAREN exp TOK_RPAREN stat - | TOK_IF TOK_LPAREN exp TOK_RPAREN stat TOK_ELSE stat - | TOK_SWITCH TOK_LPAREN exp TOK_RPAREN stat - ; - -iteration_stat : TOK_WHILE TOK_LPAREN exp TOK_RPAREN stat - | TOK_DO stat TOK_WHILE TOK_LPAREN exp TOK_RPAREN TOK_SEMICOLON - | TOK_FOR TOK_LPAREN exp TOK_SEMICOLON exp TOK_SEMICOLON exp TOK_RPAREN stat - | TOK_FOR TOK_LPAREN exp TOK_SEMICOLON exp TOK_SEMICOLON TOK_RPAREN stat - | 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 - | TOK_FOR TOK_LPAREN TOK_SEMICOLON exp TOK_SEMICOLON TOK_RPAREN stat - | TOK_FOR TOK_LPAREN TOK_SEMICOLON TOK_SEMICOLON exp TOK_RPAREN stat - | TOK_FOR TOK_LPAREN TOK_SEMICOLON TOK_SEMICOLON TOK_RPAREN stat - ; - -jump_stat : TOK_GOTO TOK_IDENTIFIER TOK_SEMICOLON - | TOK_CONTINUE TOK_SEMICOLON - | TOK_BREAK TOK_SEMICOLON - | TOK_RETURN exp TOK_SEMICOLON - | TOK_RETURN TOK_SEMICOLON - ; - -exp : assignment_exp - | exp TOK_COMMA assignment_exp - ; - -assignment_exp : conditional_exp - | unary_exp assignment_operator assignment_exp - ; - -assignment_operator : TOK_ASSIGN | TOK_TIMESEQUALS | TOK_DIVIDEEQUALS | TOK_MODEQUALS | TOK_PLUSEQUALS | TOK_MINUSEQUALS | TOK_LSHIFTEQUALS - | TOK_RSHIFTEQUALS | TOK_BITANDEQUALS | TOK_XOREQUALS | TOK_BITOREQUALS - ; - -conditional_exp : logical_or_exp - | logical_or_exp TOK_QUESTION exp TOK_COLON conditional_exp - ; - -const_exp : conditional_exp - ; - -logical_or_exp : logical_and_exp - | logical_or_exp TOK_OR logical_and_exp - ; - -logical_and_exp : inclusive_or_exp - | logical_and_exp TOK_AND inclusive_or_exp - ; - -inclusive_or_exp : exclusive_or_exp - | inclusive_or_exp TOK_BITOR exclusive_or_exp - ; - -exclusive_or_exp : and_exp - | exclusive_or_exp TOK_XOR and_exp - ; - -and_exp : equality_exp - | and_exp TOK_BITAND equality_exp - ; - -equality_exp : relational_exp - | equality_exp TOK_EQUALS relational_exp - | equality_exp TOK_NOTEQUALS relational_exp - ; - -relational_exp : shift_expression - | relational_exp TOK_LESS shift_expression - | relational_exp TOK_GREATER shift_expression - | relational_exp TOK_LESSEQ shift_expression - | relational_exp TOK_GREATEREQ shift_expression - ; - -shift_expression : additive_exp - | shift_expression TOK_LSHIFT additive_exp - | shift_expression TOK_RSHIFT additive_exp - ; - -additive_exp : mult_exp - | additive_exp TOK_PLUS mult_exp - | additive_exp TOK_MINUS mult_exp - ; - -mult_exp : cast_exp - | mult_exp TOK_TIMES cast_exp - | mult_exp TOK_DIVIDE cast_exp - | mult_exp TOK_MOD cast_exp - ; - -cast_exp : unary_exp - | TOK_LPAREN type_name TOK_RPAREN cast_exp - ; - -unary_exp : postfix_exp - | TOK_INCREMENT unary_exp - | TOK_DECREMENT unary_exp - | unary_operator cast_exp - | TOK_SIZEOF unary_exp - | TOK_SIZEOF TOK_LPAREN type_name TOK_RPAREN - ; - -unary_operator : TOK_BITAND | TOK_TIMES | TOK_PLUS | TOK_MINUS | TOK_BITNOT | TOK_NOT - ; - -postfix_exp : primary_exp - | postfix_exp TOK_LBRACKET exp TOK_RBRACKET - | postfix_exp TOK_LPAREN argument_exp_list TOK_RPAREN - | postfix_exp TOK_LPAREN TOK_RPAREN - | postfix_exp TOK_DOT TOK_IDENTIFIER - | postfix_exp TOK_ARROW TOK_IDENTIFIER - | postfix_exp TOK_INCREMENT - | postfix_exp TOK_DECREMENT - ; - -primary_exp : const - | TOK_STR_CONST - | TOK_LPAREN exp TOK_RPAREN - ; - -argument_exp_list : assignment_exp - | argument_exp_list TOK_COMMA assignment_exp - ; - -const : TOK_INT_CONST - | TOK_CHAR_CONST - | TOK_FLOAT_CONST - | TOK_IDENTIFIER - ; +constant + : INT_CONST + | FLOAT_CONST + | CHAR_CONST + ; + +primary_expression + : IDENTIFIER + | constant + | STRING_LITERAL + | LPAREN expression RPAREN + ; + +postfix_expression + : primary_expression + | postfix_expression LBRACKET expression RBRACKET + | postfix_expression LPAREN RPAREN + | postfix_expression LPAREN argument_expression_list RPAREN + | postfix_expression DOT IDENTIFIER + | postfix_expression ARROW IDENTIFIER + | postfix_expression INCREMENT + | postfix_expression DECREMENT + ; + +argument_expression_list + : assignment_expression + | argument_expression_list COMMA assignment_expression + ; + +unary_expression + : postfix_expression + | INCREMENT unary_expression + | DECREMENT unary_expression + | unary_operator cast_expression + | SIZEOF unary_expression + | SIZEOF LPAREN type_name RPAREN + ; + +unary_operator + : BITAND + | TIMES + | PLUS + | MINUS + | BITNOT + | NOT + ; + +cast_expression + : unary_expression + | LPAREN type_name RPAREN cast_expression + ; + +multiplicative_expression + : cast_expression + | multiplicative_expression TIMES cast_expression + | multiplicative_expression DIVIDE cast_expression + | multiplicative_expression MOD cast_expression + ; + +additive_expression + : multiplicative_expression + | additive_expression PLUS multiplicative_expression + | additive_expression MINUS multiplicative_expression + ; + +shift_expression + : additive_expression + | shift_expression LSHIFT additive_expression + | shift_expression RSHIFT additive_expression + ; + +relational_expression + : shift_expression + | relational_expression LESS shift_expression + | relational_expression GREATER shift_expression + | relational_expression LESSEQ shift_expression + | relational_expression GREATEREQ shift_expression + ; + +equality_expression + : relational_expression + | equality_expression EQUALS relational_expression + | equality_expression NOTEQUALS relational_expression + ; + +and_expression + : equality_expression + | and_expression BITAND equality_expression + ; + +exclusive_or_expression + : and_expression + | exclusive_or_expression XOR and_expression + ; + +inclusive_or_expression + : exclusive_or_expression + | inclusive_or_expression BITOR exclusive_or_expression + ; + +logical_and_expression + : inclusive_or_expression + | logical_and_expression AND inclusive_or_expression + ; + +logical_or_expression + : logical_and_expression + | logical_or_expression OR logical_and_expression + ; + +conditional_expression + : logical_or_expression + | logical_or_expression QUESTION expression COLON conditional_expression + ; + +assignment_expression + : conditional_expression + | unary_expression assignment_operator assignment_expression + ; + +assignment_operator + : ASSIGN + | MUL_ASSIGN + | DIV_ASSIGN + | MOD_ASSIGN + | ADD_ASSIGN + | SUB_ASSIGN + | LEFT_ASSIGN + | RIGHT_ASSIGN + | AND_ASSIGN + | XOR_ASSIGN + | OR_ASSIGN + ; + +expression + : assignment_expression + | expression COMMA assignment_expression + ; + +constant_expression + : conditional_expression + ; + +declaration + : declaration_specifiers SEMICOLON + | declaration_specifiers init_declarator_list SEMICOLON + ; + +declaration_specifiers + : storage_class_specifier + | storage_class_specifier declaration_specifiers + | type_specifier + | type_specifier declaration_specifiers + | type_qualifier + | type_qualifier declaration_specifiers + ; + +init_declarator_list + : init_declarator + | init_declarator_list COMMA init_declarator + ; + +init_declarator + : declarator + | declarator ASSIGN initializer + ; + +storage_class_specifier + : TYPEDEF + | EXTERN + | STATIC + | AUTO + | REGISTER + ; + +type_specifier + : VOID + | CHAR + | SHORT + | INT + | LONG + | FLOAT + | DOUBLE + | SIGNED + | UNSIGNED + | struct_or_union_specifier + | enum_specifier + | IDENTIFIER + ; + +struct_or_union_specifier + : struct_or_union IDENTIFIER LCURLY struct_declaration_list RCURLY + | struct_or_union LCURLY struct_declaration_list RCURLY + | struct_or_union IDENTIFIER + ; + +struct_or_union + : STRUCT + | UNION + ; + +struct_declaration_list + : struct_declaration + | struct_declaration_list struct_declaration + ; + +struct_declaration + : specifier_qualifier_list struct_declarator_list SEMICOLON + ; + +specifier_qualifier_list + : type_specifier specifier_qualifier_list + | type_specifier + | type_qualifier specifier_qualifier_list + | type_qualifier + ; + +struct_declarator_list + : struct_declarator + | struct_declarator_list COMMA struct_declarator + ; + +struct_declarator + : declarator + | COLON constant_expression + | declarator COLON constant_expression + ; + +enum_specifier + : ENUM LCURLY enumerator_list RCURLY + | ENUM IDENTIFIER LCURLY enumerator_list RCURLY + | ENUM IDENTIFIER + ; + +enumerator_list + : enumerator + | enumerator_list COMMA enumerator + ; + +enumerator + : IDENTIFIER + | IDENTIFIER ASSIGN constant_expression + ; + +type_qualifier + : CONST + | VOLATILE + ; + +declarator + : pointer direct_declarator + | direct_declarator + ; + +direct_declarator + : IDENTIFIER + | LPAREN declarator RPAREN + | direct_declarator LBRACKET constant_expression RBRACKET + | direct_declarator LBRACKET RBRACKET + | direct_declarator LPAREN parameter_type_list RPAREN + | direct_declarator LPAREN identifier_list RPAREN + | direct_declarator LPAREN RPAREN + ; + +pointer + : TIMES + | TIMES type_qualifier_list + | TIMES pointer + | TIMES type_qualifier_list pointer + ; + +type_qualifier_list + : type_qualifier + | type_qualifier_list type_qualifier + ; + + +parameter_type_list + : parameter_list + | parameter_list COMMA ELLIPSIS + ; + +parameter_list + : parameter_declaration + | parameter_list COMMA parameter_declaration + ; + +parameter_declaration + : declaration_specifiers declarator + | declaration_specifiers abstract_declarator + | declaration_specifiers + ; + +identifier_list + : IDENTIFIER + | identifier_list COMMA IDENTIFIER + ; + +type_name + : specifier_qualifier_list + | specifier_qualifier_list abstract_declarator + ; + +abstract_declarator + : pointer + | direct_abstract_declarator + | pointer direct_abstract_declarator + ; + +direct_abstract_declarator + : LPAREN abstract_declarator RPAREN + | LBRACKET RBRACKET + | LBRACKET constant_expression RBRACKET + | direct_abstract_declarator LBRACKET RBRACKET + | direct_abstract_declarator LBRACKET constant_expression RBRACKET + | LPAREN RPAREN + | LPAREN parameter_type_list RPAREN + | direct_abstract_declarator LPAREN RPAREN + | direct_abstract_declarator LPAREN parameter_type_list RPAREN + ; + +initializer + : assignment_expression + | 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 + ; %%