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

History | View | Annotate | Download (30.8 KB)

1
package org.gvsig.expressionevaluator.impl;
2

    
3
import java.util.HashMap;
4
import java.util.Map;
5
import java.util.Stack;
6
import org.apache.commons.lang3.StringUtils;
7
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
import org.gvsig.expressionevaluator.Code.Callable;
12
import org.gvsig.expressionevaluator.CodeBuilder;
13
import org.gvsig.expressionevaluator.Codes;
14
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_DICT;
15
import org.gvsig.expressionevaluator.ExpressionEvaluatorManager;
16
import org.gvsig.expressionevaluator.ExpressionSyntaxException;
17
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
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseConstant;
22
import org.gvsig.expressionevaluator.impl.function.operator.NegOperator;
23
import org.gvsig.expressionevaluator.impl.function.programming.$HostExpressionFunction;
24
import org.gvsig.expressionevaluator.impl.function.programming.CodeBlockFunction;
25
import org.gvsig.expressionevaluator.spi.AbstractLexicalAnalyzer;
26
import org.slf4j.Logger;
27
import org.slf4j.LoggerFactory;
28

    
29
public class DefaultCompiler implements Compiler {
30

    
31
    protected static final Logger LOGGER = LoggerFactory.getLogger(DefaultCompiler.class);
32
    
33
    class DefaultStatementContext implements StatementContext {
34
      
35
        private class State {
36
          public String codeClassifier;
37
          public Map<String,Code> codes;
38
          public Object otherValues;
39
        }
40
        
41
        private State state;
42
        private final Stack<State> states;
43

    
44
        public DefaultStatementContext() {
45
          this.state = new State();
46
          this.states = new Stack<>();
47
        }
48
        
49
        @Override
50
        public void save_state() {
51
          this.trace("save_state");
52
          ((AbstractLexicalAnalyzer)lexer).save_state();
53
          this.states.push(state);
54
        }
55

    
56
        @Override
57
        public void restore_state() {
58
          ((AbstractLexicalAnalyzer)lexer).restore_state();
59
          state = this.states.pop();
60
          this.trace("restore_state");
61
        }
62

    
63
        @Override
64
        public void drop_state() {
65
          ((AbstractLexicalAnalyzer)lexer).drop_state();
66
          this.states.pop();
67
          this.trace("drop_state");
68
        }
69
        
70
        @Override
71
        public Compiler getCompiler() {
72
            return DefaultCompiler.this;
73
        }
74

    
75
        @Override
76
        public LexicalAnalyzer getLexicalAnalyzer() {
77
            return lexer;
78
        }
79

    
80
        @Override
81
        public void setCode(String id, Code code) {
82
            if( this.state.codes == null ) {
83
                this.state.codes = new HashMap<>();
84
            }
85
            if( !StringUtils.isBlank(this.state.codeClassifier) ) {
86
                if( id.contains("#") ) {
87
                    id = StringUtils.replace(id,"#",this.state.codeClassifier,1);
88
                }
89
            }
90
            this.state.codes.put(id.toUpperCase(), code);
91
        }
92

    
93
        @Override
94
        public Code getCode(String id) {
95
            if( this.state==null || this.state.codes==null ) {
96
                return null;
97
            }
98
            if( StringUtils.isBlank(id) ) {
99
                return null;
100
            }
101
            return this.state.codes.get(id.toUpperCase());
102
        }
103
        
104
        @Override
105
        public void setOtherValues(Object otherValues) {
106
            this.state.otherValues = otherValues;
107
        }
108
        
109
        @Override
110
        public void setCodeClassifier(String classifier) {
111
            this.state.codeClassifier = classifier;
112
        }
113

    
114
        @Override
115
        public Object getOtherValues() {
116
            return this.state.otherValues;
117
        }
118
        
119
        @Override
120
        public String getCodeClassifier() {
121
            return this.state.codeClassifier;
122
        }
123

    
124
        @Override
125
        public CodeBuilder getCodeBuilder() {
126
            return codeBuilder;
127
        }
128

    
129
        @Override
130
        public Token look_token() {
131
            return lexer.look();
132
        }
133

    
134
        @Override
135
        public Token next_token() {
136
            return lexer.next();
137
        }
138

    
139
        @Override
140
        public Code parse_expression(boolean allow_assignement) {
141
            return DefaultCompiler.this.parse_expression(allow_assignement);
142
        }
143

    
144
        @Override
145
        public Codes parse_expressions(String separator) {
146
            return DefaultCompiler.this.parse_expressions(separator);
147
        }
148
        
149
        @Override
150
        public Codes parse_expressions(String separator, String[] terminationTokens) {
151
            return DefaultCompiler.this.parse_expressions(separator, terminationTokens);
152
        }
153
        
154
        @Override
155
        public boolean isReservedWord(String s) {
156
            return grammars.isReservedWord(s);
157
        }
158
        
159
        @Override
160
        public void trace(String msg) {
161
//            LexicalAnalyzer lex = this.getLexicalAnalyzer();
162
//            String s = StringUtils.left(lex.getSource(), lex.getPosition()) + "[*]" + StringUtils.mid(lex.getSource(), lex.getPosition(), 200);
163
//            if( s.length()>200 ) {
164
//                s = "..."+StringUtils.mid(s, lex.getPosition()-100, 200)+"...";
165
//            }            
166
//            System.out.println(msg+". "+s);
167
        } 
168
    }
169

    
170
    private boolean objectAccessSupported;
171
    private LexicalAnalyzer lexer;
172
    private CodeBuilder codeBuilder;
173
    private final GrammarSet grammars;
174
    protected ExpressionEvaluatorManager manager;
175
    protected Map<String,String> compatibility;
176
    //
177
    // https://www.postgresql.org/docs/9.1/static/functions.html
178
    //
179

    
180
    public DefaultCompiler(ExpressionEvaluatorManager manager) {
181
        this.manager = manager;
182
        this.grammars = new DefaultGrammarSet();
183
        this.lexer = new SQLLexicalAnalyzer();
184
        this.codeBuilder = new DefaultCodeBuilder(manager);
185
        this.objectAccessSupported = true;
186
    }
187

    
188
    @Override
189
    public Compiler clone() throws CloneNotSupportedException {
190
        DefaultCompiler other = (DefaultCompiler) super.clone();
191
        other.lexer = lexer.clone();
192
        other.codeBuilder = codeBuilder.clone();
193
        
194
        return other;
195
    }
196

    
197
    @Override
198
    public void setLexicalAnalyzer(LexicalAnalyzer lexer) {
199
        this.lexer = lexer;
200
    }
201

    
202
    @Override
203
    public LexicalAnalyzer getLexicalAnalyzer() {
204
        return this.lexer;
205
    }
206
    
207
    @Override
208
    public void setCodeBuilder(CodeBuilder codeBuilder) {
209
        this.codeBuilder = codeBuilder;
210
    }
211

    
212
    @Override
213
    public CodeBuilder getCodeBuilder() {
214
        return this.codeBuilder;
215
    }
216
    
217
    @Override
218
    public boolean isObjectAccessSupported() {
219
        return this.objectAccessSupported;
220
    }
221

    
222
    @Override
223
    public void setObjectAccessSupported(boolean objectAccessSupported) {
224
        this.objectAccessSupported = objectAccessSupported;
225
    }
226

    
227
    @Override
228
    public GrammarSet getGrammars() {
229
        return this.grammars;
230
    }
231

    
232
    @Override
233
    public Code compileExpression(String expression) {
234
        if( StringUtils.isBlank(expression) ) {
235
            return this.getCodeBuilder().constant(null);
236
        }        
237
        
238
        this.lexer.setSource(expression.trim());
239
        Code code = parse_expression();
240
        if( !this.lexer.isEOF() ) {
241
            throw new ExpressionSyntaxException(lexer);
242
        }
243
        return code;
244
    }
245

    
246
    @Override
247
    public Code compileExpressionQuietly(String expression) {
248
        try {
249
            return this.compileExpression(expression);
250
        } catch(Throwable t) {
251
            return null;
252
        }
253
    }
254

    
255
    public Code parse_expression() {
256
        return this.parse_expression(true);
257
    }
258

    
259
    public Code parse_expression(boolean allow_assignement) {
260
        Code code = parse_relational();
261
        if( code != null && allow_assignement) {
262
            Token token = lexer.look();
263
            if( token.is("AS") ) {
264
                lexer.next();
265
                token = lexer.look();
266
                if( token.getType() != Token.IDENTIFIER ) {
267
                    throw new ExpressionSyntaxException(
268
                        I18N.An_identifier_was_expected_and_XliteralX_was_found(token.getLiteral()),
269
                        lexer
270
                    );                    
271
                }
272
                token = lexer.next();
273
                code = codeBuilder.let(token.getLiteral(),code);
274
            }
275
        }
276
        return code;
277
    }
278

    
279
    public Code parse_relational() {
280
        Code op1 = parse_not();
281
        Code op2;
282
        while( true ) {
283
            Token token = lexer.look();
284
            switch( token.getType() ) {
285
            case Token.OP_OR:
286
                lexer.next();
287
                op2 = parse_not();
288
                if( op2==null ) {
289
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_OR_operator(),lexer);
290
                }
291
                op1 = codeBuilder.or(op1, op2);
292
                break;
293
            case Token.OP_AND:
294
                lexer.next();
295
                op2 = parse_not();
296
                if( op2==null ) {
297
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_AND_operator(),lexer);
298
                }
299
                op1 = codeBuilder.and(op1, op2);
300
                break;
301
            default:
302
                return op1;
303
            }
304
        }
