%{ #include "../C89Parser.h" #include "c89.tab.hpp" #include #include #define YYMAXDEPTH 20000 // default is 10000 #define YYDEBUG 1 #define YYERROR_VERBOSE 1 extern int c89_lex (C89_STYPE* yylval_param, C89_LTYPE* yylloc_param, void* yyscanner); using namespace uscxml; %} %pure-parser %debug %locations %file-prefix "c89" %parse-param { uscxml::C89Parser* ctx } %lex-param {void * scanner} %parse-param {void * scanner} %define api.prefix {c89_} %defines %union { uscxml::C89ParserNode* node; char* value; } %error-verbose %type primary_expression expression postfix_expression %type argument_expression_list assignment_expression %type unary_expression unary_operator cast_expression %type type_name assignment_operator %type multiplicative_expression additive_expression shift_expression %type relational_expression equality_expression and_expression %type exclusive_or_expression inclusive_or_expression %type logical_and_expression logical_or_expression conditional_expression %type specifier_qualifier_list abstract_declarator %type type_specifier type_qualifier struct_or_union_specifier %type enum_specifier pointer direct_abstract_declarator %type struct_or_union enumerator_list enumerator %type constant_expression type_qualifier_list %type parameter_type_list parameter_declaration parameter_list %type declaration_specifiers declarator storage_class_specifier %type init_declarator_list init_declarator initializer %type direct_declarator initializer_list identifier_list %type statement labeled_statement compound_statement expression_statement %type selection_statement iteration_statement jump_statement %type statement_list declaration_list declaration %type translation_unit external_declaration function_definition %type struct_declarator struct_declaration %type struct_declarator_list struct_declaration_list %type VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED TYPE_NAME %type CONST VOLATILE %type IDENTIFIER CONSTANT STRING_LITERAL %token IDENTIFIER CONSTANT STRING_LITERAL SIZEOF %token PTR_OP INC_OP DEC_OP LEFT_OP RIGHT_OP LE_OP GE_OP EQ_OP NE_OP %token AND_OP OR_OP MUL_ASSIGN DIV_ASSIGN MOD_ASSIGN ADD_ASSIGN %token SUB_ASSIGN LEFT_ASSIGN RIGHT_ASSIGN AND_ASSIGN %token XOR_ASSIGN OR_ASSIGN TYPE_NAME %token TYPEDEF EXTERN STATIC AUTO REGISTER %token CHAR SHORT INT LONG SIGNED UNSIGNED FLOAT DOUBLE CONST VOLATILE VOID %token STRUCT UNION ENUM ELLIPSIS %token CASE DEFAULT IF ELSE SWITCH WHILE DO FOR GOTO CONTINUE BREAK RETURN %start translation_unit %% primary_expression : IDENTIFIER { $$ = ctx->value(IDENTIFIER, (void*)&(@1), $1); free($1); } | CONSTANT { $$ = ctx->value(CONSTANT, (void*)&(@1), $1); free($1); } | STRING_LITERAL { $$ = ctx->value(STRING_LITERAL, (void*)&(@1), $1); free($1); } | '(' expression ')' { $$ = $2; } ; postfix_expression : primary_expression { $$ = $1; } | postfix_expression '[' expression ']' { $$ = ctx->node(__LINE__, 2, $1, $3); } | postfix_expression '(' ')' { $$ = ctx->node(__LINE__, 1, $1); } | postfix_expression '(' argument_expression_list ')' { $$ = ctx->node(__LINE__, 2, $1, $3); } | postfix_expression '.' IDENTIFIER { $$ = ctx->node(__LINE__, 2, $1, $3); } | postfix_expression PTR_OP IDENTIFIER { $$ = ctx->node(PTR_OP, 2, $1, $3); } | postfix_expression INC_OP { $$ = ctx->node(INC_OP, 1, $1); } | postfix_expression DEC_OP { $$ = ctx->node(DEC_OP, 1, $1); } ; argument_expression_list : assignment_expression { $$ = $1; } | argument_expression_list ',' assignment_expression { $$ = ctx->node(',', 2, $1, $3); } ; unary_expression : postfix_expression { $$ = $1; } | INC_OP unary_expression { $$ = ctx->node(INC_OP, 1, $2); } | DEC_OP unary_expression { $$ = ctx->node(DEC_OP, 1, $2); } | unary_operator cast_expression { $$ = ctx->node(__LINE__, 2, $1, $2); } | SIZEOF unary_expression { $$ = ctx->node(SIZEOF, 1, $2); } | SIZEOF '(' type_name ')' { $$ = ctx->node(SIZEOF, 1, $3); } ; unary_operator : '&' { $$ = ctx->node(__LINE__, 0); } | '*' { $$ = ctx->node(__LINE__, 0); } | '+' { $$ = ctx->node(__LINE__, 0); } | '-' { $$ = ctx->node(__LINE__, 0); } | '~' { $$ = ctx->node(__LINE__, 0); } | '!' { $$ = ctx->node(__LINE__, 0); } ; cast_expression : unary_expression { $$ = $1; } | '(' type_name ')' cast_expression { $$ = ctx->node(__LINE__, 2, $2, $4); } ; multiplicative_expression : cast_expression { $$ = $1; } | multiplicative_expression '*' cast_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } | multiplicative_expression '/' cast_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } | multiplicative_expression '%' cast_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } ; additive_expression : multiplicative_expression { $$ = $1; } | additive_expression '+' multiplicative_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } | additive_expression '-' multiplicative_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } ; shift_expression : additive_expression { $$ = $1; } | shift_expression LEFT_OP additive_expression { $$ = ctx->node(LEFT_OP, 2, $1, $3); } | shift_expression RIGHT_OP additive_expression { $$ = ctx->node(RIGHT_OP, 2, $1, $3); } ; relational_expression : shift_expression { $$ = $1; } | relational_expression '<' shift_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } | relational_expression '>' shift_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } | relational_expression LE_OP shift_expression { $$ = ctx->node(LE_OP, 2, $1, $3); } | relational_expression GE_OP shift_expression { $$ = ctx->node(GE_OP, 2, $1, $3); } ; equality_expression : relational_expression { $$ = $1; } | equality_expression EQ_OP relational_expression { $$ = ctx->node(EQ_OP, 2, $1, $3); } | equality_expression NE_OP relational_expression { $$ = ctx->node(NE_OP, 2, $1, $3); } ; and_expression : equality_expression { $$ = $1; } | and_expression '&' equality_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } ; exclusive_or_expression : and_expression { $$ = $1; } | exclusive_or_expression '^' and_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } ; inclusive_or_expression : exclusive_or_expression { $$ = $1; } | inclusive_or_expression '|' exclusive_or_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } ; logical_and_expression : inclusive_or_expression { $$ = $1; } | logical_and_expression AND_OP inclusive_or_expression { $$ = ctx->node(AND_OP, 2, $1, $3); } ; logical_or_expression : logical_and_expression { $$ = $1; } | logical_or_expression OR_OP logical_and_expression { $$ = ctx->node(OR_OP, 2, $1, $3); } ; conditional_expression : logical_or_expression { $$ = $1; } | logical_or_expression '?' expression ':' conditional_expression { $$ = ctx->node(__LINE__, 3, $1, $3, $5); } ; assignment_expression : conditional_expression { $$ = $1; } | unary_expression assignment_operator assignment_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } ; assignment_operator : '=' { $$ = ctx->node('=', 0); } | MUL_ASSIGN { $$ = ctx->node(MUL_ASSIGN, 0); } | DIV_ASSIGN { $$ = ctx->node(DIV_ASSIGN, 0); } | MOD_ASSIGN { $$ = ctx->node(MOD_ASSIGN, 0); } | ADD_ASSIGN { $$ = ctx->node(ADD_ASSIGN, 0); } | SUB_ASSIGN { $$ = ctx->node(SUB_ASSIGN, 0); } | LEFT_ASSIGN { $$ = ctx->node(LEFT_ASSIGN, 0); } | RIGHT_ASSIGN { $$ = ctx->node(RIGHT_ASSIGN, 0); } | AND_ASSIGN { $$ = ctx->node(AND_ASSIGN, 0); } | XOR_ASSIGN { $$ = ctx->node(XOR_ASSIGN, 0); } | OR_ASSIGN { $$ = ctx->node(OR_ASSIGN, 0); } ; expression : assignment_expression { $$ = $1; } | expression ',' assignment_expression { $$ = ctx->node(',', 2, $1, $3); } ; constant_expression : conditional_expression { $$ = $1; } ; declaration : declaration_specifiers ';' { $$ = $1; } | declaration_specifiers init_declarator_list ';' { $$ = ctx->node(',', 2, $1, $2); } ; declaration_specifiers : storage_class_specifier { $$ = $1; } | storage_class_specifier declaration_specifiers { $$ = ctx->node(__LINE__, 2, $1, $2); } | type_specifier { $$ = $1; } | type_specifier declaration_specifiers { $$ = ctx->node(__LINE__, 2, $1, $2); } | type_qualifier { $$ = $1; } | type_qualifier declaration_specifiers { $$ = ctx->node(__LINE__, 2, $1, $2); } ; init_declarator_list : init_declarator { $$ = $1; } | init_declarator_list ',' init_declarator { $$ = ctx->node(',', 2, $1, $3); } ; init_declarator : declarator { $$ = $1; } | declarator '=' initializer { $$ = ctx->node(__LINE__, 2, $1, $3); } ; storage_class_specifier : TYPEDEF { $$ = ctx->node(TYPEDEF, 0); } | EXTERN { $$ = ctx->node(EXTERN, 0); } | STATIC { $$ = ctx->node(STATIC, 0); } | AUTO { $$ = ctx->node(AUTO, 0); } | REGISTER { $$ = ctx->node(REGISTER, 0); } ; type_specifier : VOID { $$ = ctx->node(VOID, 0); } | CHAR { $$ = ctx->node(CHAR, 0); } | SHORT { $$ = ctx->node(SHORT, 0); } | INT { $$ = ctx->node(INT, 0); } | LONG { $$ = ctx->node(LONG, 0); } | FLOAT { $$ = ctx->node(FLOAT, 0); } | DOUBLE { $$ = ctx->node(DOUBLE, 0); } | SIGNED { $$ = ctx->node(SIGNED, 0); } | UNSIGNED { $$ = ctx->node(UNSIGNED, 0); } | struct_or_union_specifier { $$ = $1; } | enum_specifier { $$ = $1; } | TYPE_NAME { $$ = ctx->node(TYPE_NAME, 0); } ; struct_or_union_specifier : struct_or_union IDENTIFIER '{' struct_declaration_list '}' { $$ = ctx->node(__LINE__, 3, $1, $2, $4); } | struct_or_union '{' struct_declaration_list '}' { $$ = ctx->node(__LINE__, 2, $1, $3); } | struct_or_union IDENTIFIER { $$ = ctx->node(__LINE__, 1, $1); } ; struct_or_union : STRUCT { $$ = ctx->node(STRUCT, 0); } | UNION { $$ = ctx->node(STRUCT, 1); } ; struct_declaration_list : struct_declaration { $$ = $1; } | struct_declaration_list struct_declaration { $$ = ctx->node(',', 2, $1, $2); } ; struct_declaration : specifier_qualifier_list struct_declarator_list ';' { $$ = ctx->node(__LINE__, 2, $1, $2); } ; specifier_qualifier_list : type_specifier specifier_qualifier_list { $$ = ctx->node(',', 2, $1, $2); } | type_specifier { $$ = $1; } | type_qualifier specifier_qualifier_list { $$ = ctx->node(__LINE__, 2, $1, $2); } | type_qualifier { $$ = $1; } ; struct_declarator_list : struct_declarator { $$ = $1; } | struct_declarator_list ',' struct_declarator { $$ = ctx->node(',', 2, $1, $3); } ; struct_declarator : declarator { $$ = $1; } | ':' constant_expression { $$ = ctx->node(__LINE__, 1, $2); } | declarator ':' constant_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } ; enum_specifier : ENUM '{' enumerator_list '}' { $$ = ctx->node(ENUM, 1, $3); } | ENUM IDENTIFIER '{' enumerator_list '}' { $$ = ctx->node(ENUM, 2, $2, $4); } | ENUM IDENTIFIER { $$ = ctx->node(ENUM, 1, $2); } ; enumerator_list : enumerator { $$ = $1; } | enumerator_list ',' enumerator { $$ = ctx->node(',', 2, $1, $3); } ; enumerator : IDENTIFIER { $$ = ctx->value(IDENTIFIER, (void*)&(@1), $1); free($1); } | IDENTIFIER '=' constant_expression { $$ = ctx->node(__LINE__, 2, $1, $3); } ; type_qualifier : CONST { $$ = $1; } | VOLATILE { $$ = $1; } ; declarator : pointer direct_declarator { $$ = ctx->node(__LINE__, 2, $1, $2); } | direct_declarator { $$ = $1; } ; direct_declarator : IDENTIFIER { $$ = ctx->value(IDENTIFIER, (void*)&(@1), $1); free($1); } | '(' declarator ')' { $$ = ctx->node(__LINE__, 1, $2); } | direct_declarator '[' constant_expression ']' { $$ = ctx->node(__LINE__, 2, $1, $3); } | direct_declarator '[' ']' { $$ = ctx->node(__LINE__, 1, $1); } | direct_declarator '(' parameter_type_list ')' { $$ = ctx->node(__LINE__, 2, $1, $3); } | direct_declarator '(' identifier_list ')' { $$ = ctx->node(__LINE__, 2, $1, $3); } | direct_declarator '(' ')' { $$ = ctx->node(__LINE__, 1, $1); } ; pointer : '*' { $$ = ctx->node(__LINE__, 0); } | '*' type_qualifier_list { $$ = ctx->node(__LINE__, 1, $2); } | '*' pointer { $$ = ctx->node(__LINE__, 1, $2); } | '*' type_qualifier_list pointer { $$ = ctx->node(__LINE__, 2, $2, $3); } ; type_qualifier_list : type_qualifier { $$ = $1; } | type_qualifier_list type_qualifier { $$ = ctx->node(',', 2, $1, $2); } ; parameter_type_list : parameter_list { $$ = $1; } | parameter_list ',' ELLIPSIS { $$ = ctx->node(ELLIPSIS, 1, $1); } ; parameter_list : parameter_declaration { $$ = $1; } | parameter_list ',' parameter_declaration { $$ = ctx->node(__LINE__, 2, $1, $3); } ; parameter_declaration : declaration_specifiers declarator { $$ = ctx->node(__LINE__, 2, $1, $2); } | declaration_specifiers abstract_declarator { $$ = ctx->node(__LINE__, 2, $1, $2); } | declaration_specifiers { $$ = $1; } ; identifier_list : IDENTIFIER { $$ = ctx->value(IDENTIFIER, (void*)&(@1), $1); free($1); } | identifier_list ',' IDENTIFIER { $$ = ctx->node(',', 2, $1, $3); } ; type_name : specifier_qualifier_list { $$ = $1; } | specifier_qualifier_list abstract_declarator { $$ = ctx->node(__LINE__, 2, $1, $2); } ; abstract_declarator : pointer { $$ = $1; } | direct_abstract_declarator { $$ = $1; } | pointer direct_abstract_declarator { $$ = $1; } ; direct_abstract_declarator : '(' abstract_declarator ')' { $$ = $2; } | '[' ']' { $$ = ctx->node(__LINE__, 0); } | '[' constant_expression ']' { $$ = $2; } | direct_abstract_declarator '[' ']' { $$ = $1; } | direct_abstract_declarator '[' constant_expression ']' { $$ = ctx->node(__LINE__, 2, $1, $3); } | '(' ')' { $$ = ctx->node(__LINE__, 0); } | '(' parameter_type_list ')' { $$ = ctx->node(__LINE__, 1, $2); } | direct_abstract_declarator '(' ')' { $$ = ctx->node(__LINE__, 1, $1); } | direct_abstract_declarator '(' parameter_type_list ')' { $$ = ctx->node(__LINE__, 2, $1, $3); } ; initializer : assignment_expression { $$ = $1; } | '{' initializer_list '}' { $$ = ctx->node(__LINE__, 1, $2); } | '{' initializer_list ',' '}' { $$ = ctx->node(__LINE__, 1, $2); } ; initializer_list : initializer { $$ = $1; } | initializer_list ',' initializer { $$ = ctx->node(',', 2, $1, $3); } ; statement : labeled_statement { $$ = $1; } | compound_statement { $$ = $1; } | expression_statement { $$ = $1; } | selection_statement { $$ = $1; } | iteration_statement { $$ = $1; } | jump_statement { $$ = $1; } ; labeled_statement : IDENTIFIER ':' statement { $$ = ctx->node(IDENTIFIER, 2, $1, $3); } | CASE constant_expression ':' statement { $$ = ctx->node(CASE, 2, $2, $4); } | DEFAULT ':' statement { $$ = ctx->node(DEFAULT, 1, $3); } ; compound_statement : '{' '}' { $$ = ctx->node(__LINE__, 0); } | '{' statement_list '}' { $$ = ctx->node(__LINE__, 1, $2); } | '{' declaration_list '}' { $$ = ctx->node(__LINE__, 1, $2); } | '{' declaration_list statement_list '}' { $$ = ctx->node(__LINE__, 2, $2, $3); } ; declaration_list : declaration { $$ = $1; } | declaration_list declaration { $$ = ctx->node(',', 2, $1, $2); } ; statement_list : statement { $$ = $1; } | statement_list statement { $$ = ctx->node(',', 2, $1, $2); } ; expression_statement : ';' { $$ = ctx->node(__LINE__, 0); } | expression ';' { $$ = $1; } ; selection_statement : IF '(' expression ')' statement { $$ = ctx->node(IF, 2, $3, $5); } | IF '(' expression ')' statement ELSE statement { $$ = ctx->node(IF, 3, $3, $5, $7); } | SWITCH '(' expression ')' statement { $$ = ctx->node(SWITCH, 2, $3, $5); } ; iteration_statement : WHILE '(' expression ')' statement { $$ = ctx->node(WHILE, 2, $3, $5); } | DO statement WHILE '(' expression ')' ';' { $$ = ctx->node(DO, 2, $5, $2); } | FOR '(' expression_statement expression_statement ')' statement { $$ = ctx->node(FOR, 3, $3, $4, $6); } | FOR '(' expression_statement expression_statement expression ')' statement { $$ = ctx->node(FOR, 4, $3, $4, $5, $7); } ; jump_statement : GOTO IDENTIFIER ';' { $$ = ctx->node(GOTO, 1, $2); } | CONTINUE ';' { $$ = ctx->node(CONTINUE, 0); } | BREAK ';' { $$ = ctx->node(BREAK, 0); } | RETURN ';' { $$ = ctx->node(RETURN, 0); } | RETURN expression ';' { $$ = ctx->node(RETURN, 1, $2); } ; translation_unit : external_declaration { $$ = $1; } | translation_unit external_declaration { $$ = ctx->node(__LINE__, 2, $1, $2); } ; external_declaration : function_definition { $$ = $1; } | declaration { $$ = $1; } ; function_definition : declaration_specifiers declarator declaration_list compound_statement { $$ = ctx->node(__LINE__, 4, $1, $2, $3, $4); } | declaration_specifiers declarator compound_statement { $$ = ctx->node(__LINE__, 3, $1, $2, $3); } | declarator declaration_list compound_statement { $$ = ctx->node(__LINE__, 3, $1, $2, $3); } | declarator compound_statement { $$ = ctx->node(__LINE__, 2, $1, $2); } ; %%