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

History | View | Annotate | Download (28.4 KB)

1 43512 jjdelcerro
package org.gvsig.expressionevaluator.impl;
2
3 44139 jjdelcerro
import java.util.HashMap;
4
import java.util.Map;
5 44750 jjdelcerro
import java.util.Stack;
6 44139 jjdelcerro
import org.apache.commons.lang3.StringUtils;
7 43512 jjdelcerro
import org.gvsig.expressionevaluator.Compiler;
8
import org.gvsig.expressionevaluator.LexicalAnalyzer;
9
import org.gvsig.expressionevaluator.LexicalAnalyzer.Token;
10
import org.gvsig.expressionevaluator.Code;
11 45025 jjdelcerro
import org.gvsig.expressionevaluator.Code.Callable;
12 43512 jjdelcerro
import org.gvsig.expressionevaluator.CodeBuilder;
13 44139 jjdelcerro
import org.gvsig.expressionevaluator.Codes;
14 45025 jjdelcerro
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_DICT;
15 44644 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
16 43983 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionSyntaxException;
17 44139 jjdelcerro
import org.gvsig.expressionevaluator.GrammarSet;
18
import org.gvsig.expressionevaluator.Statement;
19
import org.gvsig.expressionevaluator.Statement.StatementContext;
20
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCodes;
21 44211 jjdelcerro
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseConstant;
22
import org.gvsig.expressionevaluator.impl.function.operator.NegOperator;
23 44379 jjdelcerro
import org.gvsig.expressionevaluator.impl.function.programming.CodeBlockFunction;
24 44738 jjdelcerro
import org.gvsig.expressionevaluator.spi.AbstractLexicalAnalyzer;
25
import org.slf4j.Logger;
26
import org.slf4j.LoggerFactory;
27 43512 jjdelcerro
28
public class DefaultCompiler implements Compiler {
29
30 44738 jjdelcerro
    protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultCompiler.class);
