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

History | View | Annotate | Download (14.6 KB)

1
package org.gvsig.expressionevaluator.impl;
2

    
3
import org.gvsig.expressionevaluator.Compiler;
4
import org.gvsig.expressionevaluator.Code.Caller.Arguments;
5
import org.gvsig.expressionevaluator.LexicalAnalyzer;
6
import org.gvsig.expressionevaluator.LexicalAnalyzer.Token;
7
import org.gvsig.expressionevaluator.Code;
8
import org.gvsig.expressionevaluator.CodeBuilder;
9
import org.gvsig.expressionevaluator.ExpressionSyntaxException;
10

    
11
public class DefaultCompiler implements Compiler {
12

    
13
    private boolean objectAccessSupported;
14
    private LexicalAnalyzer lexer;
15
    private CodeBuilder codeBuilder;
16
    //
17
    // https://www.postgresql.org/docs/9.1/static/functions.html
18
    //
19

    
20
    public DefaultCompiler() {
21
        this.lexer = new SQLLexicalAnalyzer();
22
        this.codeBuilder = new DefaultCodeBuilder();
23
        this.objectAccessSupported = true;
24
    }
25

    
26
    @Override
27
    public Compiler clone() throws CloneNotSupportedException {
28
        DefaultCompiler other = (DefaultCompiler) super.clone();
29
        other.lexer = lexer.clone();
30
        other.codeBuilder = codeBuilder.clone();
31
        
32
        return other;
33
    }
34

    
35
    @Override
36
    public void setLexicalAnalyzer(LexicalAnalyzer lexer) {
37
        this.lexer = lexer;
38
    }
39

    
40
    @Override
41
    public LexicalAnalyzer getLexicalAnalyzer() {
42
        return this.lexer;
43
    }
44
    
45
    @Override
46
    public void setCodeBuilder(CodeBuilder codeBuilder) {
47
        this.codeBuilder = codeBuilder;
48
    }
49

    
50
    @Override
51
    public CodeBuilder getCodeBuilder() {
52
        return this.codeBuilder;
53
    }
54
    
55
    @Override
56
    public boolean isObjectAccessSupported() {
57
        return this.objectAccessSupported;
58
    }
59

    
60
    @Override
61
    public void setObjectAccessSupported(boolean objectAccessSupported) {
62
        this.objectAccessSupported = objectAccessSupported;
63
    }
64
    
65
    @Override
66
    public Code compileExpression(String expression) {
67
        this.lexer.setSource(expression.trim());
68
        Code code = parseExpression();
69
        if( !this.lexer.isEOF() ) {
70
            throw new ExpressionSyntaxException(lexer);
71
        }
72
        return code;
73
    }
74

    
75
    private Code parseExpression() {
76
        Code code = parse_relational();
77
        return code;
78
    }
79

    
80
    private Code parse_relational() {
81
        Code op1 = parse_not();
82
        Code op2;
83
        while( true ) {
84
            Token token = lexer.look();
85
            switch( token.getType() ) {
86
            case Token.OP_OR:
87
                lexer.next();
88
                op2 = parse_not();
89
                if( op2==null ) {
90
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_OR_operator(),lexer);
91
                }
92
                op1 = codeBuilder.or(op1, op2);
93
                break;
94
            case Token.OP_AND:
95
                lexer.next();
96
                op2 = parse_not();
97
                if( op2==null ) {
98
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_AND_operator(),lexer);
99
                }
100
                op1 = codeBuilder.and(op1, op2);
101
                break;
102
            default:
103
                return op1;
104
            }
105
        }
106
    }
107

    
108
    private Code parse_not() {
109
        Code op1;
110
        Token token = lexer.look();
111
        if( token.getType() == Token.OP_NOT ) {
112
            lexer.next();
113
            op1 = parse_conditional();
114
            op1 = codeBuilder.not(op1);
115
        } else {
116
            op1 = parse_conditional();
117
        }
118
        return op1;
119
    }
120

    
121
    private Code parse_conditional() {
122
        Code op1 = parse_sum();
123
        Code op2;
124
        while( true ) {
125
            Token token = lexer.look();
126
            switch( token.getType() ) {
127
            case Token.OP_LT:
128
                lexer.next();
129
                op2 = parse_sum();
130
                if( op2==null ) {
131
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LT_operator(),lexer);
132
                }
133
                op1 = codeBuilder.lt(op1, op2);
134
                break;
135
            case Token.OP_GT:
136
                lexer.next();
137
                op2 = parse_sum();
138
                if( op2==null ) {
139
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GT_operator(),lexer);
140
                }
141
                op1 = codeBuilder.gt(op1, op2);
142
                break;
143
            case Token.OP_LE:
144
                lexer.next();
145
                op2 = parse_sum();
146
                if( op2==null ) {
147
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LE_operator(),lexer);
148
                }
