Statistics
| Revision:

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 @ 44198

History | View | Annotate | Download (18.8 KB)

1 43512 jjdelcerro
package org.gvsig.expressionevaluator.impl;
2
3 44139 jjdelcerro
import java.util.HashMap;
4
import java.util.Map;
5
import org.apache.commons.lang3.StringUtils;
6 43512 jjdelcerro
import org.gvsig.expressionevaluator.Compiler;
7
import org.gvsig.expressionevaluator.LexicalAnalyzer;
8
import org.gvsig.expressionevaluator.LexicalAnalyzer.Token;
9
import org.gvsig.expressionevaluator.Code;
10
import org.gvsig.expressionevaluator.CodeBuilder;
11 44139 jjdelcerro
import org.gvsig.expressionevaluator.Codes;
12 43983 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionSyntaxException;
13 44139 jjdelcerro
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;
17 43512 jjdelcerro
18
public class DefaultCompiler implements Compiler {
19
20 44139 jjdelcerro
    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
89 43939 jjdelcerro
    private boolean objectAccessSupported;
90 43512 jjdelcerro
    private LexicalAnalyzer lexer;
91
    private CodeBuilder codeBuilder;
92 44139 jjdelcerro
    private final GrammarSet grammars;
93 43532 jjdelcerro
    //
94
    // https://www.postgresql.org/docs/9.1/static/functions.html
95
    //
96 43512 jjdelcerro
97
    public DefaultCompiler() {
98 44139 jjdelcerro
        this.grammars = new DefaultGrammarSet();
99 43512 jjdelcerro
        this.lexer = new SQLLexicalAnalyzer();
100
        this.codeBuilder = new DefaultCodeBuilder();
101 43939 jjdelcerro
        this.objectAccessSupported = true;
102 43512 jjdelcerro
    }
103
104
    @Override
105 43809 jjdelcerro
    public Compiler clone() throws CloneNotSupportedException {
106
        DefaultCompiler other = (DefaultCompiler) super.clone();
107
        other.lexer = lexer.clone();
108
        other.codeBuilder = codeBuilder.clone();
109
110
        return other;
111
    }
112
113
    @Override
114 43512 jjdelcerro
    public void setLexicalAnalyzer(LexicalAnalyzer lexer) {
115
        this.lexer = lexer;
116
    }
117 43983 jjdelcerro
118
    @Override
119
    public LexicalAnalyzer getLexicalAnalyzer() {
120
        return this.lexer;
121
    }
122 43512 jjdelcerro
123
    @Override
124
    public void setCodeBuilder(CodeBuilder codeBuilder) {
125
        this.codeBuilder = codeBuilder;
126
    }
127 43809 jjdelcerro
128 43512 jjdelcerro
    @Override
129 43809 jjdelcerro
    public CodeBuilder getCodeBuilder() {
130
        return this.codeBuilder;
131
    }
132
133
    @Override
134 43939 jjdelcerro
    public boolean isObjectAccessSupported() {
135
        return this.objectAccessSupported;
136
    }
137
138
    @Override
139
    public void setObjectAccessSupported(boolean objectAccessSupported) {
140
        this.objectAccessSupported = objectAccessSupported;
141
    }
142 44139 jjdelcerro
143 43939 jjdelcerro
    @Override
144 44139 jjdelcerro
    public GrammarSet getGrammars() {
145
        return this.grammars;
146
    }
147
148
    @Override
149 43512 jjdelcerro
    public Code compileExpression(String expression) {
150 43983 jjdelcerro
        this.lexer.setSource(expression.trim());
151 44139 jjdelcerro
        Code code = parse_expression();
152 43983 jjdelcerro
        if( !this.lexer.isEOF() ) {
153
            throw new ExpressionSyntaxException(lexer);
154
        }
155
        return code;
156 43512 jjdelcerro
    }
157
158 44139 jjdelcerro
    public Code parse_expression() {
159 43983 jjdelcerro
        Code code = parse_relational();
160
        return code;
161 43512 jjdelcerro
    }
162
163 44139 jjdelcerro
    public Code parse_relational() {
164 43512 jjdelcerro
        Code op1 = parse_not();
165
        Code op2;
166
        while( true ) {
167
            Token token = lexer.look();
168
            switch( token.getType() ) {
169
            case Token.OP_OR:
170
                lexer.next();
171
                op2 = parse_not();
172 43983 jjdelcerro
                if( op2==null ) {
173 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_OR_operator(),lexer);
174 43983 jjdelcerro
                }
175 43512 jjdelcerro
                op1 = codeBuilder.or(op1, op2);
176
                break;
177
            case Token.OP_AND:
178
                lexer.next();
179
                op2 = parse_not();
180 43983 jjdelcerro
                if( op2==null ) {
181 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_AND_operator(),lexer);
182 43983 jjdelcerro
                }
183 43512 jjdelcerro
                op1 = codeBuilder.and(op1, op2);
184
                break;
185
            default:
186
                return op1;
187
            }
188
        }