305
    }
306

    
307
    public Code parse_not() {
308
        Code op1;
309
        Token token = lexer.look();
310
        if( token.getType() == Token.OP_NOT ) {
311
            lexer.next();
312
            op1 = parse_conditional();
313
            op1 = codeBuilder.not(op1);
314
        } else {
315
            op1 = parse_conditional();
316
        }
317
        return op1;
318
    }
319

    
320
    public Code parse_conditional() {
321
        Code op1 = parse_sum();
322
        Code op2;
323
        while( true ) {
324
            Token token = lexer.look();
325
            switch( token.getType() ) {
326
            case Token.OP_LT:
327
                lexer.next();
328
                op2 = parse_sum();
329
                if( op2==null ) {
330
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LT_operator(),lexer);
331
                }
332
                op1 = codeBuilder.lt(op1, op2);
333
                break;
334
            case Token.OP_GT:
335
                lexer.next();
336
                op2 = parse_sum();
337
                if( op2==null ) {
338
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GT_operator(),lexer);
339
                }
340
                op1 = codeBuilder.gt(op1, op2);
341
                break;
342
            case Token.OP_LE:
343
                lexer.next();
344
                op2 = parse_sum();
345
                if( op2==null ) {
346
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LE_operator(),lexer);
347
                }
348
                op1 = codeBuilder.le(op1, op2);