31
32 44139 jjdelcerro
    class DefaultStatementContext implements StatementContext {
33 44750 jjdelcerro
34
        private class State {
35
          public String codeClassifier;
36
          public Map<String,Code> codes;
37 46050 omartinez
          public Object otherValues;
38 44750 jjdelcerro
        }
39
40
        private State state;
41
        private final Stack<State> states;
42 44139 jjdelcerro
43 44750 jjdelcerro
        public DefaultStatementContext() {
44
          this.state = new State();
45
          this.states = new Stack<>();
46
        }
47
48
        @Override
49
        public void save_state() {
50 45153 jjdelcerro
          this.trace("save_state");
51 44750 jjdelcerro
          ((AbstractLexicalAnalyzer)lexer).save_state();
52
          this.states.push(state);
53
        }
54 44139 jjdelcerro
55
        @Override
56 44750 jjdelcerro
        public void restore_state() {
57
          ((AbstractLexicalAnalyzer)lexer).restore_state();
58
          state = this.states.pop();
59 45153 jjdelcerro
          this.trace("restore_state");
60 44750 jjdelcerro
        }
61
62
        @Override
63
        public void drop_state() {
64
          ((AbstractLexicalAnalyzer)lexer).drop_state();
65
          this.states.pop();
66 45153 jjdelcerro
          this.trace("drop_state");
67 44750 jjdelcerro
        }
68
69
        @Override
70 44139 jjdelcerro
        public Compiler getCompiler() {
71
            return DefaultCompiler.this;
72
        }
73
74
        @Override
75
        public LexicalAnalyzer getLexicalAnalyzer() {
76
            return lexer;
77
        }
78
79
        @Override
80
        public void setCode(String id, Code code) {
81 44750 jjdelcerro
            if( this.state.codes == null ) {
82
                this.state.codes = new HashMap<>();
83 44139 jjdelcerro
            }
84 44750 jjdelcerro
            if( !StringUtils.isBlank(this.state.codeClassifier) ) {
85 44139 jjdelcerro
                if( id.contains("#") ) {
86 44750 jjdelcerro
                    id = StringUtils.replace(id,"#",this.state.codeClassifier,1);
87 44139 jjdelcerro
                }
88
            }
89 44750 jjdelcerro
            this.state.codes.put(id.toUpperCase(), code);
90 44139 jjdelcerro
        }
91
92 44379 jjdelcerro
        @Override
93 44139 jjdelcerro
        public Code getCode(String id) {
94 45934 jjdelcerro
            if( this.state==null || this.state.codes==null ) {
95
                return null;
96
            }
97
            if( StringUtils.isBlank(id) ) {
98
                return null;
99
            }
100 44750 jjdelcerro
            return this.state.codes.get(id.toUpperCase());
101 44139 jjdelcerro
        }
102
103
        @Override
104 46050 omartinez
        public void setOtherValues(Object otherValues) {
105
            this.state.otherValues = otherValues;
106
        }
107
108
        @Override
109 44139 jjdelcerro
        public void setCodeClassifier(String classifier) {
110 44750 jjdelcerro
            this.state.codeClassifier = classifier;
111 44139 jjdelcerro
        }
112
113
        @Override
114 46050 omartinez
        public Object getOtherValues() {
115
            return this.state.otherValues;
116
        }
117
118
        @Override
119 44139 jjdelcerro
        public String getCodeClassifier() {
120 44750 jjdelcerro
            return this.state.codeClassifier;
121 44139 jjdelcerro
        }
122
123
        @Override
124
        public CodeBuilder getCodeBuilder() {
125
            return codeBuilder;
126
        }
127
128
        @Override
129
        public Token look_token() {
130
            return lexer.look();
131
        }
132
133
        @Override
134
        public Token next_token() {
135
            return lexer.next();
136
        }
137
138
        @Override
139 45153 jjdelcerro
        public Code parse_expression(boolean allow_assignement) {
140
            return DefaultCompiler.this.parse_expression(allow_assignement);
141 44139 jjdelcerro
        }
142
143
        @Override
144
        public Codes parse_expressions(String separator) {
145
            return DefaultCompiler.this.parse_expressions(separator);
146
        }
147
148 44738 jjdelcerro
        @Override
149 44384 jjdelcerro
        public boolean isReservedWord(String s) {
150
            return grammars.isReservedWord(s);
151
        }
152 44738 jjdelcerro
153
        @Override
154
        public void trace(String msg) {
155 45153 jjdelcerro
//            LexicalAnalyzer lex = this.getLexicalAnalyzer();
156
//            String s = StringUtils.left(lex.getSource(), lex.getPosition()) + "[*]" + StringUtils.mid(lex.getSource(), lex.getPosition(), 200);
157
//            if( s.length()>200 ) {
158
//                s = "..."+StringUtils.mid(s, lex.getPosition()-100, 200)+"...";
159
//            }
160
//            System.out.println(msg+". "+s);
161 44738 jjdelcerro
        }
162 44139 jjdelcerro
    }
163
164 43939 jjdelcerro
    private boolean objectAccessSupported;
165 43512 jjdelcerro
    private LexicalAnalyzer lexer;
166
    private CodeBuilder codeBuilder;
167 44139 jjdelcerro
    private final GrammarSet grammars;
168 44644 jjdelcerro
    protected ExpressionEvaluatorManager manager;
169 43532 jjdelcerro
    //
170
    // https://www.postgresql.org/docs/9.1/static/functions.html
171
    //
172 43512 jjdelcerro
173 44644 jjdelcerro
    public DefaultCompiler(ExpressionEvaluatorManager manager) {
174
        this.manager = manager;
175 44139 jjdelcerro
        this.grammars = new DefaultGrammarSet();
176 43512 jjdelcerro
        this.lexer = new SQLLexicalAnalyzer();
177 44644 jjdelcerro
        this.codeBuilder = new DefaultCodeBuilder(manager);
178 43939 jjdelcerro
        this.objectAccessSupported = true;
179 43512 jjdelcerro
    }
180
181
    @Override
182 43809 jjdelcerro
    public Compiler clone() throws CloneNotSupportedException {
183
        DefaultCompiler other = (DefaultCompiler) super.clone();
184
        other.lexer = lexer.clone();
185
        other.codeBuilder = codeBuilder.clone();
186
187
        return other;
188
    }
189
190
    @Override
191 43512 jjdelcerro
    public void setLexicalAnalyzer(LexicalAnalyzer lexer) {
192
        this.lexer = lexer;
193
    }
