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

History | View | Annotate | Download (18.8 KB)

1
package org.gvsig.expressionevaluator.impl;
2

    
3
import java.util.HashMap;
4
import java.util.Map;
5
import org.apache.commons.lang3.StringUtils;
6
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
import org.gvsig.expressionevaluator.Codes;
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;
17

    
18
public class DefaultCompiler implements Compiler {
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

    
89
    private boolean objectAccessSupported;
90
    private LexicalAnalyzer lexer;
91
    private CodeBuilder codeBuilder;
92
    private final GrammarSet grammars;
93
    //
94
    // https://www.postgresql.org/docs/9.1/static/functions.html
95
    //
96

    
97
    public DefaultCompiler() {
98
        this.grammars = new DefaultGrammarSet();
99
        this.lexer = new SQLLexicalAnalyzer();
100
        this.codeBuilder = new DefaultCodeBuilder();
101
        this.objectAccessSupported = true;
102
    }
103

    
104
    @Override
105
    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
    public void setLexicalAnalyzer(LexicalAnalyzer lexer) {
115
        this.lexer = lexer;
116
    }
117

    
118
    @Override
119
    public LexicalAnalyzer getLexicalAnalyzer() {
120
        return this.lexer;
121
    }
122
    
123
    @Override
124
    public void setCodeBuilder(CodeBuilder codeBuilder) {
125
        this.codeBuilder = codeBuilder;
126
    }
127

    
128
    @Override
129
    public CodeBuilder getCodeBuilder() {
130
        return this.codeBuilder;
131
    }
132
    
133
    @Override
134
    public boolean isObjectAccessSupported() {
135
        return this.objectAccessSupported;
136
    }
137

    
138
    @Override
139
    public void setObjectAccessSupported(boolean objectAccessSupported) {
140
        this.objectAccessSupported = objectAccessSupported;
141
    }
142

    
143
    @Override
144
    public GrammarSet getGrammars() {
145
        return this.grammars;
146
    }
147

    
148
    @Override
149
    public Code compileExpression(String expression) {
150
        this.lexer.setSource(expression.trim());
151
        Code code = parse_expression();
152
        if( !this.lexer.isEOF() ) {
153
            throw new ExpressionSyntaxException(lexer);
154
        }
155
        return code;
156
    }
157

    
158
    public Code parse_expression() {
159
        Code code = parse_relational();
160
        return code;
161
    }
162

    
163
    public Code parse_relational() {
164
        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
                if( op2==null ) {
173
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_OR_operator(),lexer);
174
                }
175
                op1 = codeBuilder.or(op1, op2);
176
                break;
177
            case Token.OP_AND:
178
                lexer.next();
179
                op2 = parse_not();
180
                if( op2==null ) {
181
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_AND_operator(),lexer);
182
                }
183
                op1 = codeBuilder.and(op1, op2);
184
                break;
185
            default:
186
                return op1;
187
            }
188
        }
189
    }
190

    
191
    public Code parse_not() {
192
        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
    public Code parse_conditional() {
205
        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
                if( op2==null ) {
214
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LT_operator(),lexer);
215
                }
216
                op1 = codeBuilder.lt(op1, op2);
217
                break;
218
            case Token.OP_GT:
219
                lexer.next();
220
                op2 = parse_sum();
221
                if( op2==null ) {
222
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GT_operator(),lexer);
223
                }
224
                op1 = codeBuilder.gt(op1, op2);
225
                break;
226
            case Token.OP_LE:
227
                lexer.next();
228
                op2 = parse_sum();
229
                if( op2==null ) {
230
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LE_operator(),lexer);
231
                }
232
                op1 = codeBuilder.le(op1, op2);
233
                break;
234
            case Token.OP_GE:
235
                lexer.next();
236
                op2 = parse_sum();
237
                if( op2==null ) {
238
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GE_operator(),lexer);
239
                }
240
                op1 = codeBuilder.ge(op1, op2);
241
                break;
242
            case Token.OP_EQ:
243
                lexer.next();
244
                op2 = parse_sum();
245
                if( op2==null ) {
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
                    );
261
                }
262
                op1 = codeBuilder.eq(op1, op2);
263
                break;
264
            case Token.OP_NE:
265
                lexer.next();
266
                op2 = parse_sum();
267
                if( op2==null ) {
268
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_NEQ_operator(),lexer);
269
                }
270
                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
                        if( op2==null ) {
281
                            throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_IS_operator(),lexer);
282
                        }
283
                        op1 = codeBuilder.is(op1, op2);
284
                    }
285
                }
286
                break;
