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

History | View | Annotate | Download (7.91 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
    public DefaultCompiler() {
16
        this.lexer = new SQLLexicalAnalyzer();
17
        this.codeBuilder = new DefaultCodeBuilder();
18
    }
19

    
20
    @Override
21
    public void setLexicalAnalyzer(LexicalAnalyzer lexer) {
22
        this.lexer = lexer;
23
    }
24
    
25
    @Override
26
    public void setCodeBuilder(CodeBuilder codeBuilder) {
27
        this.codeBuilder = codeBuilder;
28
    }
29
    @Override
30
    public Code compileExpression(String expression) {
31
        this.lexer.setSource(expression);
32
        return parseExpression();
33
    }
34

    
35
    private Code parseExpression() {
36
        return parse_relational();
37
    }
38

    
39
    private Code parse_relational() {
40
        Code op1 = parse_not();
41
        Code op2;
42
        while( true ) {
43
            Token token = lexer.look();
44
            switch( token.getType() ) {
45
            case Token.OP_OR:
46
                lexer.next();
47
                op2 = parse_not();
48
                op1 = codeBuilder.or(op1, op2);
49
                break;
50
            case Token.OP_AND:
51
                lexer.next();
52
                op2 = parse_not();
53
                op1 = codeBuilder.and(op1, op2);
54
                break;
55
            default:
56
                return op1;
57
            }
58
        }
59
    }
60

    
61
    private Code parse_not() {
62
        Code op1;
63
        Token token = lexer.look();
64
        if( token.getType() == Token.OP_NOT ) {
65
            lexer.next();
66
            op1 = parse_conditional();
67
            op1 = codeBuilder.not(op1);
68
        } else {
69
            op1 = parse_conditional();
70
        }
71
        return op1;
72
    }
73

    
74
    private Code parse_conditional() {
75
        Code op1 = parse_sum();
76
        Code op2;
77
        while( true ) {
78
            Token token = lexer.look();
79
            switch( token.getType() ) {
80
            case Token.OP_LT:
81
                lexer.next();
82
                op2 = parse_sum();
83
                op1 = codeBuilder.lt(op1, op2);
84
                break;
85
            case Token.OP_GT:
86
                lexer.next();
87
                op2 = parse_sum();
88
                op1 = codeBuilder.gt(op1, op2);
89
                break;
90
            case Token.OP_LE:
91
                lexer.next();
92
                op2 = parse_sum();
93
                op1 = codeBuilder.le(op1, op2);
94
                break;
95
            case Token.OP_GE:
96
                lexer.next();
97
                op2 = parse_sum();
98
                op1 = codeBuilder.ge(op1, op2);
99
                break;
100
            case Token.OP_EQ:
101
                lexer.next();
102
                op2 = parse_sum();
103
                op1 = codeBuilder.eq(op1, op2);
104
                break;
105
            case Token.OP_NE:
106
                lexer.next();
107
                op2 = parse_sum();
108
                op1 = codeBuilder.ne(op1, op2);
109
                break;
110
            case Token.PRED_IS: {
111
                    lexer.next();
112
                    Token next = lexer.look();
113
                    if( next.getType() == Token.NOTNULL ) {
114
                        op1 = codeBuilder.is(op1, codeBuilder.constant(null));
115
                        op1 = codeBuilder.not(op1);
116
                    } else {
117
                        op2 = parse_sum();
118
                        op1 = codeBuilder.is(op1, op2);
119
                    }
120
                }
121
                break;
122
            case Token.ISNULL:
123
                lexer.next();
124
                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
125
                break;
126
            case Token.PRED_LIKE:
127
                lexer.next();
128
                op2 = parse_sum();
129
                op1 = codeBuilder.like(op1, op2);
130
                break;
131
            case Token.PRED_ILIKE:
132
                lexer.next();
133
                op2 = parse_sum();
134
                op1 = codeBuilder.ilike(op1, op2);
135
                break;
136
            default:
137
                return op1;
138
            }
139
        }
140
    }
141

    
142
    private Code parse_sum() {
143
        Code op1 = parse_factor();
144
        Code op2;
145
        while( true ) {
146
            Token token = lexer.look();
147
            switch( token.getType() ) {
148
            case Token.OP_ADD:
149
                lexer.next();
150
                op2 = parse_factor();
151
                op1 = codeBuilder.add(op1, op2);
152
                break;
153
            case Token.OP_SUBST:
154
                lexer.next();
155
                op2 = parse_factor();
156
                op1 = codeBuilder.subst(op1, op2);
157
                break;
158
            default:
159
                return op1;
160
            }
161
        }
162
    }
163

    
164
    private Code parse_factor() {
165
        Code op1 = parse_termino();
166
        Code op2;
167
        while( true ) {
168
            Token token = lexer.look();
169
            switch( token.getType() ) {
170
            case Token.OP_MULT:
171
                lexer.next();
172
                op2 = parse_termino();
173
                op1 = codeBuilder.mult(op1, op2);
174
                break;
175
            case Token.OP_DIV:
176
                lexer.next();
177
                op2 = parse_termino();
178
                op1 = codeBuilder.div(op1, op2);
179
                break;
180
            case Token.OP_MOD:
181
                lexer.next();
182
                op2 = parse_termino();
183
                op1 = codeBuilder.mod(op1, op2);
184
                break;
185
            default:
186
                return op1;
187
            }
188
        }
189
    }
190

    
191
    private Code parse_termino() {
192

    
193
        Token token = lexer.look();
194
        switch( token.getType() ) {
195
        case Token.PARENTHESIS_OPEN: {
196
                lexer.next();
197
                Code value = parseExpression();
198
                Token next = lexer.next();
199
                if( next.getType() != Token.PARENTHESIS_CLOSE ) {
200
                    throw new RuntimeException();
201
                }
202
                return value;
203
            }
204
        case Token.IDENTIFIER: {
205
                lexer.next();
206
                String id = (String) token.getLiteral();
207
                Token next = lexer.look();
208
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
209
                    lexer.next();
210
                    Arguments args = parseArgs();
211
                    next = lexer.next();
212
                    if( next.getType() != Token.PARENTHESIS_CLOSE ) {
213
                        throw new RuntimeException("Expected ')'.");
214
                    }
215
                    return codeBuilder.function(id, args);
216
                } else {
217
                    return codeBuilder.identifier(id);
218
                }
219
            }
220
        case Token.STRING_LITERAL:
221
            lexer.next();
222
            return codeBuilder.constant(token.getValue());
223
        case Token.INTEGER_LITERAL:
224
            lexer.next();
225
            return codeBuilder.constant(token.getValue());
226
        case Token.FLOATING_POINT_LITERAL:
227
            lexer.next();
228
            return codeBuilder.constant(token.getValue());
229
        case Token.NULL:
230
            lexer.next();
231
            return codeBuilder.constant(null);
232
        case Token.TRUE:
233
            lexer.next();
234
            return codeBuilder.constant(true);
235
        case Token.FALSE:
236
            lexer.next();
237
            return codeBuilder.constant(false);
238
        }
239
        return null;
240
    }
241

    
242
    private Arguments parseArgs() {
243
        Arguments args = null;
244
        while( true ) {
245
            Code arg = parseExpression();
246
            if( arg!=null ) {
247
                if( args == null ) {
248
                    args = codeBuilder.args();
249
                }
250
                args.add(arg);
251
            }
252
            Token next = lexer.look();
253
            switch( next.getType() ) {
254
            case Token.COMA:
255
                lexer.next(); // Consume el ",".
256
                break;
257
            default:
258
                return args;
259
            }
260
        }
261
    }
262
}