189
    }
190
191 44139 jjdelcerro
    public Code parse_not() {
192 43512 jjdelcerro
        Code op1;
193
        Token token = lexer.look();
194
        if( token.getType() == Token.OP_NOT ) {
195
            lexer.next();
196
            op1 = parse_conditional();
197
            op1 = codeBuilder.not(op1);
198
        } else {
199
            op1 = parse_conditional();
200
        }
201
        return op1;
202
    }
203
204 44139 jjdelcerro
    public Code parse_conditional() {
205 43512 jjdelcerro
        Code op1 = parse_sum();
206
        Code op2;
207
        while( true ) {
208
            Token token = lexer.look();
209
            switch( token.getType() ) {
210
            case Token.OP_LT:
211
                lexer.next();
212
                op2 = parse_sum();
213 43983 jjdelcerro
                if( op2==null ) {
214 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LT_operator(),lexer);
215 43983 jjdelcerro
                }
216 43512 jjdelcerro
                op1 = codeBuilder.lt(op1, op2);
217
                break;
218
            case Token.OP_GT:
219
                lexer.next();
220
                op2 = parse_sum();
221 43983 jjdelcerro
                if( op2==null ) {
222 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GT_operator(),lexer);
223 43983 jjdelcerro
                }
224 43512 jjdelcerro
                op1 = codeBuilder.gt(op1, op2);
225
                break;
226
            case Token.OP_LE:
227
                lexer.next();
228
                op2 = parse_sum();
229 43983 jjdelcerro
                if( op2==null ) {
230 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LE_operator(),lexer);
231 43983 jjdelcerro
                }
232 43512 jjdelcerro
                op1 = codeBuilder.le(op1, op2);
233
                break;
234
            case Token.OP_GE:
235
                lexer.next();
236
                op2 = parse_sum();
237 43983 jjdelcerro
                if( op2==null ) {
238 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GE_operator(),lexer);
239 43983 jjdelcerro
                }
240 43512 jjdelcerro
                op1 = codeBuilder.ge(op1, op2);
241
                break;
242
            case Token.OP_EQ:
243
                lexer.next();
244
                op2 = parse_sum();
245 43983 jjdelcerro
                if( op2==null ) {
246 44139 jjdelcerro
                    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
                    );
261 43983 jjdelcerro
                }
262 43512 jjdelcerro
                op1 = codeBuilder.eq(op1, op2);
263
                break;
264 43521 jjdelcerro
            case Token.OP_NE:
265 43512 jjdelcerro
                lexer.next();
266 43521 jjdelcerro
                op2 = parse_sum();
267 43983 jjdelcerro
                if( op2==null ) {
268 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_NEQ_operator(),lexer);
269 43983 jjdelcerro
                }
270 43521 jjdelcerro
                op1 = codeBuilder.ne(op1, op2);
271
                break;
272
            case Token.PRED_IS: {
273
                    lexer.next();
274
                    Token next = lexer.look();
275
                    if( next.getType() == Token.NOTNULL ) {
276
                        op1 = codeBuilder.is(op1, codeBuilder.constant(null));
277
                        op1 = codeBuilder.not(op1);
278
                    } else {
279
                        op2 = parse_sum();
280 43983 jjdelcerro
                        if( op2==null ) {
281 44098 jjdelcerro
                            throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_IS_operator(),lexer);
282 43983 jjdelcerro
                        }
283 43521 jjdelcerro
                        op1 = codeBuilder.is(op1, op2);
284
                    }
285 43512 jjdelcerro
                }
286 43521 jjdelcerro
                break;
287 43512 jjdelcerro
            case Token.ISNULL:
288
                lexer.next();
289
                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
290
                break;
291 43532 jjdelcerro
            case Token.OP_REGEXP:
292
                lexer.next();
293
                op2 = parse_sum();
294 43983 jjdelcerro
                if( op2==null ) {
295 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_REGEXP_operator(),lexer);
296 43983 jjdelcerro
                }