194 43983 jjdelcerro
195
    @Override
196
    public LexicalAnalyzer getLexicalAnalyzer() {
197
        return this.lexer;
198
    }
199 43512 jjdelcerro
200
    @Override
201
    public void setCodeBuilder(CodeBuilder codeBuilder) {
202
        this.codeBuilder = codeBuilder;
203
    }
204 43809 jjdelcerro
205 43512 jjdelcerro
    @Override
206 43809 jjdelcerro
    public CodeBuilder getCodeBuilder() {
207
        return this.codeBuilder;
208
    }
209
210
    @Override
211 43939 jjdelcerro
    public boolean isObjectAccessSupported() {
212
        return this.objectAccessSupported;
213
    }
214
215
    @Override
216
    public void setObjectAccessSupported(boolean objectAccessSupported) {
217
        this.objectAccessSupported = objectAccessSupported;
218
    }
219 44139 jjdelcerro
220 43939 jjdelcerro
    @Override
221 44139 jjdelcerro
    public GrammarSet getGrammars() {
222
        return this.grammars;
223
    }
224
225
    @Override
226 43512 jjdelcerro
    public Code compileExpression(String expression) {
227 45950 jjdelcerro
        if( StringUtils.isBlank(expression) ) {
228
            return this.getCodeBuilder().constant(null);
229
        }
230
231 43983 jjdelcerro
        this.lexer.setSource(expression.trim());
232 44139 jjdelcerro
        Code code = parse_expression();
233 43983 jjdelcerro
        if( !this.lexer.isEOF() ) {
234
            throw new ExpressionSyntaxException(lexer);
235
        }
236
        return code;
237 43512 jjdelcerro
    }
238 45153 jjdelcerro
239
    public Code parse_expression() {
240
        return this.parse_expression(true);
241
    }
242 43512 jjdelcerro
243 45153 jjdelcerro
    public Code parse_expression(boolean allow_assignement) {
244 43983 jjdelcerro
        Code code = parse_relational();
245 45153 jjdelcerro
        if( code != null && allow_assignement) {
246
            Token token = lexer.look();
247
            if( token.is("AS") ) {
248
                lexer.next();
249
                token = lexer.look();
250
                if( token.getType() != Token.IDENTIFIER ) {
251
                    throw new ExpressionSyntaxException(
252
                        I18N.An_identifier_was_expected_and_XliteralX_was_found(token.getLiteral()),
253
                        lexer
254
                    );
255
                }
256
                token = lexer.next();
257
                code = codeBuilder.let(token.getLiteral(),code);
258
            }
259
        }
260 43983 jjdelcerro
        return code;
261 43512 jjdelcerro
    }
262
263 44139 jjdelcerro
    public Code parse_relational() {
264 43512 jjdelcerro
        Code op1 = parse_not();
265
        Code op2;
266
        while( true ) {
267
            Token token = lexer.look();
268
            switch( token.getType() ) {
269
            case Token.OP_OR:
270
                lexer.next();
271
                op2 = parse_not();
272 43983 jjdelcerro
                if( op2==null ) {
273 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_OR_operator(),lexer);
274 43983 jjdelcerro
                }
275 43512 jjdelcerro
                op1 = codeBuilder.or(op1, op2);
276
                break;
277
            case Token.OP_AND:
278
                lexer.next();
279
                op2 = parse_not();
280 43983 jjdelcerro
                if( op2==null ) {
281 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_AND_operator(),lexer);
282 43983 jjdelcerro
                }
283 43512 jjdelcerro
                op1 = codeBuilder.and(op1, op2);
284
                break;
285
            default:
286
                return op1;
287
            }
288
        }
289
    }
290
291 44139 jjdelcerro
    public Code parse_not() {
292 43512 jjdelcerro
        Code op1;
293
        Token token = lexer.look();
294
        if( token.getType() == Token.OP_NOT ) {
295
            lexer.next();
296
            op1 = parse_conditional();
297
            op1 = codeBuilder.not(op1);
298
        } else {
299
            op1 = parse_conditional();
300
        }
301
        return op1;
302
    }