349
                break;
350
            case Token.OP_GE:
351
                lexer.next();
352
                op2 = parse_sum();
353
                if( op2==null ) {
354
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GE_operator(),lexer);
355
                }
356
                op1 = codeBuilder.ge(op1, op2);
357
                break;
358
            case Token.OP_EQ:
359
                lexer.next();
360
                op2 = parse_sum();
361
                if( op2==null ) {
362
                    token = lexer.look();
363
                    String tip = null;
364
                    switch(token.getType()) {
365
                        case Token.OP_GT:
366
                            tip = I18N.The_operator_greater_than_or_equal_is_ge();
367
                            break;
368
                        case Token.OP_LT:
369
                            tip = I18N.The_operator_less_than_or_equal_is_ge();
370
                            break;
371
                    }
372
                    throw new ExpressionSyntaxException(
373
                            I18N.Cant_recognize_the_second_operand_of_EQ_operator(),
374
                            lexer,
375
                            tip
376
                    );
377
                }
378
                op1 = codeBuilder.eq(op1, op2);
379
                break;
380
            case Token.OP_NE:
381
                lexer.next();
382
                op2 = parse_sum();
383
                if( op2==null ) {
384
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_NEQ_operator(),lexer);
385
                }
386
                op1 = codeBuilder.ne(op1, op2);
