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

History | View | Annotate | Download (8.55 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

    
10
public class DefaultCompiler implements Compiler {
11

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

    
18
    public DefaultCompiler() {
19
        this.lexer = new SQLLexicalAnalyzer();
20
        this.codeBuilder = new DefaultCodeBuilder();
21
    }
22

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

    
32
    @Override
33
    public void setLexicalAnalyzer(LexicalAnalyzer lexer) {
34
        this.lexer = lexer;
35
    }
36
    
37
    @Override
38
    public void setCodeBuilder(CodeBuilder codeBuilder) {
39
        this.codeBuilder = codeBuilder;
40
    }
41

    
42
    @Override
43
    public CodeBuilder getCodeBuilder() {
44
        return this.codeBuilder;
45
    }
46
    
47
    @Override
48
    public Code compileExpression(String expression) {
49
        this.lexer.setSource(expression);
50
        return parseExpression();
51
    }
52

    
53
    private Code parseExpression() {
54
        return parse_relational();
55
    }
56

    
57
    private Code parse_relational() {
58
        Code op1 = parse_not();
59
        Code op2;
60
        while( true ) {
61
            Token token = lexer.look();
62
            switch( token.getType() ) {
63
            case Token.OP_OR:
64
                lexer.next();
65
                op2 = parse_not();
66
                op1 = codeBuilder.or(op1, op2);
67
                break;
68
            case Token.OP_AND:
69
                lexer.next();
70
                op2 = parse_not();
71
                op1 = codeBuilder.and(op1, op2);
72
                break;
73
            default:
74
                return op1;
75
            }
76
        }
77
    }
78

    
79
    private Code parse_not() {
80
        Code op1;
81
        Token token = lexer.look();
82
        if( token.getType() == Token.OP_NOT ) {
83
            lexer.next();
84
            op1 = parse_conditional();
85
            op1 = codeBuilder.not(op1);
86
        } else {
87
            op1 = parse_conditional();
88
        }
89
        return op1;
90
    }
91

    
92
    private Code parse_conditional() {
93
        Code op1 = parse_sum();
94
        Code op2;
95
        while( true ) {
96
            Token token = lexer.look();
97
            switch( token.getType() ) {
98
            case Token.OP_LT:
99
                lexer.next();
100
                op2 = parse_sum();
101
                op1 = codeBuilder.lt(op1, op2);
102
                break;
103
            case Token.OP_GT:
104
                lexer.next();
105
                op2 = parse_sum();
106
                op1 = codeBuilder.gt(op1, op2);
107
                break;
108
            case Token.OP_LE:
109
                lexer.next();
110
                op2 = parse_sum();
111
                op1 = codeBuilder.le(op1, op2);
112
                break;
113
            case Token.OP_GE:
114
                lexer.next();
115
                op2 = parse_sum();
116
                op1 = codeBuilder.ge(op1, op2);
117
                break;
118
            case Token.OP_EQ:
119
                lexer.next();
120
                op2 = parse_sum();
121
                op1 = codeBuilder.eq(op1, op2);
122
                break;
123
            case Token.OP_NE:
124
                lexer.next();
125
                op2 = parse_sum();
126
                op1 = codeBuilder.ne(op1, op2);
127
                break;
128
            case Token.PRED_IS: {
129
                    lexer.next();
130
                    Token next = lexer.look();
131
                    if( next.getType() == Token.NOTNULL ) {
132
                        op1 = codeBuilder.is(op1, codeBuilder.constant(null));
133
                        op1 = codeBuilder.not(op1);
134
                    } else {
135
                        op2 = parse_sum();
136
                        op1 = codeBuilder.is(op1, op2);
137
                    }
138
                }
139
                break;
140
            case Token.ISNULL:
141
                lexer.next();
142
                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
143
                break;
144
            case Token.OP_REGEXP:
145
                lexer.next();
146
                op2 = parse_sum();
147
                op1 = codeBuilder.regexp(op1, op2);
148
                break;
149
            case Token.PRED_LIKE:
150
                lexer.next();
151
                op2 = parse_sum();
152
                op1 = codeBuilder.like(op1, op2);
153
                break;
154
            case Token.PRED_ILIKE:
155
                lexer.next();
156
                op2 = parse_sum();
157
                op1 = codeBuilder.ilike(op1, op2);
158
                break;
159
            default:
160
                return op1;
161
            }
162
        }
163
    }
164

    
165
    private Code parse_sum() {
166
        Code op1 = parse_factor();
167
        Code op2;
168
        while( true ) {
169
            Token token = lexer.look();
170
            switch( token.getType() ) {
171
            case Token.OP_ADD:
172
                lexer.next();
173
                op2 = parse_factor();
174
                op1 = codeBuilder.add(op1, op2);
175
                break;
176
            case Token.OP_SUBST:
177
                lexer.next();
178
                op2 = parse_factor();
179
                op1 = codeBuilder.subst(op1, op2);
180
                break;
181
            default:
182
                return op1;
183
            }
184
        }
185
    }
186

    
187
    private Code parse_factor() {
188
        Code op1 = parse_termino();
189
        Code op2;
190
        while( true ) {
191
            Token token = lexer.look();
192
            switch( token.getType() ) {
193
            case Token.OP_MULT:
194
                lexer.next();
195
                op2 = parse_termino();
196
                op1 = codeBuilder.mult(op1, op2);
197
                break;
198
            case Token.OP_DIV:
199
                lexer.next();
200
                op2 = parse_termino();
201
                op1 = codeBuilder.div(op1, op2);
202
                break;
203
            case Token.OP_MOD:
204
                lexer.next();
205
                op2 = parse_termino();
206
                op1 = codeBuilder.mod(op1, op2);
207
                break;
208
            default:
209
                return op1;
210
            }
211
        }
212
    }
213

    
214
    private Code parse_termino() {
215

    
216
        Token token = lexer.look();
217
        switch( token.getType() ) {
218
        case Token.PARENTHESIS_OPEN: {
219
                lexer.next();
220
                Code value = parseExpression();
221
                Token next = lexer.next();
222
                if( next.getType() != Token.PARENTHESIS_CLOSE ) {
223
                    throw new RuntimeException();
224
                }
225
                return value;
226
            }
227
        case Token.IDENTIFIER: {
228
                lexer.next();
229
                String id = (String) token.getLiteral();
230
                Token next = lexer.look();
231
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
232
                    lexer.next();
233
                    Arguments args = parseArgs();
234
                    next = lexer.next();
235
                    if( next.getType() != Token.PARENTHESIS_CLOSE ) {
236
                        throw new RuntimeException("Expected ')'.");
237
                    }
238
                    return codeBuilder.function(id, args);
239
                } else {
240
                    return codeBuilder.identifier(id);
241
                }
242
            }
243
        case Token.STRING_LITERAL:
244
            lexer.next();
245
            return codeBuilder.constant(token.getValue());
246
        case Token.INTEGER_LITERAL:
247
            lexer.next();
248
            return codeBuilder.constant(token.getValue());
249
        case Token.FLOATING_POINT_LITERAL:
250
            lexer.next();
251
            return codeBuilder.constant(token.getValue());
252
        case Token.NULL:
253
            lexer.next();
254
            return codeBuilder.constant(null);
255
        case Token.TRUE:
256
            lexer.next();
257
            return codeBuilder.constant(true);
258
        case Token.FALSE:
259
            lexer.next();
260
            return codeBuilder.constant(false);
261
        }
262
        return null;
263
    }
264

    
265
    private Arguments parseArgs() {
266
        Arguments args = null;
267
        while( true ) {
268
            Code arg = parseExpression();
269
            if( arg!=null ) {
270
                if( args == null ) {
271
                    args = codeBuilder.args();
272
                }
273
                ((DefaultCodeBuilder.BaseArguments)args).add(arg);
274
            }
275
            Token next = lexer.look();
276
            switch( next.getType() ) {
277
            case Token.COMA:
278
                lexer.next(); // Consume el ",".
279
                break;
280
            default:
281
                return args;
282
            }
283
        }
284
    }
285
}