297 43532 jjdelcerro
                op1 = codeBuilder.regexp(op1, op2);
298
                break;
299 43512 jjdelcerro
            case Token.PRED_LIKE:
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_LIKE_operator(),lexer);
304 43983 jjdelcerro
                }
305 43512 jjdelcerro
                op1 = codeBuilder.like(op1, op2);
306
                break;
307
            case Token.PRED_ILIKE:
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_ILIKE_operator(),lexer);
312 43983 jjdelcerro
                }
313 43512 jjdelcerro
                op1 = codeBuilder.ilike(op1, op2);
314
                break;
315
            default:
316
                return op1;
317
            }
318
        }
319
    }
320
321 44139 jjdelcerro
    public Code parse_sum() {
322 43512 jjdelcerro
        Code op1 = parse_factor();
323
        Code op2;
324
        while( true ) {
325
            Token token = lexer.look();
326
            switch( token.getType() ) {
327 44139 jjdelcerro
            case Token.OP_CONCAT:
328
                lexer.next();
329
                op2 = parse_factor();
330
                op1 = codeBuilder.concat(op1, op2);
331
                break;
332 43512 jjdelcerro
            case Token.OP_ADD:
333
                lexer.next();
334
                op2 = parse_factor();
335
                op1 = codeBuilder.add(op1, op2);
336
                break;
337
            case Token.OP_SUBST:
338
                lexer.next();
339
                op2 = parse_factor();
340
                op1 = codeBuilder.subst(op1, op2);
341
                break;
342
            default:
343
                return op1;
344
            }
345
        }
346
    }
347
348 44139 jjdelcerro
    public Code parse_factor() {
349 43939 jjdelcerro
        Code op1 = parse_getattr();
350 43512 jjdelcerro
        Code op2;
351
        while( true ) {
352
            Token token = lexer.look();
353
            switch( token.getType() ) {
354
            case Token.OP_MULT:
355
                lexer.next();
356 43939 jjdelcerro
                op2 = parse_getattr();
357 43983 jjdelcerro
                if( op2==null ) {
358 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MULT_operator(),lexer);
359 43983 jjdelcerro
                }
360 43512 jjdelcerro
                op1 = codeBuilder.mult(op1, op2);
361
                break;
362
            case Token.OP_DIV:
363
                lexer.next();
364 43939 jjdelcerro
                op2 = parse_getattr();
365 43983 jjdelcerro
                if( op2==null ) {
366 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_DIV_operator(),lexer);
367 43983 jjdelcerro
                }
368 43512 jjdelcerro
                op1 = codeBuilder.div(op1, op2);
369
                break;
370
            case Token.OP_MOD:
371
                lexer.next();
372 43939 jjdelcerro
                op2 = parse_getattr();
373 43983 jjdelcerro
                if( op2==null ) {
374 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MOD_operator(),lexer);
375 43983 jjdelcerro
                }
376 43512 jjdelcerro
                op1 = codeBuilder.mod(op1, op2);
377
                break;
378 44139 jjdelcerro
            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;
391 43512 jjdelcerro
            default:
392
                return op1;
393
            }
394
        }
395
    }
396
397 44139 jjdelcerro
    public Code parse_getattr() {
398 43939 jjdelcerro
        Code op1 = parse_termino();
399
        if( !isObjectAccessSupported() ) {
400
            return op1;
401
        }
402
        while( true ) {
403
            Token next = lexer.look();
404
            switch( next.getType() ) {
405
            case Token.OP_GETATTR:
406
                lexer.next();
407
                next = lexer.look();
408
                if( next.getType()!=Token.IDENTIFIER ) {
409 43983 jjdelcerro
                    throw new ExpressionSyntaxException(
410 44098 jjdelcerro
                        I18N.An_attribute_identifier_was_expected_and_XliteralX_was_found(next.getLiteral()),
411
                        lexer
412 43983 jjdelcerro
                    );
413 43939 jjdelcerro
                }
414
                String id = (String) next.getLiteral();
415
                lexer.next();
416
                next = lexer.look();
417
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
418
                    lexer.next();
419 44139 jjdelcerro
                    Codes args = parse_expressions(",");
420 43939 jjdelcerro
                    next = lexer.next();
421
                    if( next.getType() != Token.PARENTHESIS_CLOSE ) {
422 43983 jjdelcerro
                        throw new ExpressionSyntaxException(
423 44098 jjdelcerro
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
424
                            lexer
425 43983 jjdelcerro
                        );
426 43939 jjdelcerro
                    }
427
                    return codeBuilder.method(op1, id, args);
428
                } else {
429
                    return codeBuilder.getattr(op1, id);
430
                }
431
            default:
432
                return op1;
433
            }
434
        }