387
                break;
388
            case Token.PRED_IS: {
389
                    lexer.next();
390
                    Token next = lexer.look();
391
                    switch(next.getType()) {
392
                        case Token.NOTNULL:
393
                            lexer.next();
394
                            op1 = codeBuilder.is(op1, codeBuilder.constant(null));
395
                            op1 = codeBuilder.not(op1);
396
                            break;
397
                        case Token.OP_NOT:
398
                            lexer.next();
399
                            next = lexer.look();
400
                            if( next.getType() == Token.NULL ) {
401
                                lexer.next();
402
                                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
403
                            } else {
404
                                  // FIXME: https://www.postgresql.org/docs/current/functions-comparison.html
405
                                  // FIXME: Deberiamos soportar solo las constantes TRUE y FALSE
406
//                                op2 = parse_sum();
407
//                                if( op2==null ) {
408
                                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_IS_operator(),lexer);
409
//                                }
410
//                                op1 = codeBuilder.is(op1, op2);
411
                            }
412
                            op1 = codeBuilder.not(op1);
413
                            break;
414
                        case Token.NULL:
415
                            lexer.next();
416
                            op1 = codeBuilder.is(op1, codeBuilder.constant(null));
417
                            break;
418
                        default:    
419
                            // FIXME: https://www.postgresql.org/docs/current/functions-comparison.html
420
                            // FIXME: Deberiamos soportar solo las constantes TRUE y FALSE
421
//                            op2 = parse_sum();
422
//                            if( op2==null ) {
423
                                throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_IS_operator(),lexer);
424
//                            }
425
//                            op1 = codeBuilder.is(op1, op2);
426
                    }
427
                }
428
                break;
429
            case Token.ISNULL:
430
                lexer.next();
431
                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
432
                break;
433
            case Token.OP_REGEXP:
434
                lexer.next();
435
                op2 = parse_sum();
436
                if( op2==null ) {
437
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_REGEXP_operator(),lexer);
438
                }
439
                op1 = codeBuilder.regexp(op1, op2);
440
                break;
441
            case Token.PRED_LIKE:
442
                lexer.next();
443
                op2 = parse_sum();
444
                if( op2==null ) {
445
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LIKE_operator(),lexer);
446
                }
447
                op1 = codeBuilder.like(op1, op2);
448
                break;
449
            case Token.PRED_ILIKE:
450
                lexer.next();
451
                op2 = parse_sum();
452
                if( op2==null ) {
453
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_ILIKE_operator(),lexer);
454
                }
455
                op1 = codeBuilder.ilike(op1, op2);
456
                break;
457
            default:
458
                return op1;
459
            }
460
        }
461
    }
462

    
463
    public Code parse_sum() {
464
        Code op1 = parse_factor();
465
        Code op2;
466
        while( true ) {
467
            Token token = lexer.look();
468
            switch( token.getType() ) {
469
            case Token.OP_CONCAT:
470
                lexer.next();
471
                op2 = parse_factor();
472
                op1 = codeBuilder.concat(op1, op2);
473
                break;
474
            case Token.OP_ADD:
475
                lexer.next();
476
                op2 = parse_factor();
477
                op1 = codeBuilder.add(op1, op2);
478
                break;
479
            case Token.OP_SUBST:
480
                lexer.next();
481
                op2 = parse_factor();
482
                op1 = codeBuilder.subst(op1, op2);
483
                break;
484
            default:
485
                return op1;
486
            }
487
        }
488
    }
489

    
490
    public Code parse_factor() {
491
        Code op1 = parse_getattr();
492
        Code op2;
493
        while( true ) {
494
            Token token = lexer.look();
495
            switch( token.getType() ) {
496
            case Token.OP_MULT:
497
                lexer.next();
498
                op2 = parse_getattr();
499
                if( op2==null ) {
500
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MULT_operator(),lexer);
501
                }
502
                op1 = codeBuilder.mult(op1, op2);
503
                break;
504
            case Token.OP_DIV:
505
                lexer.next();
506
                op2 = parse_getattr();
507
                if( op2==null ) {
508
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_DIV_operator(),lexer);
509
                }
510
                op1 = codeBuilder.div(op1, op2);
511
                break;
512
            case Token.OP_MOD:
513
                lexer.next();
514
                op2 = parse_getattr();
515
                if( op2==null ) {
516
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MOD_operator(),lexer);
517
                }