303
304 44139 jjdelcerro
    public Code parse_conditional() {
305 43512 jjdelcerro
        Code op1 = parse_sum();
306
        Code op2;
307
        while( true ) {
308
            Token token = lexer.look();
309
            switch( token.getType() ) {
310
            case Token.OP_LT:
311
                lexer.next();
312
                op2 = parse_sum();
313 43983 jjdelcerro
                if( op2==null ) {
314 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LT_operator(),lexer);
315 43983 jjdelcerro
                }
316 43512 jjdelcerro
                op1 = codeBuilder.lt(op1, op2);
317
                break;
318
            case Token.OP_GT:
319
                lexer.next();
320
                op2 = parse_sum();
321 43983 jjdelcerro
                if( op2==null ) {
322 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GT_operator(),lexer);
323 43983 jjdelcerro
                }
324 43512 jjdelcerro
                op1 = codeBuilder.gt(op1, op2);
325
                break;
326
            case Token.OP_LE:
327
                lexer.next();
328
                op2 = parse_sum();
329 43983 jjdelcerro
                if( op2==null ) {
330 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LE_operator(),lexer);
331 43983 jjdelcerro
                }
332 43512 jjdelcerro
                op1 = codeBuilder.le(op1, op2);
333
                break;
334
            case Token.OP_GE:
335
                lexer.next();
336
                op2 = parse_sum();
337 43983 jjdelcerro
                if( op2==null ) {
338 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GE_operator(),lexer);
339 43983 jjdelcerro
                }
340 43512 jjdelcerro
                op1 = codeBuilder.ge(op1, op2);
341
                break;
342
            case Token.OP_EQ:
343
                lexer.next();
344
                op2 = parse_sum();
345 43983 jjdelcerro
                if( op2==null ) {
346 44139 jjdelcerro
                    token = lexer.look();
347
                    String tip = null;
348
                    switch(token.getType()) {
349
                        case Token.OP_GT:
350
                            tip = I18N.The_operator_greater_than_or_equal_is_ge();
351
                            break;
352
                        case Token.OP_LT:
353
                            tip = I18N.The_operator_less_than_or_equal_is_ge();
354
                            break;
355
                    }
356
                    throw new ExpressionSyntaxException(
357
                            I18N.Cant_recognize_the_second_operand_of_EQ_operator(),
358
                            lexer,
359
                            tip
360
                    );
361 43983 jjdelcerro
                }
362 43512 jjdelcerro
                op1 = codeBuilder.eq(op1, op2);
363
                break;
364 43521 jjdelcerro
            case Token.OP_NE:
365 43512 jjdelcerro
                lexer.next();
366 43521 jjdelcerro
                op2 = parse_sum();
367 43983 jjdelcerro
                if( op2==null ) {
368 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_NEQ_operator(),lexer);
369 43983 jjdelcerro
                }
370 43521 jjdelcerro
                op1 = codeBuilder.ne(op1, op2);
371
                break;
372
            case Token.PRED_IS: {
373
                    lexer.next();
374
                    Token next = lexer.look();
375 44361 jjdelcerro
                    switch(next.getType()) {
376
                        case Token.NOTNULL:
377
                            lexer.next();
378
                            op1 = codeBuilder.is(op1, codeBuilder.constant(null));
379
                            op1 = codeBuilder.not(op1);
380
                            break;
381
                        case Token.OP_NOT:
382
                            lexer.next();
383
                            next = lexer.look();
384
                            if( next.getType() == Token.NULL ) {
385
                                lexer.next();
386
                                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
387
                            } else {
388
                                op2 = parse_sum();
389
                                if( op2==null ) {
390
                                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_IS_operator(),lexer);
391
                                }
392
                                op1 = codeBuilder.is(op1, op2);
393
                            }
394
                            op1 = codeBuilder.not(op1);
395
                            break;
396
                        case Token.NULL:
397
                            lexer.next();
398
                            op1 = codeBuilder.is(op1, codeBuilder.constant(null));
399
                            break;
400
                        default:
401
                            op2 = parse_sum();
402
                            if( op2==null ) {
403
                                throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_IS_operator(),lexer);
404
                            }
405
                            op1 = codeBuilder.is(op1, op2);
406 43521 jjdelcerro
                    }
407 43512 jjdelcerro
                }
408 43521 jjdelcerro
                break;
