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

History | View | Annotate | Download (7.78 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
    
30
    @Override
31
    public Code compileExpression(String expression) {
32
        this.lexer.setSource(expression);
33
        return parseExpression();
34
    }
35

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

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

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

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

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

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

    
192
    private Code parse_termino() {
193

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

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