435
    }
436
437 44139 jjdelcerro
    public Code parse_termino() {
438 43512 jjdelcerro
439
        Token token = lexer.look();
440
        switch( token.getType() ) {
441
        case Token.PARENTHESIS_OPEN: {
442 43521 jjdelcerro
                lexer.next();
443 44139 jjdelcerro
                Code value = parse_expression();
444 43521 jjdelcerro
                Token next = lexer.next();
445 44098 jjdelcerro
                switch(next.getType()) {
446
                    case Token.PARENTHESIS_CLOSE:
447
                        break;
448
                    case Token.EOF:
449
                        throw new ExpressionSyntaxException(
450
                            I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(),
451
                            lexer
452
                        );
453
                    default:
454
                        throw new ExpressionSyntaxException(
455
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
456
                            lexer
457
                        );
458 43521 jjdelcerro
                }
459
                return value;
460 43512 jjdelcerro
            }
461
        case Token.IDENTIFIER: {
462 44139 jjdelcerro
                Code code = parse_grammars();
463
                if( code!=null ) {
464
                    return code;
465
                }
466
                if( this.grammars.isReservedWord(token.getLiteral()) ) {
467
                    return null;
468
                }
469 43512 jjdelcerro
                lexer.next();
470 43521 jjdelcerro
                String id = (String) token.getLiteral();
471
                Token next = lexer.look();
472
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
473
                    lexer.next();
474 44139 jjdelcerro
                    Codes args = parse_expressions(",");
475 43521 jjdelcerro
                    next = lexer.next();
476 44098 jjdelcerro
                    switch(next.getType()) {
477
                        case Token.PARENTHESIS_CLOSE:
478
                            break;
479
                        case Token.EOF:
480
                            throw new ExpressionSyntaxException(
481
                                I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(),
482
                                lexer
483
                            );
484
                        default:
485
                            throw new ExpressionSyntaxException(
486
                                I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
487
                                lexer
488
                            );
489 43521 jjdelcerro
                    }
490
                    return codeBuilder.function(id, args);
491
                } else {
492
                    return codeBuilder.identifier(id);
493 43512 jjdelcerro
                }
494
            }
495
        case Token.STRING_LITERAL:
496
            lexer.next();
497
            return codeBuilder.constant(token.getValue());
498
        case Token.INTEGER_LITERAL:
499
            lexer.next();
500
            return codeBuilder.constant(token.getValue());
501
        case Token.FLOATING_POINT_LITERAL:
502
            lexer.next();
503
            return codeBuilder.constant(token.getValue());
504
        case Token.NULL:
505
            lexer.next();
506
            return codeBuilder.constant(null);
507
        case Token.TRUE:
508
            lexer.next();
509
            return codeBuilder.constant(true);
510
        case Token.FALSE:
511
            lexer.next();
512
            return codeBuilder.constant(false);
513 44098 jjdelcerro
        case Token.OP_SUBST:
514
            lexer.next();
515
            Code code = parse_termino();
516
            return codeBuilder.negate(code);
517
        case Token.EOF:
518
            throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer);
519 44139 jjdelcerro
        default:
520
            return parse_grammars();
521 43512 jjdelcerro
        }
522
    }
523
524 44139 jjdelcerro
    public Codes parse_expressions(String sep) {
525
        BaseCodes codes = null;
526 43512 jjdelcerro
        while( true ) {
527 44139 jjdelcerro
            Code code = parse_expression();
528
            if( code!=null ) {
529
                if( codes == null ) {
530
                    codes = (BaseCodes) codeBuilder.args();
531 43519 jjdelcerro
                }
532 44139 jjdelcerro
                codes.add(code);
533 43519 jjdelcerro
            }
534 43512 jjdelcerro
            Token next = lexer.look();
535 44139 jjdelcerro
            String literal = next.getLiteral();
536
            if( literal == null ) {
537
                return codes;
538
            }
539
            literal = literal.trim();
540
            if( sep.equals(literal) ) {
541 43512 jjdelcerro
                lexer.next(); // Consume el ",".
542 44139 jjdelcerro
            } else {
543
                return codes;
544 43512 jjdelcerro
            }
545
        }
546
    }
547 44139 jjdelcerro
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
    }
557 43512 jjdelcerro
}