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