518
                op1 = codeBuilder.mod(op1, op2);
519
                break;
520
            case Token.OPEN_BRACKET:
521
                lexer.next();
522
                Code codeIndex = parse_expression();
523
                if( codeIndex == null ) {
524
                    throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer);
525
                }
526
                token = lexer.look();
527
                if( token.getType()!=Token.CLOSED_BRACKET) {
528
                    throw new ExpressionSyntaxException(I18N.A_XTokenX_was_expected_and_XliteralX_was_found("]", token.getLiteral()),lexer);
529
                }
530
                lexer.next();
531
                Code code = codeBuilder.getitem(op1, codeIndex);
532
                return code;
533
            default:
534
                return op1;
535
            }
536
        }
537
    }
538

    
539
    public Code parse_getattr() {
540
        Code op1 = parse_colon();
541
        if( !isObjectAccessSupported() ) {
542
            return op1;
543
        }
544
        while( true ) {
545
            Token next = lexer.look();
546
            switch( next.getType() ) {
547
            case Token.OP_GETATTR:
548
                lexer.next();
549
                next = lexer.look();
550
                if( next.getType()!=Token.IDENTIFIER ) {
551
                    throw new ExpressionSyntaxException(
552
                        I18N.An_attribute_identifier_was_expected_and_XliteralX_was_found(next.getLiteral()),
553
                        lexer
554
                    );
555
                }
556
                String id = (String) next.getLiteral();
557
                lexer.next();
558
                next = lexer.look();
559
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
560
                    lexer.next();
561
                    Codes args = parse_expressions(",");
562
                    next = lexer.next();
563
                    if( next.getType() != Token.PARENTHESIS_CLOSE ) {
564
                        throw new ExpressionSyntaxException(
565
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
566
                            lexer
567
                        );
568
                    }
569
                    op1 = codeBuilder.method(op1, id, args);
570
                } else {
571
                    op1 = codeBuilder.getattr(op1, id);
572
                }
573
                break;
574
            default:
575
                return op1;
576
            }
577
        }
578
    }    
579

    
580
    public Code parse_colon() { 
581
        Token token = lexer.look();
582
        if( token.getType() == Token.COLON ) {
583
            // Con esto pretendemos simular el uso de los ":" de SQLJ.
584
            // 
585
            // https://docs.oracle.com/cd/A87860_01/doc/java.817/a83723/blangfe3.htm
586
            // Basic Host Expression Syntax
587
            //
588
            // Solo estamos dando soporte al especificador de modo "IN".
589
            lexer.next();
590
            token = lexer.look();
591
            String mode_specifier = null;
592
            if( token.getType() == Token.IDENTIFIER )  {
593
                switch(token.getLiteral().trim().toUpperCase()) {
594
                    case $HostExpressionFunction.MODE_SPECIFIER_IN:
595
                        lexer.next();
596
                        mode_specifier = $HostExpressionFunction.MODE_SPECIFIER_IN;
597
                        break;
598
                    case $HostExpressionFunction.MODE_SPECIFIER_OUT:
599
                        lexer.next();
600
                        mode_specifier = $HostExpressionFunction.MODE_SPECIFIER_OUT;
601
                        break;
602
                    case $HostExpressionFunction.MODE_SPECIFIER_INOUT:
603
                        lexer.next();
604
                        mode_specifier = $HostExpressionFunction.MODE_SPECIFIER_INOUT;
605
                        break;
606
                    case $HostExpressionFunction.MODE_SPECIFIER_ID:
607
                        lexer.next();
608
                        mode_specifier = $HostExpressionFunction.MODE_SPECIFIER_ID;
609
                        break;
610
                }
611
            }
612
            Code op = parse_termino();
613
            if( mode_specifier == null ) {
614
                return codeBuilder.$HostExpression(op);
615
            } 
616
            return codeBuilder.$HostExpression(op, mode_specifier);
617
        }
618
        return parse_termino();
619
    }