149
                op1 = codeBuilder.le(op1, op2);
150
                break;
151
            case Token.OP_GE:
152
                lexer.next();
153
                op2 = parse_sum();
154
                if( op2==null ) {
155
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GE_operator(),lexer);
156
                }
157
                op1 = codeBuilder.ge(op1, op2);
158
                break;
159
            case Token.OP_EQ:
160
                lexer.next();
161
                op2 = parse_sum();
162
                if( op2==null ) {
163
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_EQ_operator(),lexer);
164
                }
165
                op1 = codeBuilder.eq(op1, op2);
166
                break;
167
            case Token.OP_NE:
168
                lexer.next();
169
                op2 = parse_sum();
170
                if( op2==null ) {
171
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_NEQ_operator(),lexer);
172
                }
173
                op1 = codeBuilder.ne(op1, op2);
174
                break;
175
            case Token.PRED_IS: {
176
                    lexer.next();
177
                    Token next = lexer.look();
178
                    if( next.getType() == Token.NOTNULL ) {
179
                        op1 = codeBuilder.is(op1, codeBuilder.constant(null));
180
                        op1 = codeBuilder.not(op1);
181
                    } else {
182
                        op2 = parse_sum();
183
                        if( op2==null ) {
184
                            throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_IS_operator(),lexer);
185
                        }
186
                        op1 = codeBuilder.is(op1, op2);
187
                    }
188
                }
189
                break;
190
            case Token.ISNULL:
191
                lexer.next();
192
                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
193
                break;
194
            case Token.OP_REGEXP:
195
                lexer.next();
196
                op2 = parse_sum();
197
                if( op2==null ) {
198
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_REGEXP_operator(),lexer);
199
                }
200
                op1 = codeBuilder.regexp(op1, op2);
201
                break;
202
            case Token.PRED_LIKE:
203
                lexer.next();
204
                op2 = parse_sum();
205
                if( op2==null ) {
206
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LIKE_operator(),lexer);
207
                }
208
                op1 = codeBuilder.like(op1, op2);
209
                break;
210
            case Token.PRED_ILIKE:
211
                lexer.next();
212
                op2 = parse_sum();
213
                if( op2==null ) {
214
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_ILIKE_operator(),lexer);
215
                }
216
                op1 = codeBuilder.ilike(op1, op2);
217
                break;
218
            default:
219
                return op1;
220
            }
221
        }
222
    }
223

    
224
    private Code parse_sum() {
225
        Code op1 = parse_factor();
226
        Code op2;
227
        while( true ) {
228
            Token token = lexer.look();
229
            switch( token.getType() ) {
230
            case Token.OP_ADD:
231
                lexer.next();
232
                op2 = parse_factor();
233
                op1 = codeBuilder.add(op1, op2);
234
                break;
235
            case Token.OP_SUBST:
236
                lexer.next();
237
                op2 = parse_factor();
238
                op1 = codeBuilder.subst(op1, op2);
239
                break;
240
            default:
241
                return op1;
242
            }
243
        }
244
    }
245

    
246
    private Code parse_factor() {
247
        Code op1 = parse_getattr();
248
        Code op2;
249
        while( true ) {
250
            Token token = lexer.look();
251
            switch( token.getType() ) {
252
            case Token.OP_MULT:
253
                lexer.next();
254
                op2 = parse_getattr();
255
                if( op2==null ) {
256
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MULT_operator(),lexer);
257
                }
258
                op1 = codeBuilder.mult(op1, op2);
259
                break;
260
            case Token.OP_DIV:
261
                lexer.next();
262
                op2 = parse_getattr();
263
                if( op2==null ) {
264
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_DIV_operator(),lexer);
265
                }
266
                op1 = codeBuilder.div(op1, op2);
267
                break;
268
            case Token.OP_MOD:
269
                lexer.next();
270
                op2 = parse_getattr();
271
                if( op2==null ) {
272
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MOD_operator(),lexer);
273
                }
274
                op1 = codeBuilder.mod(op1, op2);
