1360 lines
34 KiB
Plaintext
1360 lines
34 KiB
Plaintext
%{
|
|
|
|
#include <stdio.h>
|
|
#include "parser.h"
|
|
#include <iostream>
|
|
|
|
#define yyerror(msg) handle_parse_error(msg, &yylloc)
|
|
|
|
int yylex(YYSTYPE *, YYLTYPE *);
|
|
|
|
%}
|
|
|
|
%pure-parser
|
|
%locations
|
|
%error-verbose
|
|
|
|
%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 SEMICOLON;
|
|
%token COLON;
|
|
%token QUESTION;
|
|
%token DOT;
|
|
%token ARROW;
|
|
%token COMMA;
|
|
%token ELLIPSIS;
|
|
|
|
%token LCURLY;
|
|
%token RCURLY;
|
|
%token LBRACKET;
|
|
%token RBRACKET;
|
|
%token LPAREN;
|
|
%token RPAREN;
|
|
|
|
|
|
%token VOID;
|
|
%token CHAR;
|
|
%token SHORT;
|
|
%token INT;
|
|
%token LONG;
|
|
%token FLOAT;
|
|
%token DOUBLE;
|
|
|
|
%token SIGNED;
|
|
%token UNSIGNED;
|
|
|
|
%token VOLATILE;
|
|
%token STATIC;
|
|
%token CONST;
|
|
%token EXTERN;
|
|
%token AUTO;
|
|
%token REGISTER;
|
|
%token INLINE;
|
|
|
|
%token STRUCT;
|
|
%token UNION;
|
|
%token ENUM;
|
|
|
|
%token TYPEDEF;
|
|
|
|
%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 SIZEOF;
|
|
%token ALIGNOF;
|
|
|
|
%token CHAR_CONST;
|
|
%token INT_CONST;
|
|
%token FLOAT_CONST;
|
|
%token STRING_LITERAL;
|
|
%token IDENTIFIER;
|
|
|
|
%token TYPE_NAME;
|
|
%token ATTRIBUTE;
|
|
%token RESTRICT;
|
|
%token ASM;
|
|
%token EXTENSION;
|
|
|
|
%start translation_unit
|
|
|
|
%%
|
|
|
|
constant
|
|
: INT_CONST { $$ = $1; }
|
|
| FLOAT_CONST { $$ = $1; }
|
|
| CHAR_CONST { $$ = $1; }
|
|
;
|
|
|
|
primary_expression
|
|
: IDENTIFIER { $$ = $1; }
|
|
| constant { $$ = $1; }
|
|
| string_literals { $$ = $1; }
|
|
| LPAREN expression RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
string_literals
|
|
: STRING_LITERAL {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| string_literals STRING_LITERAL {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
postfix_expression
|
|
: primary_expression { $$ = $1; }
|
|
| postfix_expression LBRACKET expression RBRACKET {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| postfix_expression LPAREN RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| postfix_expression LPAREN argument_expression_list RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| postfix_expression DOT IDENTIFIER {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| postfix_expression ARROW IDENTIFIER {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| postfix_expression INCREMENT {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| postfix_expression DECREMENT {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
argument_expression_list
|
|
: assignment_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| argument_expression_list COMMA assignment_expression {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
unary_expression
|
|
: postfix_expression { $$ = $1; }
|
|
| INCREMENT unary_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| DECREMENT unary_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| unary_operator cast_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| SIZEOF unary_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| SIZEOF LPAREN type_name RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| ALIGNOF unary_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| ALIGNOF LPAREN type_name RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| LCURLY initializer_list RCURLY {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| LCURLY initializer_list COMMA RCURLY {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
;
|
|
|
|
unary_operator
|
|
: BITAND { $$ = $1; }
|
|
| TIMES { $$ = $1; }
|
|
| PLUS { $$ = $1; }
|
|
| MINUS { $$ = $1; }
|
|
| BITNOT { $$ = $1; }
|
|
| NOT { $$ = $1; }
|
|
;
|
|
|
|
cast_expression
|
|
: unary_expression { $$ = $1; }
|
|
| LPAREN type_name RPAREN cast_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
;
|
|
|
|
multiplicative_expression
|
|
: cast_expression { $$ = $1; }
|
|
| multiplicative_expression TIMES cast_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| multiplicative_expression DIVIDE cast_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| multiplicative_expression MOD cast_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
additive_expression
|
|
: multiplicative_expression { $$ = $1; }
|
|
| additive_expression PLUS multiplicative_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| additive_expression MINUS multiplicative_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
shift_expression
|
|
: additive_expression { $$ = $1; }
|
|
| shift_expression LSHIFT additive_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| shift_expression RSHIFT additive_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
relational_expression
|
|
: shift_expression { $$ = $1; }
|
|
| relational_expression LESS shift_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| relational_expression GREATER shift_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| relational_expression LESSEQ shift_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| relational_expression GREATEREQ shift_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
equality_expression
|
|
: relational_expression { $$ = $1; }
|
|
| equality_expression EQUALS relational_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| equality_expression NOTEQUALS relational_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
and_expression
|
|
: equality_expression { $$ = $1; }
|
|
| and_expression BITAND equality_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
exclusive_or_expression
|
|
: and_expression { $$ = $1; }
|
|
| exclusive_or_expression XOR and_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
inclusive_or_expression
|
|
: exclusive_or_expression { $$ = $1; }
|
|
| inclusive_or_expression BITOR exclusive_or_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
logical_and_expression
|
|
: inclusive_or_expression { $$ = $1; }
|
|
| logical_and_expression AND inclusive_or_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
logical_or_expression
|
|
: logical_and_expression { $$ = $1; }
|
|
| logical_or_expression OR logical_and_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
conditional_expression
|
|
: logical_or_expression { $$ = $1; }
|
|
| logical_or_expression QUESTION expression COLON conditional_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
}
|
|
;
|
|
|
|
assignment_expression
|
|
: conditional_expression { $$ = $1; }
|
|
| unary_expression assignment_operator assignment_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
assignment_operator
|
|
: ASSIGN { $$ = $1; }
|
|
| MUL_ASSIGN { $$ = $1; }
|
|
| DIV_ASSIGN { $$ = $1; }
|
|
| MOD_ASSIGN { $$ = $1; }
|
|
| ADD_ASSIGN { $$ = $1; }
|
|
| SUB_ASSIGN { $$ = $1; }
|
|
| LEFT_ASSIGN { $$ = $1; }
|
|
| RIGHT_ASSIGN { $$ = $1; }
|
|
| AND_ASSIGN { $$ = $1; }
|
|
| XOR_ASSIGN { $$ = $1; }
|
|
| OR_ASSIGN { $$ = $1; }
|
|
;
|
|
|
|
expression
|
|
: assignment_expression { $$ = $1; }
|
|
| EXTENSION assignment_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| expression COMMA assignment_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
constant_expression
|
|
: conditional_expression { $$ = $1; }
|
|
;
|
|
|
|
declaration
|
|
: declaration_specifiers SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| declaration_specifiers init_declarator_list SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
for (auto d_s : *$1->list)
|
|
{
|
|
if ((d_s->type == NODE_TYPE_TOKEN) &&
|
|
(*d_s->token.text == "typedef"))
|
|
{
|
|
for (auto d : *$2->list)
|
|
{
|
|
observe_type_name(d);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
;
|
|
|
|
declaration_specifiers
|
|
: storage_class_specifier {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| storage_class_specifier declaration_specifiers {
|
|
$$ = $2;
|
|
$$->list->push_front($1);
|
|
}
|
|
| type_specifier {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| type_specifier declaration_specifiers {
|
|
$$ = $2;
|
|
$$->list->push_front($1);
|
|
}
|
|
| type_qualifier {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| type_qualifier declaration_specifiers {
|
|
$$ = $2;
|
|
$$->list->push_front($1);
|
|
}
|
|
| attribute_spec {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| attribute_spec declaration_specifiers {
|
|
$$ = $2;
|
|
$$->list->push_front($1);
|
|
}
|
|
;
|
|
|
|
init_declarator_list
|
|
: init_declarator {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| init_declarator_list COMMA init_declarator {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
init_declarator
|
|
: declarator { $$ = $1; }
|
|
| declarator ASSIGN initializer {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
storage_class_specifier
|
|
: TYPEDEF { $$ = $1; }
|
|
| EXTERN { $$ = $1; }
|
|
| INLINE { $$ = $1; }
|
|
| STATIC { $$ = $1; }
|
|
| AUTO { $$ = $1; }
|
|
| REGISTER { $$ = $1; }
|
|
;
|
|
|
|
type_specifier
|
|
: VOID { $$ = $1; }
|
|
| CHAR { $$ = $1; }
|
|
| SHORT { $$ = $1; }
|
|
| INT { $$ = $1; }
|
|
| LONG { $$ = $1; }
|
|
| FLOAT { $$ = $1; }
|
|
| DOUBLE { $$ = $1; }
|
|
| SIGNED { $$ = $1; }
|
|
| UNSIGNED { $$ = $1; }
|
|
| struct_or_union_specifier { $$ = $1; }
|
|
| enum_specifier { $$ = $1; }
|
|
| TYPE_NAME { $$ = $1; }
|
|
;
|
|
|
|
struct_or_union_specifier
|
|
: struct_or_union identifier_or_type_name LCURLY struct_declaration_list RCURLY {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
}
|
|
| struct_or_union LCURLY struct_declaration_list RCURLY {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| struct_or_union identifier_or_type_name {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
identifier_or_type_name
|
|
: IDENTIFIER { $$ = $1; }
|
|
| TYPE_NAME { $$ = $1; }
|
|
;
|
|
|
|
struct_or_union
|
|
: STRUCT { $$ = $1; }
|
|
| UNION { $$ = $1; }
|
|
;
|
|
|
|
struct_declaration_list
|
|
: struct_declaration {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| struct_declaration_list struct_declaration {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
struct_declaration
|
|
: specifier_qualifier_list SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| specifier_qualifier_list struct_declarator_list SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
specifier_qualifier_list
|
|
: type_specifier specifier_qualifier_list {
|
|
$$ = $2;
|
|
$$->list->push_front($1);
|
|
}
|
|
| type_specifier {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| type_qualifier specifier_qualifier_list {
|
|
$$ = $2;
|
|
$$->list->push_front($1);
|
|
}
|
|
| type_qualifier {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
;
|
|
|
|
struct_declarator_list
|
|
: struct_declarator {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| struct_declarator_list COMMA struct_declarator {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
struct_declarator
|
|
: declarator { $$ = $1; }
|
|
| COLON constant_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| declarator COLON constant_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
enum_specifier
|
|
: ENUM LCURLY enumerator_list RCURLY {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| ENUM IDENTIFIER LCURLY enumerator_list RCURLY {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
}
|
|
| ENUM IDENTIFIER {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
enumerator_list
|
|
: enumerator {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| enumerator_list COMMA enumerator {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
enumerator
|
|
: IDENTIFIER { $$ = $1; }
|
|
| IDENTIFIER ASSIGN constant_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
type_qualifier
|
|
: CONST { $$ = $1; }
|
|
| VOLATILE { $$ = $1; }
|
|
| RESTRICT { $$ = $1; }
|
|
| EXTENSION { $$ = $1; }
|
|
;
|
|
|
|
declarator
|
|
: pointer direct_declarator attributes {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| direct_declarator attributes {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
direct_declarator
|
|
: IDENTIFIER {
|
|
$$ = $1;
|
|
$$->declarator_name = $1->token.text;
|
|
}
|
|
| LPAREN declarator RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| direct_declarator LBRACKET constant_expression RBRACKET {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| direct_declarator LBRACKET RBRACKET {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| direct_declarator LPAREN parameter_type_list RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| direct_declarator LPAREN identifier_list RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| direct_declarator LPAREN RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
pointer
|
|
: TIMES { $$ = $1; }
|
|
| TIMES type_qualifier_list {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| TIMES pointer {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| TIMES type_qualifier_list pointer {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
type_qualifier_list
|
|
: type_qualifier {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| type_qualifier_list type_qualifier {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
parameter_type_list
|
|
: parameter_list { $$ = $1; }
|
|
| parameter_list COMMA ELLIPSIS {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
parameter_list
|
|
: parameter_declaration {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| parameter_list COMMA parameter_declaration {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
parameter_declaration
|
|
: declaration_specifiers declarator {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| declaration_specifiers abstract_declarator {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| declaration_specifiers { $$ = $1; }
|
|
;
|
|
|
|
identifier_list
|
|
: IDENTIFIER {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| identifier_list COMMA IDENTIFIER {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
type_name
|
|
: specifier_qualifier_list { $$ = $1; }
|
|
| specifier_qualifier_list abstract_declarator {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
abstract_declarator
|
|
: pointer { $$ = $1; }
|
|
| direct_abstract_declarator { $$ = $1; }
|
|
| pointer direct_abstract_declarator {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
direct_abstract_declarator
|
|
: LPAREN abstract_declarator RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| LBRACKET RBRACKET {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| LBRACKET constant_expression RBRACKET {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| direct_abstract_declarator LBRACKET RBRACKET {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| direct_abstract_declarator LBRACKET constant_expression RBRACKET {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| LPAREN RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| LPAREN parameter_type_list RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| direct_abstract_declarator LPAREN RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| direct_abstract_declarator LPAREN parameter_type_list RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
;
|
|
|
|
initializer
|
|
: assignment_expression { $$ = $1; }
|
|
;
|
|
|
|
initializer_list
|
|
: initializer {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| initializer_list COMMA initializer {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
statement
|
|
: labeled_statement { $$ = $1; }
|
|
| compound_statement { $$ = $1; }
|
|
| expression_statement { $$ = $1; }
|
|
| selection_statement { $$ = $1; }
|
|
| iteration_statement { $$ = $1; }
|
|
| jump_statement { $$ = $1; }
|
|
| asm_statement { $$ = $1; }
|
|
;
|
|
|
|
labeled_statement
|
|
: IDENTIFIER COLON statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| CASE constant_expression COLON statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| DEFAULT COLON statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
compound_statement
|
|
: LCURLY RCURLY {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| LCURLY statement_list RCURLY {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| LCURLY declaration_list RCURLY {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| LCURLY declaration_list statement_list RCURLY {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
;
|
|
|
|
declaration_list
|
|
: declaration {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| declaration_list declaration {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
statement_list
|
|
: statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| statement_list statement {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
expression_statement
|
|
: SEMICOLON { $$ = $1; }
|
|
| expression SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
selection_statement
|
|
: IF LPAREN expression RPAREN statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
}
|
|
| IF LPAREN expression RPAREN statement ELSE statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
$$->list->push_back($6);
|
|
$$->list->push_back($7);
|
|
}
|
|
| SWITCH LPAREN expression RPAREN statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
}
|
|
;
|
|
|
|
iteration_statement
|
|
: WHILE LPAREN expression RPAREN statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
}
|
|
| DO statement WHILE LPAREN expression RPAREN SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
$$->list->push_back($6);
|
|
$$->list->push_back($7);
|
|
}
|
|
| FOR LPAREN expression_statement expression_statement RPAREN statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
$$->list->push_back($6);
|
|
}
|
|
| FOR LPAREN expression_statement expression_statement expression RPAREN statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
$$->list->push_back($6);
|
|
$$->list->push_back($7);
|
|
}
|
|
| FOR LPAREN declaration expression_statement RPAREN statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
$$->list->push_back($6);
|
|
}
|
|
| FOR LPAREN declaration expression_statement expression RPAREN statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
$$->list->push_back($6);
|
|
$$->list->push_back($7);
|
|
}
|
|
;
|
|
|
|
jump_statement
|
|
: GOTO IDENTIFIER SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
| CONTINUE SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| BREAK SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| RETURN SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| RETURN expression SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
asm_statement
|
|
: asm_expression SEMICOLON {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
asm_expression
|
|
: ASM LPAREN string_literals asm_operands RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
}
|
|
| ASM VOLATILE LPAREN string_literals asm_operands RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
$$->list->push_back($6);
|
|
}
|
|
;
|
|
|
|
asm_operands
|
|
: { $$ = new Node(NODE_TYPE_NULL); }
|
|
| asm_operand { $$ = $1; }
|
|
| asm_operands asm_operand {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
asm_operand
|
|
: COLON primary_expressions {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
primary_expressions
|
|
: primary_expression { $$ = $1; }
|
|
| primary_expressions primary_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
translation_unit
|
|
: external_declaration {
|
|
$$ = $1;
|
|
set_translation_unit_node($$);
|
|
}
|
|
| translation_unit external_declaration {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
set_translation_unit_node($$);
|
|
}
|
|
;
|
|
|
|
external_declaration
|
|
: function_definition { $$ = $1; }
|
|
| declaration { $$ = $1; }
|
|
;
|
|
|
|
function_definition
|
|
: declaration_specifiers declarator declaration_list attributes compound_statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
}
|
|
| declaration_specifiers declarator attributes compound_statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| declarator declaration_list attributes compound_statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
| declarator attributes compound_statement {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
attributes
|
|
: { $$ = new Node(NODE_TYPE_NULL); }
|
|
| attribute_spec { $$ = $1; }
|
|
| attributes attribute_spec {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
| asm_expression { $$ = $1; }
|
|
| attributes asm_expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
}
|
|
;
|
|
|
|
attribute_spec
|
|
: ATTRIBUTE LPAREN LPAREN attribute_list RPAREN RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
$$->list->push_back($5);
|
|
$$->list->push_back($6);
|
|
}
|
|
;
|
|
|
|
attribute_list
|
|
: attribute {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| attribute_list COMMA attribute {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
attribute
|
|
: IDENTIFIER { $$ = $1; }
|
|
| IDENTIFIER LPAREN expression_list RPAREN {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
$$->list->push_back($4);
|
|
}
|
|
;
|
|
|
|
expression_list
|
|
: expression {
|
|
$$ = new Node(NODE_TYPE_LIST);
|
|
$$->list->push_back($1);
|
|
}
|
|
| expression_list COMMA expression {
|
|
$$ = $1;
|
|
$$->list->push_back($2);
|
|
$$->list->push_back($3);
|
|
}
|
|
;
|
|
|
|
%%
|