620
    
621
    @SuppressWarnings("UnusedAssignment")
622
    public Code parse_termino() {
623

    
624
        Token token = lexer.look();
625
        switch( token.getType() ) {
626
        case Token.PARENTHESIS_OPEN: {
627
                lexer.next();
628
                Code value = parse_expression();
629
                Token next = lexer.next();
630
                switch(next.getType()) {
631
                    case Token.PARENTHESIS_CLOSE:
632
                        break;
633
                    case Token.EOF:
634
                        throw new ExpressionSyntaxException(
635
                            I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(),
636
                            lexer
637
                        );
638
                    default:
639
                        throw new ExpressionSyntaxException(
640
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
641
                            lexer
642
                        );
643
                }
644
                return value;
645
            }
646
        case Token.IDENTIFIER: {
647
                Code code = parse_grammars();
648
                if( code!=null ) {
649
                    return code;
650
                }
651
                if( this.grammars.isReservedWord(token.getLiteral()) ) {
652
                    return null;
653
                }
654
                lexer.next();
655
                String id = (String) token.getLiteral();
656
                Token next = lexer.look();
657
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
658
                    next = lexer.next();
659
                    Codes args = parse_arguments();
660
                    next = lexer.next();
661
                    switch(next.getType()) {
662
                        case Token.PARENTHESIS_CLOSE:
663
                            break;
664
                        case Token.EOF:
665
                            throw new ExpressionSyntaxException(
666
                                I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(),
667
                                lexer
668
                            );
669
                        default:
670
                            throw new ExpressionSyntaxException(
671
                                I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
672
                                lexer
673
                            );
674
                    }
675
                    // Optimizacion para cuando se esta invocando a la funcion dict
676
                    if( StringUtils.equalsIgnoreCase(id, FUNCTION_DICT) && args!=null && args.size()==1 ) {
677
                        code = args.get(0);
678
                        if( code.code()==Code.CALLABLE && 
679
                            StringUtils.equalsIgnoreCase(((Callable)code).name(),FUNCTION_DICT) ) {
680
                            return code;
681
                        }
682
                    }
683
                    return codeBuilder.function(id, args);
684
                } else {
685
                    if( StringUtils.equalsIgnoreCase(id, "TRUE") ) {
686
                        return codeBuilder.constant(true);
687
                    }
688
                    if( StringUtils.equalsIgnoreCase(id, "FALSE") ) {
689
                        return codeBuilder.constant(false);
690
                    }
691
                    return codeBuilder.identifier(id);
692
                }
693
            }
694
        case Token.STRING_LITERAL: 
695
            lexer.next();
696
            return codeBuilder.constant(token.getValue());
697
        case Token.INTEGER_LITERAL:
698
            lexer.next();
699
            return codeBuilder.constant(token.getValue());
700
        case Token.FLOATING_POINT_LITERAL:
701
            lexer.next();
702
            return codeBuilder.constant(token.getValue());
703
        case Token.NULL:
704
            lexer.next();
705
            return codeBuilder.constant(null);
706
        case Token.TRUE:
707
            lexer.next();
708
            return codeBuilder.constant(true);
709
        case Token.FALSE:
710
            lexer.next();
711
            return codeBuilder.constant(false);
712
        case Token.OP_SUBST:
713
            lexer.next();
714
            Code code = parse_termino();
715
            if( code.code()==Code.CONSTANT ) {
716
                BaseConstant c = (BaseConstant)code;
717
                if( c.value() instanceof Number ) {
718
                    c.value(NegOperator.negate((Number) c.value()));
719
                    return code;
720
                }
721
                throw new ExpressionSyntaxException(I18N.A_numeric_constant_was_expected_after_the_unary_operator_minus(),lexer);
722
            }
723
            return codeBuilder.negate(code);
724
        case Token.EOF:
725
            throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer);
726
        default:
727
            return parse_grammars();
728
        }
729
    }
730

    
731
    public Codes parse_expressions(String sep) {
732
        return parse_expressions(sep, null);
733
    }
734
    
