0
|
1 %skeleton "lalr1.cc"
|
|
2 %define "parser_class_name" "script_parser"
|
|
3 %defines
|
|
4 %{
|
|
5 #ifdef _MSC_VER
|
|
6 #pragma warning(disable: 4800)
|
|
7 #pragma warning(disable: 4267)
|
|
8 #endif
|
|
9
|
|
10 #include <string>
|
|
11 #include "node.h"
|
|
12 class compiler;
|
|
13 %}
|
|
14 %parse-param { compiler& driver }
|
|
15 %lex-param { compiler& driver }
|
|
16 %locations
|
|
17 %expect 1 /* if文で衝突が発生するので、1つの衝突は無視 */
|
|
18 %initial-action
|
|
19 {
|
|
20 // ロケーション初期化
|
|
21 @$.begin.filename = @$.end.filename = &driver.get_filename();
|
|
22 } ;
|
|
23 // %debug
|
|
24 %error-verbose
|
|
25 // Symbols.
|
|
26 %union
|
|
27 {
|
|
28 int ival;
|
|
29 std::string *sval;
|
|
30
|
|
31 int type;
|
|
32 CValueList *value_list;
|
|
33 CArgList *arglist;
|
|
34 CDeclList *decls;
|
|
35 CStateList *states;
|
|
36 CStatement *statement;
|
|
37 CArgDef *argdef;
|
|
38 CArgs *args;
|
|
39 CValueNode *value;
|
|
40 CNode *expr;
|
|
41 CAssign *assign;
|
|
42 CStateBlock *block;
|
|
43 }
|
|
44 %{
|
|
45 #include "compiler.h"
|
|
46 %}
|
|
47
|
|
48 %token END_OF_FILE 0 "end of file"
|
|
49 %token <ival> TK_IVAL "ival"
|
|
50 %token <sval> TK_IDENTIFIER "identifier"
|
|
51 %token <sval> TK_SVAL "sval"
|
|
52 %token TK_LOGOR "||"
|
|
53 %token TK_LOGAND "&&"
|
|
54 %token TK_EQ "=="
|
|
55 %token TK_NE "!="
|
|
56 %token TK_GE ">="
|
|
57 %token TK_LE "<="
|
|
58 %token TK_LSHIFT "<<"
|
|
59 %token TK_RSHIFT ">>"
|
|
60 %token TK_ADD_ASSIGN "+="
|
|
61 %token TK_SUB_ASSIGN "-="
|
|
62 %token TK_MUL_ASSIGN "*="
|
|
63 %token TK_DIV_ASSIGN "/="
|
|
64 %token TK_MOD_ASSIGN "%="
|
|
65
|
|
66 %token TK_IF "if"
|
|
67 %token TK_ELSE "else"
|
|
68 %token TK_WHILE "while"
|
|
69 %token TK_FOR "for"
|
|
70 %token TK_SWITCH "switch"
|
|
71 %token TK_CASE "case"
|
|
72 %token TK_DEFAULT "default"
|
|
73 %token TK_BREAK "break"
|
|
74 %token TK_RETURN "return"
|
|
75 %token TK_INTEGER "int"
|
|
76 %token TK_STRING "string"
|
|
77 %token TK_VOID "void"
|
|
78
|
|
79 %type <expr> expr
|
|
80 %type <value> value
|
|
81 %type <assign> assign
|
|
82 %type <value_list> value_list
|
|
83 %type <arglist> arglist
|
|
84 %type <argdef> arg
|
|
85 %type <decls> decls decl_list
|
|
86 %type <states> states state_list
|
|
87 %type <block> block
|
|
88 %type <args> args
|
|
89 %type <statement> statement
|
|
90 %type <type> type
|
|
91
|
|
92 %destructor { delete $$; } "identifier"
|
|
93 %destructor { delete $$; } "sval"
|
|
94
|
|
95 %destructor { delete $$; } value_list
|
|
96 %destructor { delete $$; } arglist
|
|
97 %destructor { delete $$; } arg
|
|
98 %destructor { delete $$; } decls decl_list
|
|
99 %destructor { delete $$; } states state_list
|
|
100 %destructor { delete $$; } args
|
|
101 %destructor { delete $$; } block
|
|
102 %destructor { delete $$; } assign
|
|
103 %destructor { delete $$; } statement
|
|
104 %destructor { delete $$; } value
|
|
105 %destructor { delete $$; } expr
|
|
106
|
|
107 %left "||";
|
|
108 %left "&&";
|
|
109 %nonassoc "==" "!=" '>' '<' ">=" "<=";
|
|
110 %left '&' '|';
|
|
111 %left "<<" ">>";
|
|
112 %left '+' '-';
|
|
113 %left '*' '/' '%';
|
|
114 %left NEG;
|
|
115 %%
|
|
116 %start unit;
|
|
117
|
|
118 unit : define_or_state
|
|
119 | unit define_or_state
|
|
120 ;
|
|
121
|
|
122 define_or_state : error ';'
|
|
123 | function
|
|
124 | declaration
|
|
125 ;
|
|
126
|
|
127 declaration : type value_list ';' { driver.DefineValue(@2, $1, $2); }
|
|
128 | type "identifier" '(' ')' ';' { driver.DefineFunction(@2, $1, $2, NULL); }
|
|
129 | type "identifier" '(' arglist ')' ';' { driver.DefineFunction(@2, $1, $2, $4); }
|
|
130 | "void" "identifier" '(' ')' ';' { driver.DefineFunction(@2, TYPE_VOID, $2, NULL); }
|
|
131 | "void" "identifier" '(' arglist ')' ';' { driver.DefineFunction(@2, TYPE_VOID, $2, $4); }
|
|
132 ;
|
|
133
|
|
134 value_list : value { $$ = new CValueList($1); }
|
|
135 | value_list ',' value { $$ = $1->Add($3); }
|
|
136 ;
|
|
137
|
|
138 arglist : arg { $$ = new CArgList($1); }
|
|
139 | arglist ',' arg { $$ = $1->Add($3); }
|
|
140 ;
|
|
141
|
|
142 arg : type { $$ = new CArgDef(@1, $1, NULL); }
|
|
143 | type '&' { $$ = new CArgDef(@1, TypeToRef($1), NULL); }
|
|
144 | type "identifier" { $$ = new CArgDef(@1, $1, $2); }
|
|
145 | type '&' "identifier" { $$ = new CArgDef(@1, TypeToRef($1), $3); }
|
|
146 | type "identifier" '[' ']' { $$ = new CArgDef(@1, TypeToRef($1), $2); }
|
|
147 | type '&' "identifier" '[' ']' { $$ = new CArgDef(@1, TypeToRef($1), $3); }
|
|
148 ;
|
|
149
|
|
150 function : type "identifier" '(' ')' block { driver.AddFunction(@1, $1, $2, NULL, $5); }
|
|
151 | type "identifier" '(' arglist ')' block { driver.AddFunction(@1, $1, $2, $4, $6); }
|
|
152 | "void" "identifier" '(' ')' block { driver.AddFunction(@1, TYPE_VOID, $2, NULL, $5); }
|
|
153 | "void" "identifier" '(' arglist ')' block { driver.AddFunction(@1, TYPE_VOID, $2, $4, $6); }
|
|
154 ;
|
|
155
|
|
156 type : "int" { $$ = TYPE_INTEGER; }
|
|
157 | "string" { $$ = TYPE_STRING; }
|
|
158 ;
|
|
159
|
|
160 block : '{' decl_list state_list '}' { $$ = new CStateBlock($2, $3); }
|
|
161 ;
|
|
162
|
|
163 decl_list : { $$ = NULL }
|
|
164 | decls { $$ = $1 }
|
|
165 ;
|
|
166
|
|
167 state_list : { $$ = NULL }
|
|
168 | states { $$ = $1 }
|
|
169 ;
|
|
170
|
|
171 decls : type value_list ';' { $$ = new CDeclList(new CDecl($1, $2)); }
|
|
172 | decls type value_list ';' { $$ = $1->Add(new CDecl($2, $3)); }
|
|
173 ;
|
|
174
|
|
175 states : statement { $$ = new CStateList($1); }
|
|
176 | states statement { $$ = $1->Add($2); }
|
|
177 ;
|
|
178
|
|
179 statement : ';' { $$ = new CNopStatement(@1); }
|
|
180 | assign ';' { $$ = new CAssignStatement(@1, $1); }
|
|
181 | "identifier" '(' args ')' ';' { $$ = new CFunctionStatement(@1, $1, $3); }
|
|
182 | "identifier" '(' ')' ';' { $$ = new CFunctionStatement(@1, $1, NULL); }
|
|
183 | "case" expr ':' { $$ = new CCaseStatement(@1, $2); }
|
|
184 | "default" ':' { $$ = new CDefaultStatement(@1); }
|
|
185 | "break" ';' { $$ = new CBreakStatement(@1); }
|
|
186 | "return" ';' { $$ = new CReturnStatement(@1, NULL); }
|
|
187 | "return" expr ';' { $$ = new CReturnStatement(@1, $2); }
|
|
188 | "if" '(' expr ')' statement { $$ = new CIfStatement(@1, $3, $5); }
|
|
189 | "if" '(' expr ')' statement "else" statement { $$ = new CIfStatement(@1, $3, $5, $7); }
|
|
190 | "for" '(' assign ';' expr ';' assign ')' statement
|
|
191 { $$ = new CForStatement(@1, $3, $5, $7, $9); }
|
|
192 | "while" '(' expr ')' statement { $$ = new CWhileStatement(@1, $3, $5); }
|
|
193 | "switch" '(' expr ')' '{' state_list '}' { $$ = new CSwitchStatement(@1, $3, $6); }
|
|
194 | block { $$ = new CBlockStatement(@1, $1); }
|
|
195 ;
|
|
196
|
|
197 assign : value '=' expr { $$ = new CAssign(@1, '=', $1, $3); }
|
|
198 | value "+=" expr { $$ = new CAssign(@1, '+', $1, $3); }
|
|
199 | value "-=" expr { $$ = new CAssign(@1, '-', $1, $3); }
|
|
200 | value "*=" expr { $$ = new CAssign(@1, '*', $1, $3); }
|
|
201 | value "/=" expr { $$ = new CAssign(@1, '/', $1, $3); }
|
|
202 | value "%=" expr { $$ = new CAssign(@1, '%', $1, $3); }
|
|
203 ;
|
|
204
|
|
205 expr : expr "&&" expr { $$ = CNode::MakeNode(driver, @2, OP_LOGAND, $1, $3); }
|
|
206 | expr "||" expr { $$ = CNode::MakeNode(driver, @2, OP_LOGOR, $1, $3); }
|
|
207 | expr "==" expr { $$ = CNode::MakeNode(driver, @2, OP_EQ, $1, $3); }
|
|
208 | expr "!=" expr { $$ = CNode::MakeNode(driver, @2, OP_NE, $1, $3); }
|
|
209 | expr '>' expr { $$ = CNode::MakeNode(driver, @2, OP_GT, $1, $3); }
|
|
210 | expr ">=" expr { $$ = CNode::MakeNode(driver, @2, OP_GE, $1, $3); }
|
|
211 | expr '<' expr { $$ = CNode::MakeNode(driver, @2, OP_LT, $1, $3); }
|
|
212 | expr "<=" expr { $$ = CNode::MakeNode(driver, @2, OP_LE, $1, $3); }
|
|
213 | expr '&' expr { $$ = CNode::MakeNode(driver, @2, OP_AND, $1, $3); }
|
|
214 | expr '|' expr { $$ = CNode::MakeNode(driver, @2, OP_OR, $1, $3); }
|
|
215 | expr "<<" expr { $$ = CNode::MakeNode(driver, @2, OP_LSHIFT, $1, $3); }
|
|
216 | expr ">>" expr { $$ = CNode::MakeNode(driver, @2, OP_RSHIFT, $1, $3); }
|
|
217 | expr '-' expr { $$ = CNode::MakeNode(driver, @2, OP_MINUS, $1, $3); }
|
|
218 | expr '+' expr { $$ = CNode::MakeNode(driver, @2, OP_PLUS, $1, $3); }
|
|
219 | expr '*' expr { $$ = CNode::MakeNode(driver, @2, OP_TIMES, $1, $3); }
|
|
220 | expr '/' expr { $$ = CNode::MakeNode(driver, @2, OP_DIVIDE, $1, $3); }
|
|
221 | expr '%' expr { $$ = CNode::MakeNode(driver, @2, OP_MOD, $1, $3); }
|
|
222 | '-' expr %prec NEG { $$ = CNode::MakeNode(driver, @2, OP_NEG, $2); }
|
|
223 | '(' expr ')' { $$ = $2; }
|
|
224 | value { $$ = $1; }
|
|
225 | "ival" { $$ = new CNode(@1, OP_CONST, $1); }
|
|
226 | "sval" { $$ = new CNode(@1, OP_STRING, $1); }
|
|
227 | "identifier" '(' args ')' { $$ = new CFunctionNode(@1, $1, $3); }
|
|
228 | "identifier" '(' ')' { $$ = new CFunctionNode(@1, $1, NULL); }
|
|
229 ;
|
|
230
|
|
231 value : "identifier" { $$ = new CValueNode(@1, $1); }
|
|
232 | "identifier" '[' expr ']' { $$ = new CValueNode(@1, $1, $3); }
|
|
233 ;
|
|
234
|
|
235 args : expr { $$ = new CArgs($1); }
|
|
236 | args ',' expr { $$ = $1->Add($3); }
|
|
237 ;
|
|
238
|
|
239 %%
|
|
240 void yy::script_parser::error(const yy::script_parser::location_type& l, const std::string& m)
|
|
241 {
|
|
242 driver.error(l, m);
|
|
243 }
|