409 43512 jjdelcerro
            case Token.ISNULL:
410
                lexer.next();
411
                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
412
                break;
413 43532 jjdelcerro
            case Token.OP_REGEXP:
414
                lexer.next();
415
                op2 = parse_sum();
416 43983 jjdelcerro
                if( op2==null ) {
417 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_REGEXP_operator(),lexer);
418 43983 jjdelcerro
                }
419 43532 jjdelcerro
                op1 = codeBuilder.regexp(op1, op2);
420
                break;
421 43512 jjdelcerro
            case Token.PRED_LIKE:
422
                lexer.next();
423
                op2 = parse_sum();
424 43983 jjdelcerro
                if( op2==null ) {
425 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LIKE_operator(),lexer);
426 43983 jjdelcerro
                }
427 43512 jjdelcerro
                op1 = codeBuilder.like(op1, op2);
428
                break;
429
            case Token.PRED_ILIKE:
430
                lexer.next();
431
                op2 = parse_sum();
432 43983 jjdelcerro
                if( op2==null ) {
433 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_ILIKE_operator(),lexer);
434 43983 jjdelcerro
                }
435 43512 jjdelcerro
                op1 = codeBuilder.ilike(op1, op2);
436
                break;
437
            default:
438
                return op1;
439
            }
440
        }
441
    }
442
443 44139 jjdelcerro
    public Code parse_sum() {
444 43512 jjdelcerro
        Code op1 = parse_factor();
445
        Code op2;
446
        while( true ) {
447
            Token token = lexer.look();
448
            switch( token.getType() ) {
449 44139 jjdelcerro
            case Token.OP_CONCAT:
450
                lexer.next();
451
                op2 = parse_factor();
452
                op1 = codeBuilder.concat(op1, op2);
453
                break;
454 43512 jjdelcerro
            case Token.OP_ADD:
455
                lexer.next();
456
                op2 = parse_factor();
457
                op1 = codeBuilder.add(op1, op2);
458
                break;
459
            case Token.OP_SUBST:
460
                lexer.next();
461
                op2 = parse_factor();
462
                op1 = codeBuilder.subst(op1, op2);
463
                break;
464
            default:
465
                return op1;
466
            }
467
        }
468
    }
469
470 44139 jjdelcerro
    public Code parse_factor() {
471 43939 jjdelcerro
        Code op1 = parse_getattr();
472 43512 jjdelcerro
        Code op2;
473
        while( true ) {
474
            Token token = lexer.look();
475
            switch( token.getType() ) {
476
            case Token.OP_MULT:
477
                lexer.next();
478 43939 jjdelcerro
                op2 = parse_getattr();
479 43983 jjdelcerro
                if( op2==null ) {
480 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MULT_operator(),lexer);
481 43983 jjdelcerro
                }
482 43512 jjdelcerro
                op1 = codeBuilder.mult(op1, op2);
483
                break;
484
            case Token.OP_DIV:
485
                lexer.next();
486 43939 jjdelcerro
                op2 = parse_getattr();
487 43983 jjdelcerro
                if( op2==null ) {
488 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_DIV_operator(),lexer);
489 43983 jjdelcerro
                }
490 43512 jjdelcerro
                op1 = codeBuilder.div(op1, op2);
491
                break;
492
            case Token.OP_MOD:
493
                lexer.next();
494 43939 jjdelcerro
                op2 = parse_getattr();
495 43983 jjdelcerro
                if( op2==null ) {
496 44098 jjdelcerro
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MOD_operator(),lexer);
497 43983 jjdelcerro
                }
498 43512 jjdelcerro
                op1 = codeBuilder.mod(op1, op2);
499
                break;
500 44139 jjdelcerro
            case Token.OPEN_BRACKET:
501
                lexer.next();
502
                Code codeIndex = parse_expression();
503
                if( codeIndex == null ) {
504
                    throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer);
505
                }
506
                token = lexer.look();
507
                if( token.getType()!=Token.CLOSED_BRACKET) {
508
                    throw new ExpressionSyntaxException(I18N.A_XTokenX_was_expected_and_XliteralX_was_found("]", token.getLiteral()),lexer);
509
                }
510
                lexer.next();
511
                Code code = codeBuilder.getitem(op1, codeIndex);
