summaryrefslogtreecommitdiffstats
path: root/src/uscxml/plugins/datamodel/c89/parser/c89.ypp
diff options
context:
space:
mode:
authorStefan Radomski <github@mintwerk.de>2016-07-11 12:55:48 (GMT)
committerStefan Radomski <github@mintwerk.de>2016-07-11 12:55:48 (GMT)
commit1a362feda9d514ee30ad8815394ce11da2bdd29a (patch)
tree284d708961830b3a1863597e4330c695cc52993c /src/uscxml/plugins/datamodel/c89/parser/c89.ypp
parentf06269c9ecfa94c966d0f453b2c8f03ccf8279cf (diff)
downloaduscxml-1a362feda9d514ee30ad8815394ce11da2bdd29a.zip
uscxml-1a362feda9d514ee30ad8815394ce11da2bdd29a.tar.gz
uscxml-1a362feda9d514ee30ad8815394ce11da2bdd29a.tar.bz2
More work on ANSI C datamodel
Diffstat (limited to 'src/uscxml/plugins/datamodel/c89/parser/c89.ypp')
-rw-r--r--src/uscxml/plugins/datamodel/c89/parser/c89.ypp681
1 files changed, 681 insertions, 0 deletions
diff --git a/src/uscxml/plugins/datamodel/c89/parser/c89.ypp b/src/uscxml/plugins/datamodel/c89/parser/c89.ypp
new file mode 100644
index 0000000..8e113c8
--- /dev/null
+++ b/src/uscxml/plugins/datamodel/c89/parser/c89.ypp
@@ -0,0 +1,681 @@
+%{
+#include "../C89Parser.h"
+#include "c89.tab.hpp"
+#include <sys/types.h>
+#include <stdarg.h>
+
+#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 <node> primary_expression expression postfix_expression
+%type <node> argument_expression_list assignment_expression
+%type <node> unary_expression unary_operator cast_expression
+%type <node> type_name assignment_operator
+%type <node> multiplicative_expression additive_expression shift_expression
+%type <node> relational_expression equality_expression and_expression
+%type <node> exclusive_or_expression inclusive_or_expression
+%type <node> logical_and_expression logical_or_expression conditional_expression
+%type <node> specifier_qualifier_list abstract_declarator
+%type <node> type_specifier type_qualifier struct_or_union_specifier
+%type <node> enum_specifier pointer direct_abstract_declarator
+%type <node> struct_or_union enumerator_list enumerator
+%type <node> constant_expression type_qualifier_list
+%type <node> parameter_type_list parameter_declaration parameter_list
+%type <node> declaration_specifiers declarator storage_class_specifier
+%type <node> init_declarator_list init_declarator initializer
+%type <node> direct_declarator initializer_list identifier_list
+%type <node> statement labeled_statement compound_statement expression_statement
+%type <node> selection_statement iteration_statement jump_statement
+%type <node> statement_list declaration_list declaration
+%type <node> translation_unit external_declaration function_definition
+%type <node> struct_declarator struct_declaration
+%type <node> struct_declarator_list struct_declaration_list
+
+%type <node> VOID CHAR SHORT INT LONG FLOAT DOUBLE SIGNED UNSIGNED TYPE_NAME
+%type <node> CONST VOLATILE
+
+%type <value> 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);
+ }
+ ;
+
+%%