Revision 44139 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
DefaultCompiler.java | ||
---|---|---|
1 | 1 |
package org.gvsig.expressionevaluator.impl; |
2 | 2 |
|
3 |
import java.util.HashMap; |
|
4 |
import java.util.Map; |
|
5 |
import org.apache.commons.lang3.StringUtils; |
|
3 | 6 |
import org.gvsig.expressionevaluator.Compiler; |
4 |
import org.gvsig.expressionevaluator.Code.Caller.Arguments; |
|
5 | 7 |
import org.gvsig.expressionevaluator.LexicalAnalyzer; |
6 | 8 |
import org.gvsig.expressionevaluator.LexicalAnalyzer.Token; |
7 | 9 |
import org.gvsig.expressionevaluator.Code; |
8 | 10 |
import org.gvsig.expressionevaluator.CodeBuilder; |
11 |
import org.gvsig.expressionevaluator.Codes; |
|
9 | 12 |
import org.gvsig.expressionevaluator.ExpressionSyntaxException; |
13 |
import org.gvsig.expressionevaluator.GrammarSet; |
|
14 |
import org.gvsig.expressionevaluator.Statement; |
|
15 |
import org.gvsig.expressionevaluator.Statement.StatementContext; |
|
16 |
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCodes; |
|
10 | 17 |
|
11 | 18 |
public class DefaultCompiler implements Compiler { |
12 | 19 |
|
20 |
class DefaultStatementContext implements StatementContext { |
|
21 |
|
|
22 |
private String codeClassifier; |
|
23 |
private Map<String,Code> codes; |
|
24 |
|
|
25 |
@Override |
|
26 |
public Compiler getCompiler() { |
|
27 |
return DefaultCompiler.this; |
|
28 |
} |
|
29 |
|
|
30 |
@Override |
|
31 |
public LexicalAnalyzer getLexicalAnalyzer() { |
|
32 |
return lexer; |
|
33 |
} |
|
34 |
|
|
35 |
@Override |
|
36 |
public void setCode(String id, Code code) { |
|
37 |
if( this.codes == null ) { |
|
38 |
this.codes = new HashMap<>(); |
|
39 |
} |
|
40 |
if( !StringUtils.isBlank(this.codeClassifier) ) { |
|
41 |
if( id.contains("#") ) { |
|
42 |
id = StringUtils.replace(id,"#",this.codeClassifier,1); |
|
43 |
} |
|
44 |
} |
|
45 |
this.codes.put(id, code); |
|
46 |
} |
|
47 |
|
|
48 |
public Code getCode(String id) { |
|
49 |
return this.codes.get(id); |
|
50 |
} |
|
51 |
|
|
52 |
@Override |
|
53 |
public void setCodeClassifier(String classifier) { |
|
54 |
this.codeClassifier = classifier; |
|
55 |
} |
|
56 |
|
|
57 |
@Override |
|
58 |
public String getCodeClassifier() { |
|
59 |
return this.codeClassifier; |
|
60 |
} |
|
61 |
|
|
62 |
@Override |
|
63 |
public CodeBuilder getCodeBuilder() { |
|
64 |
return codeBuilder; |
|
65 |
} |
|
66 |
|
|
67 |
@Override |
|
68 |
public Token look_token() { |
|
69 |
return lexer.look(); |
|
70 |
} |
|
71 |
|
|
72 |
@Override |
|
73 |
public Token next_token() { |
|
74 |
return lexer.next(); |
|
75 |
} |
|
76 |
|
|
77 |
@Override |
|
78 |
public Code parse_expression() { |
|
79 |
return DefaultCompiler.this.parse_expression(); |
|
80 |
} |
|
81 |
|
|
82 |
@Override |
|
83 |
public Codes parse_expressions(String separator) { |
|
84 |
return DefaultCompiler.this.parse_expressions(separator); |
|
85 |
} |
|
86 |
|
|
87 |
} |
|
88 |
|
|
13 | 89 |
private boolean objectAccessSupported; |
14 | 90 |
private LexicalAnalyzer lexer; |
15 | 91 |
private CodeBuilder codeBuilder; |
92 |
private final GrammarSet grammars; |
|
16 | 93 |
// |
17 | 94 |
// https://www.postgresql.org/docs/9.1/static/functions.html |
18 | 95 |
// |
19 | 96 |
|
20 | 97 |
public DefaultCompiler() { |
98 |
this.grammars = new DefaultGrammarSet(); |
|
21 | 99 |
this.lexer = new SQLLexicalAnalyzer(); |
22 | 100 |
this.codeBuilder = new DefaultCodeBuilder(); |
23 | 101 |
this.objectAccessSupported = true; |
... | ... | |
61 | 139 |
public void setObjectAccessSupported(boolean objectAccessSupported) { |
62 | 140 |
this.objectAccessSupported = objectAccessSupported; |
63 | 141 |
} |
64 |
|
|
142 |
|
|
65 | 143 |
@Override |
144 |
public GrammarSet getGrammars() { |
|
145 |
return this.grammars; |
|
146 |
} |
|
147 |
|
|
148 |
@Override |
|
66 | 149 |
public Code compileExpression(String expression) { |
67 | 150 |
this.lexer.setSource(expression.trim()); |
68 |
Code code = parseExpression();
|
|
151 |
Code code = parse_expression();
|
|
69 | 152 |
if( !this.lexer.isEOF() ) { |
70 | 153 |
throw new ExpressionSyntaxException(lexer); |
71 | 154 |
} |
72 | 155 |
return code; |
73 | 156 |
} |
74 | 157 |
|
75 |
private Code parseExpression() {
|
|
158 |
public Code parse_expression() {
|
|
76 | 159 |
Code code = parse_relational(); |
77 | 160 |
return code; |
78 | 161 |
} |
79 | 162 |
|
80 |
private Code parse_relational() {
|
|
163 |
public Code parse_relational() {
|
|
81 | 164 |
Code op1 = parse_not(); |
82 | 165 |
Code op2; |
83 | 166 |
while( true ) { |
... | ... | |
105 | 188 |
} |
106 | 189 |
} |
107 | 190 |
|
108 |
private Code parse_not() {
|
|
191 |
public Code parse_not() {
|
|
109 | 192 |
Code op1; |
110 | 193 |
Token token = lexer.look(); |
111 | 194 |
if( token.getType() == Token.OP_NOT ) { |
... | ... | |
118 | 201 |
return op1; |
119 | 202 |
} |
120 | 203 |
|
121 |
private Code parse_conditional() {
|
|
204 |
public Code parse_conditional() {
|
|
122 | 205 |
Code op1 = parse_sum(); |
123 | 206 |
Code op2; |
124 | 207 |
while( true ) { |
... | ... | |
160 | 243 |
lexer.next(); |
161 | 244 |
op2 = parse_sum(); |
162 | 245 |
if( op2==null ) { |
163 |
throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_EQ_operator(),lexer); |
|
246 |
token = lexer.look(); |
|
247 |
String tip = null; |
|
248 |
switch(token.getType()) { |
|
249 |
case Token.OP_GT: |
|
250 |
tip = I18N.The_operator_greater_than_or_equal_is_ge(); |
|
251 |
break; |
|
252 |
case Token.OP_LT: |
|
253 |
tip = I18N.The_operator_less_than_or_equal_is_ge(); |
|
254 |
break; |
|
255 |
} |
|
256 |
throw new ExpressionSyntaxException( |
|
257 |
I18N.Cant_recognize_the_second_operand_of_EQ_operator(), |
|
258 |
lexer, |
|
259 |
tip |
|
260 |
); |
|
164 | 261 |
} |
165 | 262 |
op1 = codeBuilder.eq(op1, op2); |
166 | 263 |
break; |
... | ... | |
221 | 318 |
} |
222 | 319 |
} |
223 | 320 |
|
224 |
private Code parse_sum() {
|
|
321 |
public Code parse_sum() {
|
|
225 | 322 |
Code op1 = parse_factor(); |
226 | 323 |
Code op2; |
227 | 324 |
while( true ) { |
228 | 325 |
Token token = lexer.look(); |
229 | 326 |
switch( token.getType() ) { |
327 |
case Token.OP_CONCAT: |
|
328 |
lexer.next(); |
|
329 |
op2 = parse_factor(); |
|
330 |
op1 = codeBuilder.concat(op1, op2); |
|
331 |
break; |
|
230 | 332 |
case Token.OP_ADD: |
231 | 333 |
lexer.next(); |
232 | 334 |
op2 = parse_factor(); |
... | ... | |
243 | 345 |
} |
244 | 346 |
} |
245 | 347 |
|
246 |
private Code parse_factor() {
|
|
348 |
public Code parse_factor() {
|
|
247 | 349 |
Code op1 = parse_getattr(); |
248 | 350 |
Code op2; |
249 | 351 |
while( true ) { |
... | ... | |
273 | 375 |
} |
274 | 376 |
op1 = codeBuilder.mod(op1, op2); |
275 | 377 |
break; |
378 |
case Token.OPEN_BRACKET: |
|
379 |
lexer.next(); |
|
380 |
Code codeIndex = parse_expression(); |
|
381 |
if( codeIndex == null ) { |
|
382 |
throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer); |
|
383 |
} |
|
384 |
token = lexer.look(); |
|
385 |
if( token.getType()!=Token.CLOSED_BRACKET) { |
|
386 |
throw new ExpressionSyntaxException(I18N.A_XTokenX_was_expected_and_XliteralX_was_found("]", token.getLiteral()),lexer); |
|
387 |
} |
|
388 |
lexer.next(); |
|
389 |
Code code = codeBuilder.getitem(op1, codeIndex); |
|
390 |
return code; |
|
276 | 391 |
default: |
277 | 392 |
return op1; |
278 | 393 |
} |
279 | 394 |
} |
280 | 395 |
} |
281 | 396 |
|
282 |
private Code parse_getattr() {
|
|
397 |
public Code parse_getattr() {
|
|
283 | 398 |
Code op1 = parse_termino(); |
284 | 399 |
if( !isObjectAccessSupported() ) { |
285 | 400 |
return op1; |
... | ... | |
301 | 416 |
next = lexer.look(); |
302 | 417 |
if( next.getType() == Token.PARENTHESIS_OPEN ) { |
303 | 418 |
lexer.next(); |
304 |
Arguments args = parseArgs();
|
|
419 |
Codes args = parse_expressions(",");
|
|
305 | 420 |
next = lexer.next(); |
306 | 421 |
if( next.getType() != Token.PARENTHESIS_CLOSE ) { |
307 | 422 |
throw new ExpressionSyntaxException( |
... | ... | |
319 | 434 |
} |
320 | 435 |
} |
321 | 436 |
|
322 |
private Code parse_termino() {
|
|
437 |
public Code parse_termino() {
|
|
323 | 438 |
|
324 | 439 |
Token token = lexer.look(); |
325 | 440 |
switch( token.getType() ) { |
326 | 441 |
case Token.PARENTHESIS_OPEN: { |
327 | 442 |
lexer.next(); |
328 |
Code value = parseExpression();
|
|
443 |
Code value = parse_expression();
|
|
329 | 444 |
Token next = lexer.next(); |
330 | 445 |
switch(next.getType()) { |
331 | 446 |
case Token.PARENTHESIS_CLOSE: |
... | ... | |
344 | 459 |
return value; |
345 | 460 |
} |
346 | 461 |
case Token.IDENTIFIER: { |
462 |
Code code = parse_grammars(); |
|
463 |
if( code!=null ) { |
|
464 |
return code; |
|
465 |
} |
|
466 |
if( this.grammars.isReservedWord(token.getLiteral()) ) { |
|
467 |
return null; |
|
468 |
} |
|
347 | 469 |
lexer.next(); |
348 | 470 |
String id = (String) token.getLiteral(); |
349 | 471 |
Token next = lexer.look(); |
350 | 472 |
if( next.getType() == Token.PARENTHESIS_OPEN ) { |
351 | 473 |
lexer.next(); |
352 |
Arguments args = parseArgs();
|
|
474 |
Codes args = parse_expressions(",");
|
|
353 | 475 |
next = lexer.next(); |
354 | 476 |
switch(next.getType()) { |
355 | 477 |
case Token.PARENTHESIS_CLOSE: |
... | ... | |
394 | 516 |
return codeBuilder.negate(code); |
395 | 517 |
case Token.EOF: |
396 | 518 |
throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer); |
519 |
default: |
|
520 |
return parse_grammars(); |
|
397 | 521 |
} |
398 |
return null; |
|
399 | 522 |
} |
400 | 523 |
|
401 |
private Arguments parseArgs() {
|
|
402 |
Arguments args = null;
|
|
524 |
public Codes parse_expressions(String sep) {
|
|
525 |
BaseCodes codes = null;
|
|
403 | 526 |
while( true ) { |
404 |
Code arg = parseExpression();
|
|
405 |
if( arg!=null ) {
|
|
406 |
if( args == null ) {
|
|
407 |
args = codeBuilder.args();
|
|
527 |
Code code = parse_expression();
|
|
528 |
if( code!=null ) {
|
|
529 |
if( codes == null ) {
|
|
530 |
codes = (BaseCodes) codeBuilder.args();
|
|
408 | 531 |
} |
409 |
((DefaultCodeBuilder.BaseArguments)args).add(arg);
|
|
532 |
codes.add(code);
|
|
410 | 533 |
} |
411 | 534 |
Token next = lexer.look(); |
412 |
switch( next.getType() ) { |
|
413 |
case Token.COMA: |
|
535 |
String literal = next.getLiteral(); |
|
536 |
if( literal == null ) { |
|
537 |
return codes; |
|
538 |
} |
|
539 |
literal = literal.trim(); |
|
540 |
if( sep.equals(literal) ) { |
|
414 | 541 |
lexer.next(); // Consume el ",". |
415 |
break; |
|
416 |
default: |
|
417 |
return args; |
|
542 |
} else { |
|
543 |
return codes; |
|
418 | 544 |
} |
419 | 545 |
} |
420 | 546 |
} |
547 |
|
|
548 |
private Code parse_grammars() { |
|
549 |
StatementContext context = new DefaultStatementContext(); |
|
550 |
Statement stmt = this.grammars.getApplicableStatement(context); |
|
551 |
if( stmt!=null ) { |
|
552 |
Code code1 = stmt.parse(context); |
|
553 |
return code1; |
|
554 |
} |
|
555 |
return null; |
|
556 |
} |
|
421 | 557 |
} |
Also available in: Unified diff