512
                return code;
513 43512 jjdelcerro
            default:
514
                return op1;
515
            }
516
        }
517
    }
518
519 44139 jjdelcerro
    public Code parse_getattr() {
520 46081 jjdelcerro
        Code op1 = parse_colon();
521 43939 jjdelcerro
        if( !isObjectAccessSupported() ) {
522
            return op1;
523
        }
524
        while( true ) {
525
            Token next = lexer.look();
526
            switch( next.getType() ) {
527
            case Token.OP_GETATTR:
528
                lexer.next();
529
                next = lexer.look();
530
                if( next.getType()!=Token.IDENTIFIER ) {
531 43983 jjdelcerro
                    throw new ExpressionSyntaxException(
532 44098 jjdelcerro
                        I18N.An_attribute_identifier_was_expected_and_XliteralX_was_found(next.getLiteral()),
533
                        lexer
534 43983 jjdelcerro
                    );
535 43939 jjdelcerro
                }
536
                String id = (String) next.getLiteral();
537
                lexer.next();
538
                next = lexer.look();
539
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
540
                    lexer.next();
541 44139 jjdelcerro
                    Codes args = parse_expressions(",");
542 43939 jjdelcerro
                    next = lexer.next();
543
                    if( next.getType() != Token.PARENTHESIS_CLOSE ) {
544 43983 jjdelcerro
                        throw new ExpressionSyntaxException(
545 44098 jjdelcerro
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
546
                            lexer
547 43983 jjdelcerro
                        );
548 43939 jjdelcerro
                    }
549 44379 jjdelcerro
                    op1 = codeBuilder.method(op1, id, args);
550 43939 jjdelcerro
                } else {
551 44379 jjdelcerro
                    op1 = codeBuilder.getattr(op1, id);
552 43939 jjdelcerro
                }
553 44379 jjdelcerro
                break;
554 43939 jjdelcerro
            default:
555
                return op1;
556
            }
557
        }
558
    }
559
560 46081 jjdelcerro
    public Code parse_colon() {
561
        Token token = lexer.look();
562
        if( token.getType() == Token.COLON ) {
563
            // Con esto pretendemos simular el uso de los ":" de SQLJ.
564
            //
565
            // https://docs.oracle.com/cd/A87860_01/doc/java.817/a83723/blangfe3.htm
566
            // Basic Host Expression Syntax
567
            //
568
            // Solo estamos dando soporte al especificador de modo "IN".
569
            lexer.next();
570
            token = lexer.look();
571 46082 jjdelcerro
            String mode_specifier = "IN";
572 46081 jjdelcerro
            if( token.getType() == Token.IDENTIFIER )  {
573
                switch(token.getLiteral().trim().toUpperCase()) {
574
                    case "IN":
575
                        lexer.next();
576 46082 jjdelcerro
                        mode_specifier = "IN";
577 46081 jjdelcerro
                        break;
578
                    case "OUT":
579 46082 jjdelcerro
                        lexer.next();
580
                        mode_specifier = "OUT";
581
                        break;
582 46081 jjdelcerro
                    case "INOUT":
583 46082 jjdelcerro
                        lexer.next();
584
                        mode_specifier = "INOUT";
585
                        break;
586 46081 jjdelcerro
                }
587
            }
588
            Code op = parse_termino();
589 46082 jjdelcerro
            return codeBuilder.$HostExpression(op, mode_specifier);
590 46081 jjdelcerro
        }
591
        return parse_termino();
592
    }
593
594 45132 jjdelcerro
    @SuppressWarnings("UnusedAssignment")
