svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.library / org.gvsig.expressionevaluator / org.gvsig.expressionevaluator.lib / org.gvsig.expressionevaluator.lib.impl / src / main / java / org / gvsig / expressionevaluator / impl / DefaultCompiler.java @ 46010
History | View | Annotate | Download (26.9 KB)
1 | 43512 | jjdelcerro | package org.gvsig.expressionevaluator.impl; |
---|---|---|---|
2 | |||
3 | 44139 | jjdelcerro | import java.util.HashMap; |
4 | import java.util.Map; |
||
5 | 44750 | jjdelcerro | import java.util.Stack; |
6 | 44139 | jjdelcerro | import org.apache.commons.lang3.StringUtils; |
7 | 43512 | jjdelcerro | import org.gvsig.expressionevaluator.Compiler; |
8 | import org.gvsig.expressionevaluator.LexicalAnalyzer; |
||
9 | import org.gvsig.expressionevaluator.LexicalAnalyzer.Token; |
||
10 | import org.gvsig.expressionevaluator.Code; |
||
11 | 45025 | jjdelcerro | import org.gvsig.expressionevaluator.Code.Callable; |
12 | 43512 | jjdelcerro | import org.gvsig.expressionevaluator.CodeBuilder; |
13 | 44139 | jjdelcerro | import org.gvsig.expressionevaluator.Codes; |
14 | 45025 | jjdelcerro | import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_DICT; |
15 | 44644 | jjdelcerro | import org.gvsig.expressionevaluator.ExpressionEvaluatorManager; |
16 | 43983 | jjdelcerro | import org.gvsig.expressionevaluator.ExpressionSyntaxException; |
17 | 44139 | jjdelcerro | import org.gvsig.expressionevaluator.GrammarSet; |
18 | import org.gvsig.expressionevaluator.Statement; |
||
19 | import org.gvsig.expressionevaluator.Statement.StatementContext; |
||
20 | import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCodes; |
||
21 | 44211 | jjdelcerro | import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseConstant; |
22 | import org.gvsig.expressionevaluator.impl.function.operator.NegOperator; |
||
23 | 44379 | jjdelcerro | import org.gvsig.expressionevaluator.impl.function.programming.CodeBlockFunction; |
24 | 44738 | jjdelcerro | import org.gvsig.expressionevaluator.spi.AbstractLexicalAnalyzer; |
25 | import org.slf4j.Logger; |
||
26 | import org.slf4j.LoggerFactory; |
||
27 | 43512 | jjdelcerro | |
28 | public class DefaultCompiler implements Compiler { |
||
29 | |||
30 | 44738 | jjdelcerro | protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultCompiler.class); |
31 | |||
32 | 44139 | jjdelcerro | class DefaultStatementContext implements StatementContext { |
33 | 44750 | jjdelcerro | |
34 | private class State { |
||
35 | public String codeClassifier; |
||
36 | public Map<String,Code> codes; |
||
37 | } |
||
38 | |||
39 | private State state;
|
||
40 | private final Stack<State> states; |
||
41 | 44139 | jjdelcerro | |
42 | 44750 | jjdelcerro | public DefaultStatementContext() {
|
43 | this.state = new State(); |
||
44 | this.states = new Stack<>(); |
||
45 | } |
||
46 | |||
47 | @Override
|
||
48 | public void save_state() { |
||
49 | 45153 | jjdelcerro | this.trace("save_state"); |
50 | 44750 | jjdelcerro | ((AbstractLexicalAnalyzer)lexer).save_state(); |
51 | this.states.push(state);
|
||
52 | } |
||
53 | 44139 | jjdelcerro | |
54 | @Override
|
||
55 | 44750 | jjdelcerro | public void restore_state() { |
56 | ((AbstractLexicalAnalyzer)lexer).restore_state(); |
||
57 | state = this.states.pop();
|
||
58 | 45153 | jjdelcerro | this.trace("restore_state"); |
59 | 44750 | jjdelcerro | } |
60 | |||
61 | @Override
|
||
62 | public void drop_state() { |
||
63 | ((AbstractLexicalAnalyzer)lexer).drop_state(); |
||
64 | this.states.pop();
|
||
65 | 45153 | jjdelcerro | this.trace("drop_state"); |
66 | 44750 | jjdelcerro | } |
67 | |||
68 | @Override
|
||
69 | 44139 | jjdelcerro | public Compiler getCompiler() { |
70 | return DefaultCompiler.this;
|
||
71 | } |
||
72 | |||
73 | @Override
|
||
74 | public LexicalAnalyzer getLexicalAnalyzer() {
|
||
75 | return lexer;
|
||
76 | } |
||
77 | |||
78 | @Override
|
||
79 | public void setCode(String id, Code code) { |
||
80 | 44750 | jjdelcerro | if( this.state.codes == null ) { |
81 | this.state.codes = new HashMap<>(); |
||
82 | 44139 | jjdelcerro | } |
83 | 44750 | jjdelcerro | if( !StringUtils.isBlank(this.state.codeClassifier) ) { |
84 | 44139 | jjdelcerro | if( id.contains("#") ) { |
85 | 44750 | jjdelcerro | id = StringUtils.replace(id,"#",this.state.codeClassifier,1); |
86 | 44139 | jjdelcerro | } |
87 | } |
||
88 | 44750 | jjdelcerro | this.state.codes.put(id.toUpperCase(), code);
|
89 | 44139 | jjdelcerro | } |
90 | |||
91 | 44379 | jjdelcerro | @Override
|
92 | 44139 | jjdelcerro | public Code getCode(String id) { |
93 | 45934 | jjdelcerro | if( this.state==null || this.state.codes==null ) { |
94 | return null; |
||
95 | } |
||
96 | if( StringUtils.isBlank(id) ) {
|
||
97 | return null; |
||
98 | } |
||
99 | 44750 | jjdelcerro | return this.state.codes.get(id.toUpperCase()); |
100 | 44139 | jjdelcerro | } |
101 | |||
102 | @Override
|
||
103 | public void setCodeClassifier(String classifier) { |
||
104 | 44750 | jjdelcerro | this.state.codeClassifier = classifier;
|
105 | 44139 | jjdelcerro | } |
106 | |||
107 | @Override
|
||
108 | public String getCodeClassifier() { |
||
109 | 44750 | jjdelcerro | return this.state.codeClassifier; |
110 | 44139 | jjdelcerro | } |
111 | |||
112 | @Override
|
||
113 | public CodeBuilder getCodeBuilder() {
|
||
114 | return codeBuilder;
|
||
115 | } |
||
116 | |||
117 | @Override
|
||
118 | public Token look_token() {
|
||
119 | return lexer.look();
|
||
120 | } |
||
121 | |||
122 | @Override
|
||
123 | public Token next_token() {
|
||
124 | return lexer.next();
|
||
125 | } |
||
126 | |||
127 | @Override
|
||
128 | 45153 | jjdelcerro | public Code parse_expression(boolean allow_assignement) { |
129 | return DefaultCompiler.this.parse_expression(allow_assignement);
|
||
130 | 44139 | jjdelcerro | } |
131 | |||
132 | @Override
|
||
133 | public Codes parse_expressions(String separator) { |
||
134 | return DefaultCompiler.this.parse_expressions(separator);
|
||
135 | } |
||
136 | |||
137 | 44738 | jjdelcerro | @Override
|
138 | 44384 | jjdelcerro | public boolean isReservedWord(String s) { |
139 | return grammars.isReservedWord(s);
|
||
140 | } |
||
141 | 44738 | jjdelcerro | |
142 | @Override
|
||
143 | public void trace(String msg) { |
||
144 | 45153 | jjdelcerro | // LexicalAnalyzer lex = this.getLexicalAnalyzer();
|
145 | // String s = StringUtils.left(lex.getSource(), lex.getPosition()) + "[*]" + StringUtils.mid(lex.getSource(), lex.getPosition(), 200);
|
||
146 | // if( s.length()>200 ) {
|
||
147 | // s = "..."+StringUtils.mid(s, lex.getPosition()-100, 200)+"...";
|
||
148 | // }
|
||
149 | // System.out.println(msg+". "+s);
|
||
150 | 44738 | jjdelcerro | } |
151 | 44139 | jjdelcerro | } |
152 | |||
153 | 43939 | jjdelcerro | private boolean objectAccessSupported; |
154 | 43512 | jjdelcerro | private LexicalAnalyzer lexer;
|
155 | private CodeBuilder codeBuilder;
|
||
156 | 44139 | jjdelcerro | private final GrammarSet grammars; |
157 | 44644 | jjdelcerro | protected ExpressionEvaluatorManager manager;
|
158 | 43532 | jjdelcerro | //
|
159 | // https://www.postgresql.org/docs/9.1/static/functions.html
|
||
160 | //
|
||
161 | 43512 | jjdelcerro | |
162 | 44644 | jjdelcerro | public DefaultCompiler(ExpressionEvaluatorManager manager) {
|
163 | this.manager = manager;
|
||
164 | 44139 | jjdelcerro | this.grammars = new DefaultGrammarSet(); |
165 | 43512 | jjdelcerro | this.lexer = new SQLLexicalAnalyzer(); |
166 | 44644 | jjdelcerro | this.codeBuilder = new DefaultCodeBuilder(manager); |
167 | 43939 | jjdelcerro | this.objectAccessSupported = true; |
168 | 43512 | jjdelcerro | } |
169 | |||
170 | @Override
|
||
171 | 43809 | jjdelcerro | public Compiler clone() throws CloneNotSupportedException { |
172 | DefaultCompiler other = (DefaultCompiler) super.clone();
|
||
173 | other.lexer = lexer.clone(); |
||
174 | other.codeBuilder = codeBuilder.clone(); |
||
175 | |||
176 | return other;
|
||
177 | } |
||
178 | |||
179 | @Override
|
||
180 | 43512 | jjdelcerro | public void setLexicalAnalyzer(LexicalAnalyzer lexer) { |
181 | this.lexer = lexer;
|
||
182 | } |
||
183 | 43983 | jjdelcerro | |
184 | @Override
|
||
185 | public LexicalAnalyzer getLexicalAnalyzer() {
|
||
186 | return this.lexer; |
||
187 | } |
||
188 | 43512 | jjdelcerro | |
189 | @Override
|
||
190 | public void setCodeBuilder(CodeBuilder codeBuilder) { |
||
191 | this.codeBuilder = codeBuilder;
|
||
192 | } |
||
193 | 43809 | jjdelcerro | |
194 | 43512 | jjdelcerro | @Override
|
195 | 43809 | jjdelcerro | public CodeBuilder getCodeBuilder() {
|
196 | return this.codeBuilder; |
||
197 | } |
||
198 | |||
199 | @Override
|
||
200 | 43939 | jjdelcerro | public boolean isObjectAccessSupported() { |
201 | return this.objectAccessSupported; |
||
202 | } |
||
203 | |||
204 | @Override
|
||
205 | public void setObjectAccessSupported(boolean objectAccessSupported) { |
||
206 | this.objectAccessSupported = objectAccessSupported;
|
||
207 | } |
||
208 | 44139 | jjdelcerro | |
209 | 43939 | jjdelcerro | @Override
|
210 | 44139 | jjdelcerro | public GrammarSet getGrammars() {
|
211 | return this.grammars; |
||
212 | } |
||
213 | |||
214 | @Override
|
||
215 | 43512 | jjdelcerro | public Code compileExpression(String expression) { |
216 | 45950 | jjdelcerro | if( StringUtils.isBlank(expression) ) {
|
217 | return this.getCodeBuilder().constant(null); |
||
218 | } |
||
219 | |||
220 | 43983 | jjdelcerro | this.lexer.setSource(expression.trim());
|
221 | 44139 | jjdelcerro | Code code = parse_expression(); |
222 | 43983 | jjdelcerro | if( !this.lexer.isEOF() ) { |
223 | throw new ExpressionSyntaxException(lexer); |
||
224 | } |
||
225 | return code;
|
||
226 | 43512 | jjdelcerro | } |
227 | 45153 | jjdelcerro | |
228 | public Code parse_expression() {
|
||
229 | return this.parse_expression(true); |
||
230 | } |
||
231 | 43512 | jjdelcerro | |
232 | 45153 | jjdelcerro | public Code parse_expression(boolean allow_assignement) { |
233 | 43983 | jjdelcerro | Code code = parse_relational(); |
234 | 45153 | jjdelcerro | if( code != null && allow_assignement) { |
235 | Token token = lexer.look(); |
||
236 | if( token.is("AS") ) { |
||
237 | lexer.next(); |
||
238 | token = lexer.look(); |
||
239 | if( token.getType() != Token.IDENTIFIER ) {
|
||
240 | throw new ExpressionSyntaxException( |
||
241 | I18N.An_identifier_was_expected_and_XliteralX_was_found(token.getLiteral()), |
||
242 | lexer |
||
243 | ); |
||
244 | } |
||
245 | token = lexer.next(); |
||
246 | code = codeBuilder.let(token.getLiteral(),code); |
||
247 | } |
||
248 | } |
||
249 | 43983 | jjdelcerro | return code;
|
250 | 43512 | jjdelcerro | } |
251 | |||
252 | 44139 | jjdelcerro | public Code parse_relational() {
|
253 | 43512 | jjdelcerro | Code op1 = parse_not(); |
254 | Code op2; |
||
255 | while( true ) { |
||
256 | Token token = lexer.look(); |
||
257 | switch( token.getType() ) {
|
||
258 | case Token.OP_OR:
|
||
259 | lexer.next(); |
||
260 | op2 = parse_not(); |
||
261 | 43983 | jjdelcerro | if( op2==null ) { |
262 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_OR_operator(),lexer); |
263 | 43983 | jjdelcerro | } |
264 | 43512 | jjdelcerro | op1 = codeBuilder.or(op1, op2); |
265 | break;
|
||
266 | case Token.OP_AND:
|
||
267 | lexer.next(); |
||
268 | op2 = parse_not(); |
||
269 | 43983 | jjdelcerro | if( op2==null ) { |
270 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_AND_operator(),lexer); |
271 | 43983 | jjdelcerro | } |
272 | 43512 | jjdelcerro | op1 = codeBuilder.and(op1, op2); |
273 | break;
|
||
274 | default:
|
||
275 | return op1;
|
||
276 | } |
||
277 | } |
||
278 | } |
||
279 | |||
280 | 44139 | jjdelcerro | public Code parse_not() {
|
281 | 43512 | jjdelcerro | Code op1; |
282 | Token token = lexer.look(); |
||
283 | if( token.getType() == Token.OP_NOT ) {
|
||
284 | lexer.next(); |
||
285 | op1 = parse_conditional(); |
||
286 | op1 = codeBuilder.not(op1); |
||
287 | } else {
|
||
288 | op1 = parse_conditional(); |
||
289 | } |
||
290 | return op1;
|
||
291 | } |
||
292 | |||
293 | 44139 | jjdelcerro | public Code parse_conditional() {
|
294 | 43512 | jjdelcerro | Code op1 = parse_sum(); |
295 | Code op2; |
||
296 | while( true ) { |
||
297 | Token token = lexer.look(); |
||
298 | switch( token.getType() ) {
|
||
299 | case Token.OP_LT:
|
||
300 | lexer.next(); |
||
301 | op2 = parse_sum(); |
||
302 | 43983 | jjdelcerro | if( op2==null ) { |
303 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LT_operator(),lexer); |
304 | 43983 | jjdelcerro | } |
305 | 43512 | jjdelcerro | op1 = codeBuilder.lt(op1, op2); |
306 | break;
|
||
307 | case Token.OP_GT:
|
||
308 | lexer.next(); |
||
309 | op2 = parse_sum(); |
||
310 | 43983 | jjdelcerro | if( op2==null ) { |
311 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GT_operator(),lexer); |
312 | 43983 | jjdelcerro | } |
313 | 43512 | jjdelcerro | op1 = codeBuilder.gt(op1, op2); |
314 | break;
|
||
315 | case Token.OP_LE:
|
||
316 | lexer.next(); |
||
317 | op2 = parse_sum(); |
||
318 | 43983 | jjdelcerro | if( op2==null ) { |
319 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LE_operator(),lexer); |
320 | 43983 | jjdelcerro | } |
321 | 43512 | jjdelcerro | op1 = codeBuilder.le(op1, op2); |
322 | break;
|
||
323 | case Token.OP_GE:
|
||
324 | lexer.next(); |
||
325 | op2 = parse_sum(); |
||
326 | 43983 | jjdelcerro | if( op2==null ) { |
327 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GE_operator(),lexer); |
328 | 43983 | jjdelcerro | } |
329 | 43512 | jjdelcerro | op1 = codeBuilder.ge(op1, op2); |
330 | break;
|
||
331 | case Token.OP_EQ:
|
||
332 | lexer.next(); |
||
333 | op2 = parse_sum(); |
||
334 | 43983 | jjdelcerro | if( op2==null ) { |
335 | 44139 | jjdelcerro | token = lexer.look(); |
336 | String tip = null; |
||
337 | switch(token.getType()) {
|
||
338 | case Token.OP_GT:
|
||
339 | tip = I18N.The_operator_greater_than_or_equal_is_ge(); |
||
340 | break;
|
||
341 | case Token.OP_LT:
|
||
342 | tip = I18N.The_operator_less_than_or_equal_is_ge(); |
||
343 | break;
|
||
344 | } |
||
345 | throw new ExpressionSyntaxException( |
||
346 | I18N.Cant_recognize_the_second_operand_of_EQ_operator(), |
||
347 | lexer, |
||
348 | tip |
||
349 | ); |
||
350 | 43983 | jjdelcerro | } |
351 | 43512 | jjdelcerro | op1 = codeBuilder.eq(op1, op2); |
352 | break;
|
||
353 | 43521 | jjdelcerro | case Token.OP_NE:
|
354 | 43512 | jjdelcerro | lexer.next(); |
355 | 43521 | jjdelcerro | op2 = parse_sum(); |
356 | 43983 | jjdelcerro | if( op2==null ) { |
357 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_NEQ_operator(),lexer); |
358 | 43983 | jjdelcerro | } |
359 | 43521 | jjdelcerro | op1 = codeBuilder.ne(op1, op2); |
360 | break;
|
||
361 | case Token.PRED_IS: {
|
||
362 | lexer.next(); |
||
363 | Token next = lexer.look(); |
||
364 | 44361 | jjdelcerro | switch(next.getType()) {
|
365 | case Token.NOTNULL:
|
||
366 | lexer.next(); |
||
367 | op1 = codeBuilder.is(op1, codeBuilder.constant(null));
|
||
368 | op1 = codeBuilder.not(op1); |
||
369 | break;
|
||
370 | case Token.OP_NOT:
|
||
371 | lexer.next(); |
||
372 | next = lexer.look(); |
||
373 | if( next.getType() == Token.NULL ) {
|
||
374 | lexer.next(); |
||
375 | op1 = codeBuilder.is(op1, codeBuilder.constant(null));
|
||
376 | } else {
|
||
377 | op2 = parse_sum(); |
||
378 | if( op2==null ) { |
||
379 | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_IS_operator(),lexer); |
||
380 | } |
||
381 | op1 = codeBuilder.is(op1, op2); |
||
382 | } |
||
383 | op1 = codeBuilder.not(op1); |
||
384 | break;
|
||
385 | case Token.NULL:
|
||
386 | lexer.next(); |
||
387 | op1 = codeBuilder.is(op1, codeBuilder.constant(null));
|
||
388 | break;
|
||
389 | default:
|
||
390 | op2 = parse_sum(); |
||
391 | if( op2==null ) { |
||
392 | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_IS_operator(),lexer); |
||
393 | } |
||
394 | op1 = codeBuilder.is(op1, op2); |
||
395 | 43521 | jjdelcerro | } |
396 | 43512 | jjdelcerro | } |
397 | 43521 | jjdelcerro | break;
|
398 | 43512 | jjdelcerro | case Token.ISNULL:
|
399 | lexer.next(); |
||
400 | op1 = codeBuilder.is(op1, codeBuilder.constant(null));
|
||
401 | break;
|
||
402 | 43532 | jjdelcerro | case Token.OP_REGEXP:
|
403 | lexer.next(); |
||
404 | op2 = parse_sum(); |
||
405 | 43983 | jjdelcerro | if( op2==null ) { |
406 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_REGEXP_operator(),lexer); |
407 | 43983 | jjdelcerro | } |
408 | 43532 | jjdelcerro | op1 = codeBuilder.regexp(op1, op2); |
409 | break;
|
||
410 | 43512 | jjdelcerro | case Token.PRED_LIKE:
|
411 | lexer.next(); |
||
412 | op2 = parse_sum(); |
||
413 | 43983 | jjdelcerro | if( op2==null ) { |
414 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LIKE_operator(),lexer); |
415 | 43983 | jjdelcerro | } |
416 | 43512 | jjdelcerro | op1 = codeBuilder.like(op1, op2); |
417 | break;
|
||
418 | case Token.PRED_ILIKE:
|
||
419 | lexer.next(); |
||
420 | op2 = parse_sum(); |
||
421 | 43983 | jjdelcerro | if( op2==null ) { |
422 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_ILIKE_operator(),lexer); |
423 | 43983 | jjdelcerro | } |
424 | 43512 | jjdelcerro | op1 = codeBuilder.ilike(op1, op2); |
425 | break;
|
||
426 | default:
|
||
427 | return op1;
|
||
428 | } |
||
429 | } |
||
430 | } |
||
431 | |||
432 | 44139 | jjdelcerro | public Code parse_sum() {
|
433 | 43512 | jjdelcerro | Code op1 = parse_factor(); |
434 | Code op2; |
||
435 | while( true ) { |
||
436 | Token token = lexer.look(); |
||
437 | switch( token.getType() ) {
|
||
438 | 44139 | jjdelcerro | case Token.OP_CONCAT:
|
439 | lexer.next(); |
||
440 | op2 = parse_factor(); |
||
441 | op1 = codeBuilder.concat(op1, op2); |
||
442 | break;
|
||
443 | 43512 | jjdelcerro | case Token.OP_ADD:
|
444 | lexer.next(); |
||
445 | op2 = parse_factor(); |
||
446 | op1 = codeBuilder.add(op1, op2); |
||
447 | break;
|
||
448 | case Token.OP_SUBST:
|
||
449 | lexer.next(); |
||
450 | op2 = parse_factor(); |
||
451 | op1 = codeBuilder.subst(op1, op2); |
||
452 | break;
|
||
453 | default:
|
||
454 | return op1;
|
||
455 | } |
||
456 | } |
||
457 | } |
||
458 | |||
459 | 44139 | jjdelcerro | public Code parse_factor() {
|
460 | 43939 | jjdelcerro | Code op1 = parse_getattr(); |
461 | 43512 | jjdelcerro | Code op2; |
462 | while( true ) { |
||
463 | Token token = lexer.look(); |
||
464 | switch( token.getType() ) {
|
||
465 | case Token.OP_MULT:
|
||
466 | lexer.next(); |
||
467 | 43939 | jjdelcerro | op2 = parse_getattr(); |
468 | 43983 | jjdelcerro | if( op2==null ) { |
469 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MULT_operator(),lexer); |
470 | 43983 | jjdelcerro | } |
471 | 43512 | jjdelcerro | op1 = codeBuilder.mult(op1, op2); |
472 | break;
|
||
473 | case Token.OP_DIV:
|
||
474 | lexer.next(); |
||
475 | 43939 | jjdelcerro | op2 = parse_getattr(); |
476 | 43983 | jjdelcerro | if( op2==null ) { |
477 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_DIV_operator(),lexer); |
478 | 43983 | jjdelcerro | } |
479 | 43512 | jjdelcerro | op1 = codeBuilder.div(op1, op2); |
480 | break;
|
||
481 | case Token.OP_MOD:
|
||
482 | lexer.next(); |
||
483 | 43939 | jjdelcerro | op2 = parse_getattr(); |
484 | 43983 | jjdelcerro | if( op2==null ) { |
485 | 44098 | jjdelcerro | throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MOD_operator(),lexer); |
486 | 43983 | jjdelcerro | } |
487 | 43512 | jjdelcerro | op1 = codeBuilder.mod(op1, op2); |
488 | break;
|
||
489 | 44139 | jjdelcerro | case Token.OPEN_BRACKET:
|
490 | lexer.next(); |
||
491 | Code codeIndex = parse_expression(); |
||
492 | if( codeIndex == null ) { |
||
493 | throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer); |
||
494 | } |
||
495 | token = lexer.look(); |
||
496 | if( token.getType()!=Token.CLOSED_BRACKET) {
|
||
497 | throw new ExpressionSyntaxException(I18N.A_XTokenX_was_expected_and_XliteralX_was_found("]", token.getLiteral()),lexer); |
||
498 | } |
||
499 | lexer.next(); |
||
500 | Code code = codeBuilder.getitem(op1, codeIndex); |
||
501 | return code;
|
||
502 | 43512 | jjdelcerro | default:
|
503 | return op1;
|
||
504 | } |
||
505 | } |
||
506 | } |
||
507 | |||
508 | 44139 | jjdelcerro | public Code parse_getattr() {
|
509 | 43939 | jjdelcerro | Code op1 = parse_termino(); |
510 | if( !isObjectAccessSupported() ) {
|
||
511 | return op1;
|
||
512 | } |
||
513 | while( true ) { |
||
514 | Token next = lexer.look(); |
||
515 | switch( next.getType() ) {
|
||
516 | case Token.OP_GETATTR:
|
||
517 | lexer.next(); |
||
518 | next = lexer.look(); |
||
519 | if( next.getType()!=Token.IDENTIFIER ) {
|
||
520 | 43983 | jjdelcerro | throw new ExpressionSyntaxException( |
521 | 44098 | jjdelcerro | I18N.An_attribute_identifier_was_expected_and_XliteralX_was_found(next.getLiteral()), |
522 | lexer |
||
523 | 43983 | jjdelcerro | ); |
524 | 43939 | jjdelcerro | } |
525 | String id = (String) next.getLiteral(); |
||
526 | lexer.next(); |
||
527 | next = lexer.look(); |
||
528 | if( next.getType() == Token.PARENTHESIS_OPEN ) {
|
||
529 | lexer.next(); |
||
530 | 44139 | jjdelcerro | Codes args = parse_expressions(",");
|
531 | 43939 | jjdelcerro | next = lexer.next(); |
532 | if( next.getType() != Token.PARENTHESIS_CLOSE ) {
|
||
533 | 43983 | jjdelcerro | throw new ExpressionSyntaxException( |
534 | 44098 | jjdelcerro | I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()), |
535 | lexer |
||
536 | 43983 | jjdelcerro | ); |
537 | 43939 | jjdelcerro | } |
538 | 44379 | jjdelcerro | op1 = codeBuilder.method(op1, id, args); |
539 | 43939 | jjdelcerro | } else {
|
540 | 44379 | jjdelcerro | op1 = codeBuilder.getattr(op1, id); |
541 | 43939 | jjdelcerro | } |
542 | 44379 | jjdelcerro | break;
|
543 | 43939 | jjdelcerro | default:
|
544 | return op1;
|
||
545 | } |
||
546 | } |
||
547 | } |
||
548 | |||
549 | 45132 | jjdelcerro | @SuppressWarnings("UnusedAssignment") |
550 | 44139 | jjdelcerro | public Code parse_termino() {
|
551 | 43512 | jjdelcerro | |
552 | Token token = lexer.look(); |
||
553 | switch( token.getType() ) {
|
||
554 | case Token.PARENTHESIS_OPEN: {
|
||
555 | 43521 | jjdelcerro | lexer.next(); |
556 | 44139 | jjdelcerro | Code value = parse_expression(); |
557 | 43521 | jjdelcerro | Token next = lexer.next(); |
558 | 44098 | jjdelcerro | switch(next.getType()) {
|
559 | case Token.PARENTHESIS_CLOSE:
|
||
560 | break;
|
||
561 | case Token.EOF:
|
||
562 | throw new ExpressionSyntaxException( |
||
563 | I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(), |
||
564 | lexer |
||
565 | ); |
||
566 | default:
|
||
567 | throw new ExpressionSyntaxException( |
||
568 | I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()), |
||
569 | lexer |
||
570 | ); |
||
571 | 43521 | jjdelcerro | } |
572 | return value;
|
||
573 | 43512 | jjdelcerro | } |
574 | case Token.IDENTIFIER: {
|
||
575 | 44139 | jjdelcerro | Code code = parse_grammars(); |
576 | if( code!=null ) { |
||
577 | return code;
|
||
578 | } |
||
579 | if( this.grammars.isReservedWord(token.getLiteral()) ) { |
||
580 | return null; |
||
581 | } |
||
582 | 43512 | jjdelcerro | lexer.next(); |
583 | 43521 | jjdelcerro | String id = (String) token.getLiteral(); |
584 | Token next = lexer.look(); |
||
585 | if( next.getType() == Token.PARENTHESIS_OPEN ) {
|
||
586 | 44750 | jjdelcerro | next = lexer.next(); |
587 | 44738 | jjdelcerro | Codes args = parse_arguments(); |
588 | 43521 | jjdelcerro | next = lexer.next(); |
589 | 44098 | jjdelcerro | switch(next.getType()) {
|
590 | case Token.PARENTHESIS_CLOSE:
|
||
591 | break;
|
||
592 | case Token.EOF:
|
||
593 | throw new ExpressionSyntaxException( |
||
594 | I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(), |
||
595 | lexer |
||
596 | ); |
||
597 | default:
|
||
598 | throw new ExpressionSyntaxException( |
||
599 | I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()), |
||
600 | lexer |
||
601 | ); |
||
602 | 43521 | jjdelcerro | } |
603 | 45025 | jjdelcerro | // Optimizacion para cuando se esta invocando a la funcion dict
|
604 | if( StringUtils.equalsIgnoreCase(id, FUNCTION_DICT) && args!=null && args.size()==1 ) { |
||
605 | code = args.get(0);
|
||
606 | if( code.code()==Code.CALLABLE &&
|
||
607 | StringUtils.equalsIgnoreCase(((Callable)code).name(),FUNCTION_DICT) ) {
|
||
608 | return code;
|
||
609 | } |
||
610 | } |
||
611 | 43521 | jjdelcerro | return codeBuilder.function(id, args);
|
612 | } else {
|
||
613 | 44379 | jjdelcerro | if( StringUtils.equalsIgnoreCase(id, "TRUE") ) { |
614 | return codeBuilder.constant(true); |
||
615 | } |
||
616 | if( StringUtils.equalsIgnoreCase(id, "FALSE") ) { |
||
617 | return codeBuilder.constant(false); |
||
618 | } |
||
619 | 43521 | jjdelcerro | return codeBuilder.identifier(id);
|
620 | 43512 | jjdelcerro | } |
621 | } |
||
622 | case Token.STRING_LITERAL:
|
||
623 | lexer.next(); |
||
624 | return codeBuilder.constant(token.getValue());
|
||
625 | case Token.INTEGER_LITERAL:
|
||
626 | lexer.next(); |
||
627 | return codeBuilder.constant(token.getValue());
|
||
628 | case Token.FLOATING_POINT_LITERAL:
|
||
629 | lexer.next(); |
||
630 | return codeBuilder.constant(token.getValue());
|
||
631 | case Token.NULL:
|
||
632 | lexer.next(); |
||
633 | return codeBuilder.constant(null); |
||
634 | case Token.TRUE:
|
||
635 | lexer.next(); |
||
636 | return codeBuilder.constant(true); |
||
637 | case Token.FALSE:
|
||
638 | lexer.next(); |
||
639 | return codeBuilder.constant(false); |
||
640 | 44098 | jjdelcerro | case Token.OP_SUBST:
|
641 | lexer.next(); |
||
642 | Code code = parse_termino(); |
||
643 | 44211 | jjdelcerro | if( code.code()==Code.CONSTANT ) {
|
644 | BaseConstant c = (BaseConstant)code; |
||
645 | if( c.value() instanceof Number ) { |
||
646 | c.value(NegOperator.negate((Number) c.value()));
|
||
647 | return code;
|
||
648 | } |
||
649 | 44212 | jjdelcerro | throw new ExpressionSyntaxException(I18N.A_numeric_constant_was_expected_after_the_unary_operator_minus(),lexer); |
650 | 44211 | jjdelcerro | } |
651 | 44098 | jjdelcerro | return codeBuilder.negate(code);
|
652 | case Token.EOF:
|
||
653 | throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer); |
||
654 | 44139 | jjdelcerro | default:
|
655 | return parse_grammars();
|
||
656 | 43512 | jjdelcerro | } |
657 | } |
||
658 | |||
659 | 44139 | jjdelcerro | public Codes parse_expressions(String sep) { |
660 | BaseCodes codes = null;
|
||
661 | 43512 | jjdelcerro | while( true ) { |
662 | 44139 | jjdelcerro | Code code = parse_expression(); |
663 | if( code!=null ) { |
||
664 | if( codes == null ) { |
||
665 | codes = (BaseCodes) codeBuilder.args(); |
||
666 | 43519 | jjdelcerro | } |
667 | 44139 | jjdelcerro | codes.add(code); |
668 | 43519 | jjdelcerro | } |
669 | 43512 | jjdelcerro | Token next = lexer.look(); |
670 | 44139 | jjdelcerro | String literal = next.getLiteral();
|
671 | if( literal == null ) { |
||
672 | return codes;
|
||
673 | } |
||
674 | literal = literal.trim(); |
||
675 | if( sep.equals(literal) ) {
|
||
676 | 43512 | jjdelcerro | lexer.next(); // Consume el ",".
|
677 | 44139 | jjdelcerro | } else {
|
678 | return codes;
|
||
679 | 43512 | jjdelcerro | } |
680 | } |
||
681 | } |
||
682 | 44139 | jjdelcerro | |
683 | 45025 | jjdelcerro | private String getKeyArgument() { |
684 | ((AbstractLexicalAnalyzer)lexer).save_state(); |
||
685 | Token next = lexer.look(); |
||
686 | if( next.getType()==Token.IDENTIFIER ) {
|
||
687 | String key = next.getLiteral();
|
||
688 | lexer.next(); |
||
689 | next = lexer.next(); |
||
690 | 45132 | jjdelcerro | if( next.is(":","=","=>") ) { |
691 | 45025 | jjdelcerro | ((AbstractLexicalAnalyzer)lexer).drop_state(); |
692 | return key;
|
||
693 | } |
||
694 | } |
||
695 | ((AbstractLexicalAnalyzer)lexer).restore_state(); |
||
696 | return null; |
||
697 | } |
||
698 | |||
699 | 44738 | jjdelcerro | public Codes parse_arguments() {
|
700 | String sep = ","; |
||
701 | BaseCodes codes = null;
|
||
702 | 45025 | jjdelcerro | Map<String,Code> kwargs = null; |
703 | 44738 | jjdelcerro | while( true ) { |
704 | 45025 | jjdelcerro | String key = getKeyArgument();
|
705 | if( key == null ) { |
||
706 | if( kwargs != null ) { |
||
707 | throw new ExpressionSyntaxException(I18N.nonkeyword_arg_after_keyword_arg(),lexer); |
||
708 | 44738 | jjdelcerro | } |
709 | 45025 | jjdelcerro | Code code = parse_expression(); |
710 | if( code!=null ) { |
||
711 | if( codes == null ) { |
||
712 | codes = (BaseCodes) codeBuilder.args(); |
||
713 | } |
||
714 | codes.add(code); |
||
715 | } |
||
716 | } else {
|
||
717 | if( kwargs == null ) { |
||
718 | kwargs = new HashMap<>(); |
||
719 | } |
||
720 | Code code = parse_expression(); |
||
721 | kwargs.put(key, code); |
||
722 | 44738 | jjdelcerro | } |
723 | Token next = lexer.look(); |
||
724 | 45025 | jjdelcerro | if( !next.is(sep) ) {
|
725 | break;
|
||
726 | 44738 | jjdelcerro | } |
727 | 45025 | jjdelcerro | lexer.next(); // Consume el ",".
|
728 | } |
||
729 | if( kwargs!=null ) { |
||
730 | if( codes == null ) { |
||
731 | codes = (BaseCodes) codeBuilder.args(); |
||
732 | 44738 | jjdelcerro | } |
733 | 45025 | jjdelcerro | Code code = codeBuilder.dict(kwargs); |
734 | codes.add(code); |
||
735 | 44738 | jjdelcerro | } |
736 | 45025 | jjdelcerro | return codes;
|
737 | 44738 | jjdelcerro | } |
738 | |||
739 | 44139 | jjdelcerro | private Code parse_grammars() {
|
740 | StatementContext context = new DefaultStatementContext();
|
||
741 | 44379 | jjdelcerro | Code code; |
742 | BaseCodes args = (BaseCodes) this.codeBuilder.args();
|
||
743 | 45153 | jjdelcerro | context.trace("compiler.parse_gramars");
|
744 | 44139 | jjdelcerro | Statement stmt = this.grammars.getApplicableStatement(context); |
745 | 44379 | jjdelcerro | while( stmt!=null ) { |
746 | code = stmt.parse(context); |
||
747 | args.add(code); |
||
748 | stmt = this.grammars.getApplicableStatement(context);
|
||
749 | 44139 | jjdelcerro | } |
750 | 44379 | jjdelcerro | switch(args.size()) {
|
751 | case 0 : |
||
752 | code = null;
|
||
753 | break;
|
||
754 | case 1 : |
||
755 | code = args.get(0);
|
||
756 | break;
|
||
757 | default:
|
||
758 | code = this.codeBuilder.function(CodeBlockFunction.NAME, args);
|
||
759 | break;
|
||
760 | } |
||
761 | return code;
|
||
762 | 44139 | jjdelcerro | } |
763 | 43512 | jjdelcerro | } |