275
                break;
276
            default:
277
                return op1;
278
            }
279
        }
280
    }
281

    
282
    private Code parse_getattr() {
283
        Code op1 = parse_termino();
284
        if( !isObjectAccessSupported() ) {
285
            return op1;
286
        }
287
        while( true ) {
288
            Token next = lexer.look();
289
            switch( next.getType() ) {
290
            case Token.OP_GETATTR:
291
                lexer.next();
292
                next = lexer.look();
293
                if( next.getType()!=Token.IDENTIFIER ) {
294
                    throw new ExpressionSyntaxException(
295
                        I18N.An_attribute_identifier_was_expected_and_XliteralX_was_found(next.getLiteral()),
296
                        lexer
297
                    );
298
                }
299
                String id = (String) next.getLiteral();
300
                lexer.next();
301
                next = lexer.look();
302
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
303
                    lexer.next();
304
                    Arguments args = parseArgs();
305
                    next = lexer.next();
306
                    if( next.getType() != Token.PARENTHESIS_CLOSE ) {
307
                        throw new ExpressionSyntaxException(
308
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
309
                            lexer
310
                        );
311
                    }
312
                    return codeBuilder.method(op1, id, args);
313
                } else {
314
                    return codeBuilder.getattr(op1, id);
315
                }
316
            default:
317
                return op1;
318
            }
319
        }
320
    }    
321

    
322
    private Code parse_termino() {
323

    
324
        Token token = lexer.look();
325
        switch( token.getType() ) {
326
        case Token.PARENTHESIS_OPEN: {
327
                lexer.next();
328
                Code value = parseExpression();
329
                Token next = lexer.next();
330
                switch(next.getType()) {
331
                    case Token.PARENTHESIS_CLOSE:
332
                        break;
333
                    case Token.EOF:
334
                        throw new ExpressionSyntaxException(
335
                            I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(),
336
                            lexer
337
                        );
338
                    default:
339
                        throw new ExpressionSyntaxException(
340
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
341
                            lexer
342
                        );
343
                }
344
                return value;
345
            }
346
        case Token.IDENTIFIER: {
347
                lexer.next();
348
                String id = (String) token.getLiteral();
349
                Token next = lexer.look();
350
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
351
                    lexer.next();
352
                    Arguments args = parseArgs();
353
                    next = lexer.next();
354
                    switch(next.getType()) {
355
                        case Token.PARENTHESIS_CLOSE:
356
                            break;
357
                        case Token.EOF:
358
                            throw new ExpressionSyntaxException(
359
                                I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(),
360
                                lexer
361
                            );
362
                        default:
363
                            throw new ExpressionSyntaxException(
364
                                I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
365
                                lexer
366
                            );
367
                    }
368
                    return codeBuilder.function(id, args);
369
                } else {
370
                    return codeBuilder.identifier(id);
371
                }
372
            }
373
        case Token.STRING_LITERAL:
374
            lexer.next();
375
            return codeBuilder.constant(token.getValue());
376
        case Token.INTEGER_LITERAL:
377
            lexer.next();
378
            return codeBuilder.constant(token.getValue());
379
        case Token.FLOATING_POINT_LITERAL:
380
            lexer.next();
381
            return codeBuilder.constant(token.getValue());
382
        case Token.NULL:
383
            lexer.next();
384
            return codeBuilder.constant(null);
385
        case Token.TRUE:
386
            lexer.next();
387
            return codeBuilder.constant(true);
388
        case Token.FALSE:
389
            lexer.next();
390
            return codeBuilder.constant(false);
391
        case Token.OP_SUBST:
392
            lexer.next();
393
            Code code = parse_termino();
394
            return codeBuilder.negate(code);
395
        case Token.EOF:
396
            throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer);
397
        }
398
        return null;
399
    }
400

    
401
    private Arguments parseArgs() {
402
        Arguments args = null;
403
        while( true ) {
404
            Code arg = parseExpression();
405
            if( arg!=null ) {
406
                if( args == null ) {
407
                    args = codeBuilder.args();
408
                }
409
                ((DefaultCodeBuilder.BaseArguments)args).add(arg);
410
            }
411
            Token next = lexer.look();
412
            switch( next.getType() ) {
413
            case Token.COMA:
414
                lexer.next(); // Consume el ",".
415
                break;
416
            default:
417
                return args;
418
            }
419
        }
420
    }
421
}