595 44139 jjdelcerro
    public Code parse_termino() {
596 43512 jjdelcerro
597
        Token token = lexer.look();
598
        switch( token.getType() ) {
599
        case Token.PARENTHESIS_OPEN: {
600 43521 jjdelcerro
                lexer.next();
601 44139 jjdelcerro
                Code value = parse_expression();
602 43521 jjdelcerro
                Token next = lexer.next();
603 44098 jjdelcerro
                switch(next.getType()) {
604
                    case Token.PARENTHESIS_CLOSE:
605
                        break;
606
                    case Token.EOF:
607
                        throw new ExpressionSyntaxException(
608
                            I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(),
609
                            lexer
610
                        );
611
                    default:
612
                        throw new ExpressionSyntaxException(
613
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
614
                            lexer
615
                        );
616 43521 jjdelcerro
                }
617
                return value;
618 43512 jjdelcerro
            }
619
        case Token.IDENTIFIER: {
620 44139 jjdelcerro
                Code code = parse_grammars();
621
                if( code!=null ) {
622
                    return code;
623
                }
624
                if( this.grammars.isReservedWord(token.getLiteral()) ) {
625
                    return null;
626
                }
627 43512 jjdelcerro
                lexer.next();
628 43521 jjdelcerro
                String id = (String) token.getLiteral();
629
                Token next = lexer.look();
630
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
631 44750 jjdelcerro
                    next = lexer.next();
632 44738 jjdelcerro
                    Codes args = parse_arguments();
633 43521 jjdelcerro
                    next = lexer.next();
634 44098 jjdelcerro
                    switch(next.getType()) {
635
                        case Token.PARENTHESIS_CLOSE:
636
                            break;
637
                        case Token.EOF:
638
                            throw new ExpressionSyntaxException(
639
                                I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(),
640
                                lexer
641
                            );
642
                        default:
643
                            throw new ExpressionSyntaxException(
644
                                I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
645
                                lexer
646
                            );
647 43521 jjdelcerro
                    }
648 45025 jjdelcerro
                    // Optimizacion para cuando se esta invocando a la funcion dict
649
                    if( StringUtils.equalsIgnoreCase(id, FUNCTION_DICT) && args!=null && args.size()==1 ) {
650
                        code = args.get(0);
651
                        if( code.code()==Code.CALLABLE &&
652
                            StringUtils.equalsIgnoreCase(((Callable)code).name(),FUNCTION_DICT) ) {
653
                            return code;
654
                        }
655
                    }
656 43521 jjdelcerro
                    return codeBuilder.function(id, args);
657
                } else {
658 44379 jjdelcerro
                    if( StringUtils.equalsIgnoreCase(id, "TRUE") ) {
659
                        return codeBuilder.constant(true);
660
                    }
661
                    if( StringUtils.equalsIgnoreCase(id, "FALSE") ) {
662
                        return codeBuilder.constant(false);
663
                    }
664 43521 jjdelcerro
                    return codeBuilder.identifier(id);
665 43512 jjdelcerro
                }
666
            }
667 46081 jjdelcerro
        case Token.STRING_LITERAL:
668 43512 jjdelcerro
            lexer.next();
669
            return codeBuilder.constant(token.getValue());
670
        case Token.INTEGER_LITERAL:
671
            lexer.next();
672
            return codeBuilder.constant(token.getValue());
673
        case Token.FLOATING_POINT_LITERAL:
674
            lexer.next();
675
            return codeBuilder.constant(token.getValue());
676
        case Token.NULL:
677
            lexer.next();
678
            return codeBuilder.constant(null);
679
        case Token.TRUE:
680
            lexer.next();
681
            return codeBuilder.constant(true);
682
        case Token.FALSE:
683
            lexer.next();
684
            return codeBuilder.constant(false);
685 44098 jjdelcerro
        case Token.OP_SUBST:
686
            lexer.next();
687
            Code code = parse_termino();
688 44211 jjdelcerro
            if( code.code()==Code.CONSTANT ) {
689
                BaseConstant c = (BaseConstant)code;
690
                if( c.value() instanceof Number ) {
691
                    c.value(NegOperator.negate((Number) c.value()));
692
                    return code;
693
                }
694 44212 jjdelcerro
                throw new ExpressionSyntaxException(I18N.A_numeric_constant_was_expected_after_the_unary_operator_minus(),lexer);
695 44211 jjdelcerro
            }
696 44098 jjdelcerro
            return codeBuilder.negate(code);
697
        case Token.EOF:
698
            throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer);
699 44139 jjdelcerro
        default:
700
            return parse_grammars();
701 43512 jjdelcerro
        }
702
    }
