/
calculator1.lalrpop
283 lines (255 loc) · 13.7 KB
/
calculator1.lalrpop
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
use std::str::FromStr;
use ast::{If, Expression, Block, Variable, ClassNameReference};
grammar;
T_NUMBER : String = {
<s:r"([0-9]+)"> => s.to_string(),
<s:r"([0-9]+)\.([0-9]+)"> => s.to_string()
};
T_VARIABLE : String = { <s:r"\$([a-zA-Z\_]+)([0-9a-zA-Z\_]*)"> => s.to_string() };
T_STATIC : String = { <s:r"\[a-zA-Z0-9\_\/\\\]+"> => s.to_string() };
T_INCLUDE = { "include" };
T_INCLUDE_ONCE = { "include_once" };
T_EVAL = { "eval" };
T_REQUIRE = { "require" };
T_REQUIRE_ONCE = { "require_once" };
T_LOGICAL_OR = { "or" };
T_LOGICAL_XOR = { "xor" };
T_LOGICAL_AND = { "and" };
T_PRINT = { "print" };
T_YIELD = { "yield" };
T_YIELD_FROM = { "yield from" };
T_PLUS_EQUAL = { "+=" };
T_MINUS_EQUAL = { "-=" };
T_MUL_EQUAL = { "*=" };
T_DIV_EQUAL = { "/=" };
T_CONCAT_EQUAL = { ".=" };
T_MOD_EQUAL = { "%=" };
T_AND_EQUAL = { "&=" };
T_OR_EQUAL = { "|=" };
T_XOR_EQUAL = { "^=" };
T_SL_EQUAL = { "<<=" };
T_SR_EQUAL = { ">>=" };
T_BOOLEAN_OR = { "||" };
T_BOOLEAN_AND = { "&&" };
T_IS_EQUAL = { "==" };
T_IS_NOT_EQUAL = { "!=" };
T_IS_IDENTICAL = { "===" };
T_IS_NOT_IDENTICAL = { "!==" };
T_IS_SMALLER_OR_EQUAL = { "<=" };
T_IS_GREATER_OR_EQUAL = { ">=" };
T_SPACESHIP = { "<=>" };
T_SL = { "<<" };
T_SR = { ">>" };
T_INSTANCEOF = { "instanceof" };
T_INC = { "++" };
T_DEC = { "--" };
T_INT_CAST = { "(int)" };
T_DOUBLE_CAST = { "(double)" };
T_STRING_CAST = { "(string)" };
T_ARRAY_CAST = { "(array)" };
T_OBJECT_CAST = { "(object)" };
T_BOOL_CAST = { "(bool)" };
T_UNSET_CAST = { "(unset)" };
T_NEW = { "new (T_NEW)" };
T_CLONE = { "clone" };
T_EXIT = { "exit" };
T_IF = { "if" };
T_ELSEIF = { "elseif" };
T_ELSE = { "else" };
T_ENDIF = { "endif" };
T_ECHO = { "echo" };
T_DO = { "do" };
T_WHILE = { "while" };
T_ENDWHILE = { "endwhile" };
T_FOR = { "for" };
T_ENDFOR = { "endfor" };
T_FOREACH = { "foreach" };
T_ENDFOREACH = { "endforeach" };
T_DECLARE = { "declare" };
T_ENDDECLARE = { "enddeclare" };
T_AS = { "as" };
T_SWITCH = { "switch" };
T_ENDSWITCH = { "endswitch" };
T_CASE = { "case" };
T_DEFAULT = { "default" };
T_BREAK = { "break" };
T_CONTINUE = { "continue" };
T_GOTO = { "goto" };
T_FUNCTION = { "function" };
T_CONST = { "cons" };
T_RETURN = { "return" };
T_TRY = { "try" };
T_CATCH = { "catch" };
T_FINALLY = { "finally" };
T_THROW = { "throw" };
T_USE = { "use" };
T_INSTEADOF = { "insteadof" };
T_GLOBAL = { "global" };
//T_STATIC = { "static" };
T_ABSTRACT = { "abstract" };
T_FINAL = { "final" };
T_PRIVATE = { "private" };
T_PROTECTED = { "protected" };
T_PUBLIC = { "public" };
T_VAR = { "var" };
T_UNSET = { "unset" };
T_ISSET = { "isset" };
T_EMPTY = { "empty" };
T_HALT_COMPILER = {"__halt_compiler" };
T_CLASS = { "class" };
T_TRAIT = { "trait" };
T_INTERFACE = { "interface" };
T_EXTENDS = { "extends" };
T_IMPLEMENTS = { "implements" };
T_OBJECT_OPERATOR = { "->" };
T_DOUBLE_ARROW = { "=>" };
T_LIST = { "list" };
T_ARRAY = { "array" };
T_CALLABLE = { "callable" };
T_LINE = { "__LINE__" };
T_FILE = { "__FILE__" };
T_DIR = { "__DIR__" };
T_CLASS_C = { "__CLASS__" };
T_TRAIT_C = { "__TRAIT__" };
T_METHOD_C = { "__METHOD__" };
T_FUNC_C = { "__FUNCTION__" };
T_COMMENT = { "comment" }; // TODO
T_DOC_COMMENT = { "doc comment" }; // TODO
T_OPEN_TAG = { "open tag" }; // TODO
T_OPEN_TAG_WITH_ECHO = { "open tag with echo" }; // TODO
T_CLOSE_TAG = { "close tag" }; // TODO
T_WHITESPACE = { "whitespace" }; // TODO
T_START_HEREDOC = { "heredoc start " }; // TODO
T_END_HEREDOC = { "heredoc end" }; // TODO
T_DOLLAR_OPEN_CURLY_BRACES = { "${" };
T_CURLY_OPEN = { "{$" };
T_PAAMAYIM_NEKUDOTAYIM = { "::" };
T_NAMESPACE = { "namespace" };
T_NS_C = { "__NAMESPACE__" };
T_NS_SEPARATOR = { "\\" };
T_ELLIPSIS = { "..." };
T_COALESCE = { "??" };
T_POW = { "**" };
T_POW_EQUAL = { "**=" };
pub variable : Box<Variable> = {
simple_variable
// | dereferencable '[' optional_expr ']'
// | constant '[' optional_expr ']'
// | dereferencable '{' expr '}'
// | dereferencable T_OBJECT_OPERATOR property_name argument_list
// | function_call { $$ = $1; }
};
pub simple_variable : Box<Variable> = {
<a:"${"> <expr:expr> <c:"}"> => { Box::new(Variable::Expression(expr)) },
<a:"$"> <var:simple_variable> => { Box::new(Variable::Variable(var)) },
<var:T_VARIABLE> => { Box::new(Variable::Identifier(var)) }
};
pub expr : Box<Expression> = {
<v1:variable> <op:"="> <expr:expr> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:"=&"> <expr:expr> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_PLUS_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_MINUS_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_MUL_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_POW_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_DIV_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_CONCAT_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_MOD_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_AND_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_OR_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_XOR_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_SL_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_SR_EQUAL> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_BOOLEAN_AND> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_LOGICAL_OR> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_LOGICAL_AND> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<v1:variable> <op:T_LOGICAL_XOR> <expr:expr0> => { Box::new(Expression::AssignOp { op: op.to_string(), var: v1, expr_right: expr }) },
<expr:expr0> <op:T_INSTANCEOF> <class_name_reference:class_name_reference> => { Box::new(Expression::Instanceof { class_name_reference: class_name_reference, expr: expr }) },
<expr:expr0> <a:"?"> <expr_if:expr0> <b:":"> <expr_else:expr0> => { Box::new(Expression::Conditional { expr: expr, expr_if: Box::new(Some(expr_if)), expr_else: expr_else }) },
<expr:expr0> <a:"?"> <b:":"> <expr_else:expr0> => { Box::new(Expression::Conditional { expr: expr, expr_if: Box::new(None), expr_else: expr_else }) },
<expr:expr0> => { expr }
};
expr0 : Box<Expression> = {
<op:T_CLONE> <expr:expr1> => { Box::new(Expression::CloneOp { expr: expr }) },
new_expr => <>,
<expr_left:expr0> <op:T_BOOLEAN_OR> <expr_right:expr1> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
<expr:expr1> => { expr }
};
expr1 : Box<Expression> = {
<expr_left:expr1> <op:"|"> <expr_right:expr2> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
<expr_left:expr1> <op:"&"> <expr_right:expr2> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
<expr_left:expr1> <op:"^"> <expr_right:expr2> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
<expr_left:expr1> <op:"."> <expr_right:expr2> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
<expr_left:expr1> <op:"+"> <expr_right:expr2> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
<expr_left:expr1> <op:"-"> <expr_right:expr2> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
<expr_left:expr1> <op:"*"> <expr_right:expr2> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
<expr_left:expr1> <op:"/"> <expr_right:expr2> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
<expr_left:expr1> <op:"%"> <expr_right:expr2> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
<expr_left:expr1> <op:T_SL> <expr_right:expr2> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
<expr_left:expr1> <op:T_SR> <expr_right:expr2> => { Box::new(Expression::ExpressionOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right }) },
expr2 => <>
};
expr2 : Box<Expression> = {
<expr_left:expr2> <op:T_POW> <expr_right:expr3> => { Box::new(Expression::BinaryOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right}) },
<expr_left:expr2> <op:T_IS_IDENTICAL> <expr_right:expr3> => { Box::new(Expression::BinaryOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right}) },
<expr_left:expr2> <op:T_IS_NOT_IDENTICAL> <expr_right:expr3> => { Box::new(Expression::BinaryOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right}) },
<expr_left:expr2> <op:T_IS_EQUAL> <expr_right:expr3> => { Box::new(Expression::BinaryOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right}) },
<expr_left:expr2> <op:T_IS_NOT_EQUAL> <expr_right:expr3> => { Box::new(Expression::BinaryOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right}) },
<expr_left:expr2> <op:"<"> <expr_right:expr3> => { Box::new(Expression::BinaryOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right}) },
<expr_left:expr2> <op:T_IS_SMALLER_OR_EQUAL> <expr_right:expr3> => { Box::new(Expression::BinaryOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right}) },
<expr_left:expr2> <op:">"> <expr_right:expr3> => { Box::new(Expression::BinaryOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right}) },
<expr_left:expr2> <op:T_IS_GREATER_OR_EQUAL> <expr_right:expr3> => { Box::new(Expression::BinaryOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right}) },
<expr_left:expr2> <op:T_SPACESHIP> <expr_right:expr3> => { Box::new(Expression::BinaryOp { op: op.to_string(), expr_left: expr_left, expr_right: expr_right}) },
expr3 => <>
};
expr3 : Box<Expression> = {
<v1:variable> <op:T_INC> => { Box::new(Expression::Increment(v1, true)) },
<v1:variable> <op:T_DEC> => { Box::new(Expression::Decrement(v1, true)) },
<op:T_INC> <v1:variable> => { Box::new(Expression::Increment(v1, false)) },
<op:T_DEC> <v1:variable> => { Box::new(Expression::Decrement(v1, false)) },
<op:"!"> <expr:expr3> => { Box::new(Expression::UnaryOp { op: op.to_string(), expr: expr}) },
<op:"~"> <expr:expr3> => { Box::new(Expression::UnaryOp { op: op.to_string(), expr: expr}) },
<op:T_INT_CAST> <expr:expr3> => { Box::new(Expression::CastInt(expr)) },
<op:T_DOUBLE_CAST> <expr:expr3> => { Box::new(Expression::CastDouble(expr)) },
<op:T_STRING_CAST> <expr:expr3> => { Box::new(Expression::CastString(expr)) },
<op:T_ARRAY_CAST> <expr:expr3> => { Box::new(Expression::CastArray(expr)) },
<op:T_OBJECT_CAST> <expr:expr3> => { Box::new(Expression::CastObject(expr)) },
<op:T_BOOL_CAST> <expr:expr3> => { Box::new(Expression::CastBool(expr)) },
<op:T_UNSET_CAST> <expr:expr3> => { Box::new(Expression::CastUnset(expr)) },
<a:"("> <expr:expr> <b:")"> => { Box::new(Expression::Parentness(expr)) },
<v1:variable> => { Box::new(Expression::Variable(v1)) }
};
class_name_reference : Box<ClassNameReference> = {
// todo ...
name => { Box::new(ClassNameReference::Identifier(<>)) }
};
name : String = {
// todo ...
T_STATIC => <>
};
new_expr : Box<Expression> = {
// todo
<a:T_NEW> <class_name_reference:class_name_reference> => { Box::new(Expression::New(class_name_reference)) }
// T_NEW class_name_reference ctor_arguments
//<a:T_NEW> anonymous_class
};
pub exprsadfasdf : Box<Expression> = {
// !!!! expr_without_variable
// <"list"> <"("> assignment_list <")"> = expr,
// | '+' expr %prec T_INC { $$ = zend_ast_create(ZEND_AST_UNARY_PLUS, $2); }
// | '-' expr %prec T_INC { $$ = zend_ast_create(ZEND_AST_UNARY_MINUS, $2); }
// | expr '?' expr ':' expr
// | expr '?' ':' expr
// | expr T_COALESCE expr
// | internal_functions_in_yacc { $$ = $1; }
// | T_EXIT exit_expr { $$ = zend_ast_create(ZEND_AST_EXIT, $2); }
// | '@' expr { $$ = zend_ast_create(ZEND_AST_SILENCE, $2); }
// | scalar { $$ = $1; }
// | '`' backticks_expr '`' { $$ = zend_ast_create(ZEND_AST_SHELL_EXEC, $2); }
// | T_PRINT expr { $$ = zend_ast_create(ZEND_AST_PRINT, $2); }
// | T_YIELD { $$ = zend_ast_create(ZEND_AST_YIELD, NULL, NULL); }
// | T_YIELD expr { $$ = zend_ast_create(ZEND_AST_YIELD, $2, NULL); }
// | T_YIELD expr T_DOUBLE_ARROW expr { $$ = zend_ast_create(ZEND_AST_YIELD, $4, $2); }
// | T_YIELD_FROM expr { $$ = zend_ast_create(ZEND_AST_YIELD_FROM, $2); }
// | function returns_ref '(' parameter_list ')' lexical_vars return_type
// | T_STATIC function returns_ref '(' parameter_list ')' lexical_vars
};