735
    public Codes parse_expressions(String sep, String[] terminationTokens) {
736
        BaseCodes codes = null;
737
        while( true ) {
738
            if( terminationTokens != null ) {
739
                Token next = lexer.look();
740
                String literal = next.getLiteral();
741
                if( literal == null ) {
742
                    return codes;
743
                }
744
                if( StringUtils.containsAny(literal, terminationTokens) ) {
745
                    return codes;
746
                }
747
            }
748
            Code code = parse_expression();
749
            if( code!=null ) {
750
                if( codes == null ) {
751
                    codes = (BaseCodes) codeBuilder.args();
752
                }
753
                codes.add(code);
754
            }
755
            Token next = lexer.look();
756
            String literal = next.getLiteral();
757
            if( literal == null ) {
758
                return codes;
759
            }
760
            literal = literal.trim();
761
            if( sep.equals(literal) ) {
762
                lexer.next(); // Consume el ",".
763
            } else {
764
                return codes;
765
            }
766
        }
767
    }
768

    
769
    private String getKeyArgument() {
770
        ((AbstractLexicalAnalyzer)lexer).save_state();
771
        Token next = lexer.look();
772
        if( next.getType()==Token.IDENTIFIER ) {
773
            String key = next.getLiteral();
774
            lexer.next(); 
775
            next = lexer.next();
776
            if( next.is(":","=","=>") ) {
777
                ((AbstractLexicalAnalyzer)lexer).drop_state();
778
                return key;
779
            }
780
        }
781
        ((AbstractLexicalAnalyzer)lexer).restore_state();
782
        return null;
783
    }
784
    
785
    public Codes parse_arguments() {
786
        String sep = ",";
787
        BaseCodes codes = null;
788
        Map<String,Code> kwargs = null;
789
        while( true ) {
790
            String key = getKeyArgument();
791
            if( key == null ) {
792
                if( kwargs != null ) {
793
                    throw new ExpressionSyntaxException(I18N.nonkeyword_arg_after_keyword_arg(),lexer);
794
                }
795
                Code code = parse_expression();
796
                if( code!=null ) {
797
                    if( codes == null ) {
798
                        codes = (BaseCodes) codeBuilder.args();
799
                    }
800
                    codes.add(code);
801
                }
802
            } else {
803
                if( kwargs == null ) {
804
                    kwargs = new HashMap<>();
805
                }
806
                Code code = parse_expression();
807
                kwargs.put(key, code);
808
            }
809
            Token next = lexer.look();
810
            if( !next.is(sep) ) {
811
                break;
812
            }
813
            lexer.next(); // Consume el ",".
814
        }
815
        if( kwargs!=null ) {
816
            if( codes == null ) {
817
                codes = (BaseCodes) codeBuilder.args();
818
            }
819
            Code code = codeBuilder.dict(kwargs);
820
            codes.add(code);
821
        }
822
        return codes;
823
    }
824

    
825
    private Code parse_grammars() {
826
        StatementContext context = new DefaultStatementContext();
827
        Code code;
828
        BaseCodes args = (BaseCodes) this.codeBuilder.args();
829
        context.trace("compiler.parse_gramars");
830
        Statement stmt = this.grammars.getApplicableStatement(context);
831
        while( stmt!=null ) {
832
            code = stmt.parse(context);
833
            args.add(code);
834
            stmt = this.grammars.getApplicableStatement(context);
835
        }
836
        switch(args.size()) {
837
            case 0 :
838
                code = null;
839
                break;
840
            case 1 :
841
                code = args.get(0);
842
                break;
843
            default:
844
                code = this.codeBuilder.function(CodeBlockFunction.NAME, args);
845
                break;
846
        }
847
        return code;
848
    }
849

    
850
    @Override
851
    public void addCompatibility(String compatid, String value) {
852
        if( this.compatibility == null ) {
853
            this.compatibility = new HashMap<>();
854
        }
855
        this.compatibility.put(compatid, value);
856
    }
857

    
858
    @Override
859
    public String getCompatibility(String compatid) {
860
        if( this.compatibility == null ) {
861
            return null;
862
        }
863
        return this.compatibility.get(compatid);
864
    }
865
    
866
}