703
704 44139 jjdelcerro
    public Codes parse_expressions(String sep) {
705
        BaseCodes codes = null;
706 43512 jjdelcerro
        while( true ) {
707 44139 jjdelcerro
            Code code = parse_expression();
708
            if( code!=null ) {
709
                if( codes == null ) {
710
                    codes = (BaseCodes) codeBuilder.args();
711 43519 jjdelcerro
                }
712 44139 jjdelcerro
                codes.add(code);
713 43519 jjdelcerro
            }
714 43512 jjdelcerro
            Token next = lexer.look();
715 44139 jjdelcerro
            String literal = next.getLiteral();
716
            if( literal == null ) {
717
                return codes;
718
            }
719
            literal = literal.trim();
720
            if( sep.equals(literal) ) {
721 43512 jjdelcerro
                lexer.next(); // Consume el ",".
722 44139 jjdelcerro
            } else {
723
                return codes;
724 43512 jjdelcerro
            }
725
        }
726
    }
727 44139 jjdelcerro
728 45025 jjdelcerro
    private String getKeyArgument() {
729
        ((AbstractLexicalAnalyzer)lexer).save_state();
730
        Token next = lexer.look();
731
        if( next.getType()==Token.IDENTIFIER ) {
732
            String key = next.getLiteral();
733
            lexer.next();
734
            next = lexer.next();
735 45132 jjdelcerro
            if( next.is(":","=","=>") ) {
736 45025 jjdelcerro
                ((AbstractLexicalAnalyzer)lexer).drop_state();
737
                return key;
738
            }
739
        }
740
        ((AbstractLexicalAnalyzer)lexer).restore_state();
741
        return null;
742
    }
743
744 44738 jjdelcerro
    public Codes parse_arguments() {
745
        String sep = ",";
746
        BaseCodes codes = null;
747 45025 jjdelcerro
        Map<String,Code> kwargs = null;
748 44738 jjdelcerro
        while( true ) {
749 45025 jjdelcerro
            String key = getKeyArgument();
750
            if( key == null ) {
751
                if( kwargs != null ) {
752
                    throw new ExpressionSyntaxException(I18N.nonkeyword_arg_after_keyword_arg(),lexer);
753 44738 jjdelcerro
                }
754 45025 jjdelcerro
                Code code = parse_expression();
755
                if( code!=null ) {
756
                    if( codes == null ) {
757
                        codes = (BaseCodes) codeBuilder.args();
758
                    }
759
                    codes.add(code);
760
                }
761
            } else {
762
                if( kwargs == null ) {
763
                    kwargs = new HashMap<>();
764
                }
765
                Code code = parse_expression();
766
                kwargs.put(key, code);
767 44738 jjdelcerro
            }
768
            Token next = lexer.look();
769 45025 jjdelcerro
            if( !next.is(sep) ) {
770
                break;
771 44738 jjdelcerro
            }
772 45025 jjdelcerro
            lexer.next(); // Consume el ",".
773
        }
774
        if( kwargs!=null ) {
775
            if( codes == null ) {
776
                codes = (BaseCodes) codeBuilder.args();
777 44738 jjdelcerro
            }
778 45025 jjdelcerro
            Code code = codeBuilder.dict(kwargs);
779
            codes.add(code);
780 44738 jjdelcerro
        }
781 45025 jjdelcerro
        return codes;
782 44738 jjdelcerro
    }
783
784 44139 jjdelcerro
    private Code parse_grammars() {
785
        StatementContext context = new DefaultStatementContext();
786 44379 jjdelcerro
        Code code;
787
        BaseCodes args = (BaseCodes) this.codeBuilder.args();
788 45153 jjdelcerro
        context.trace("compiler.parse_gramars");
789 44139 jjdelcerro
        Statement stmt = this.grammars.getApplicableStatement(context);
790 44379 jjdelcerro
        while( stmt!=null ) {
791
            code = stmt.parse(context);
792
            args.add(code);
793
            stmt = this.grammars.getApplicableStatement(context);
794 44139 jjdelcerro
        }
795 44379 jjdelcerro
        switch(args.size()) {
796
            case 0 :
797
                code = null;
798
                break;
799
            case 1 :
800
                code = args.get(0);
801
                break;
802
            default:
803
                code = this.codeBuilder.function(CodeBlockFunction.NAME, args);
804
                break;
805
        }
806
        return code;
807 44139 jjdelcerro
    }
808 43512 jjdelcerro
}