287
            case Token.ISNULL:
288
                lexer.next();
289
                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
290
                break;
291
            case Token.OP_REGEXP:
292
                lexer.next();
293
                op2 = parse_sum();
294
                if( op2==null ) {
295
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_REGEXP_operator(),lexer);
296
                }
297
                op1 = codeBuilder.regexp(op1, op2);
298
                break;
299
            case Token.PRED_LIKE:
300
                lexer.next();
301
                op2 = parse_sum();
302
                if( op2==null ) {
303
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LIKE_operator(),lexer);
304
                }
305
                op1 = codeBuilder.like(op1, op2);
306
                break;
307
            case Token.PRED_ILIKE:
308
                lexer.next();
309
                op2 = parse_sum();
310
                if( op2==null ) {
311
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_ILIKE_operator(),lexer);
312
                }
313
                op1 = codeBuilder.ilike(op1, op2);
314
                break;
315
            default:
316
                return op1;
317
            }
318
        }
319
    }
320

    
321
    public Code parse_sum() {
322
        Code op1 = parse_factor();
323
        Code op2;
324
        while( true ) {
325
            Token token = lexer.look();
326
            switch( token.getType() ) {
327
            case Token.OP_CONCAT:
328
                lexer.next();
329
                op2 = parse_factor();
330
                op1 = codeBuilder.concat(op1, op2);
331
                break;
332
            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
    public Code parse_factor() {
349
        Code op1 = parse_getattr();
350
        Code op2;
351
        while( true ) {
352
            Token token = lexer.look();
353
            switch( token.getType() ) {
354
            case Token.OP_MULT:
355
                lexer.next();
356
                op2 = parse_getattr();
357
                if( op2==null ) {
358
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MULT_operator(),lexer);
359
                }
360
                op1 = codeBuilder.mult(op1, op2);
361
                break;
362
            case Token.OP_DIV:
363
                lexer.next();
364
                op2 = parse_getattr();
365
                if( op2==null ) {
366
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_DIV_operator(),lexer);
367
                }
368
                op1 = codeBuilder.div(op1, op2);
369
                break;
370
            case Token.OP_MOD:
371
                lexer.next();
372
                op2 = parse_getattr();
373
                if( op2==null ) {
374
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MOD_operator(),lexer);
375
                }
376
                op1 = codeBuilder.mod(op1, op2);
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;
391
            default:
392
                return op1;
393
            }
394
        }
395
    }
396

    
397
    public Code parse_getattr() {
398
        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
                    throw new ExpressionSyntaxException(
410
                        I18N.An_attribute_identifier_was_expected_and_XliteralX_was_found(next.getLiteral()),
411
                        lexer
412
                    );
413
                }
414
                String id = (String) next.getLiteral();
415
                lexer.next();
416
                next = lexer.look();
417
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
418
                    lexer.next();
419
                    Codes args = parse_expressions(",");
420
                    next = lexer.next();
421
                    if( next.getType() != Token.PARENTHESIS_CLOSE ) {
422
                        throw new ExpressionSyntaxException(
423
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
424
                            lexer
425
                        );
426
                    }
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
    public Code parse_termino() {
438

    
439
        Token token = lexer.look();
440
        switch( token.getType() ) {
441
        case Token.PARENTHESIS_OPEN: {
442
                lexer.next();
443
                Code value = parse_expression();
444
                Token next = lexer.next();
445
                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
                }
459
                return value;
460
            }
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
                }
469
                lexer.next();
470
                String id = (String) token.getLiteral();
471
                Token next = lexer.look();
472
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
473
                    lexer.next();
474
                    Codes args = parse_expressions(",");
475
                    next = lexer.next();
476
                    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
                    }
490
                    return codeBuilder.function(id, args);
491
                } else {
492
                    return codeBuilder.identifier(id);
493
                }
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
        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
        default:
520
            return parse_grammars();
521
        }
522
    }
523

    
524
    public Codes parse_expressions(String sep) {
525
        BaseCodes codes = null;
526
        while( true ) {
527
            Code code = parse_expression();
528
            if( code!=null ) {
529
                if( codes == null ) {
530
                    codes = (BaseCodes) codeBuilder.args();
531
                }
532
                codes.add(code);
533
            }
534
            Token next = lexer.look();
535
            String literal = next.getLiteral();
536
            if( literal == null ) {
537
                return codes;
538
            }
539
            literal = literal.trim();
540
            if( sep.equals(literal) ) {
541
                lexer.next(); // Consume el ",".
542
            } else {
543
                return codes;
544
            }
545
        }
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
    }
557
}