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
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.CodeBlockFunction;
24
import org.gvsig.expressionevaluator.spi.AbstractLexicalAnalyzer;
25
import org.slf4j.Logger;
26
import org.slf4j.LoggerFactory;
27

    
28
public class DefaultCompiler implements Compiler {
29

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

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

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

    
62
        @Override
63
        public void drop_state() {
64
          ((AbstractLexicalAnalyzer)lexer).drop_state();
65
          this.states.pop();
66
          this.trace("drop_state");
67
        }
68
        
69
        @Override
70
        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
            if( this.state.codes == null ) {
82
                this.state.codes = new HashMap<>();
83
            }
84
            if( !StringUtils.isBlank(this.state.codeClassifier) ) {
85
                if( id.contains("#") ) {
86
                    id = StringUtils.replace(id,"#",this.state.codeClassifier,1);
87
                }
88
            }
89
            this.state.codes.put(id.toUpperCase(), code);
90
        }
91

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

    
113
        @Override
114
        public Object getOtherValues() {
115
            return this.state.otherValues;
116
        }
117
        
118
        @Override
119
        public String getCodeClassifier() {
120
            return this.state.codeClassifier;
121
        }
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
        public Code parse_expression(boolean allow_assignement) {
140
            return DefaultCompiler.this.parse_expression(allow_assignement);
141
        }
142

    
143
        @Override
144
        public Codes parse_expressions(String separator) {
145
            return DefaultCompiler.this.parse_expressions(separator);
146
        }
147
        
148
        @Override
149
        public boolean isReservedWord(String s) {
150
            return grammars.isReservedWord(s);
151
        }
152
        
153
        @Override
154
        public void trace(String msg) {
155
//            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
        } 
162
    }
163

    
164
    private boolean objectAccessSupported;
165
    private LexicalAnalyzer lexer;
166
    private CodeBuilder codeBuilder;
167
    private final GrammarSet grammars;
168
    protected ExpressionEvaluatorManager manager;
169
    //
170
    // https://www.postgresql.org/docs/9.1/static/functions.html
171
    //
172

    
173
    public DefaultCompiler(ExpressionEvaluatorManager manager) {
174
        this.manager = manager;
175
        this.grammars = new DefaultGrammarSet();
176
        this.lexer = new SQLLexicalAnalyzer();
177
        this.codeBuilder = new DefaultCodeBuilder(manager);
178
        this.objectAccessSupported = true;
179
    }
180

    
181
    @Override
182
    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
    public void setLexicalAnalyzer(LexicalAnalyzer lexer) {
192
        this.lexer = lexer;
193
    }
194

    
195
    @Override
196
    public LexicalAnalyzer getLexicalAnalyzer() {
197
        return this.lexer;
198
    }
199
    
200
    @Override
201
    public void setCodeBuilder(CodeBuilder codeBuilder) {
202
        this.codeBuilder = codeBuilder;
203
    }
204

    
205
    @Override
206
    public CodeBuilder getCodeBuilder() {
207
        return this.codeBuilder;
208
    }
209
    
210
    @Override
211
    public boolean isObjectAccessSupported() {
212
        return this.objectAccessSupported;
213
    }
214

    
215
    @Override
216
    public void setObjectAccessSupported(boolean objectAccessSupported) {
217
        this.objectAccessSupported = objectAccessSupported;
218
    }
219

    
220
    @Override
221
    public GrammarSet getGrammars() {
222
        return this.grammars;
223
    }
224

    
225
    @Override
226
    public Code compileExpression(String expression) {
227
        if( StringUtils.isBlank(expression) ) {
228
            return this.getCodeBuilder().constant(null);
229
        }        
230
        
231
        this.lexer.setSource(expression.trim());
232
        Code code = parse_expression();
233
        if( !this.lexer.isEOF() ) {
234
            throw new ExpressionSyntaxException(lexer);
235
        }
236
        return code;
237
    }
238
    
239
    public Code parse_expression() {
240
        return this.parse_expression(true);
241
    }
242

    
243
    public Code parse_expression(boolean allow_assignement) {
244
        Code code = parse_relational();
245
        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
        return code;
261
    }
262

    
263
    public Code parse_relational() {
264
        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
                if( op2==null ) {
273
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_OR_operator(),lexer);
274
                }
275
                op1 = codeBuilder.or(op1, op2);
276
                break;
277
            case Token.OP_AND:
278
                lexer.next();
279
                op2 = parse_not();
280
                if( op2==null ) {
281
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_AND_operator(),lexer);
282
                }
283
                op1 = codeBuilder.and(op1, op2);
284
                break;
285
            default:
286
                return op1;
287
            }
288
        }
289
    }
290

    
291
    public Code parse_not() {
292
        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
    public Code parse_conditional() {
305
        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
                if( op2==null ) {
314
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LT_operator(),lexer);
315
                }
316
                op1 = codeBuilder.lt(op1, op2);
317
                break;
318
            case Token.OP_GT:
319
                lexer.next();
320
                op2 = parse_sum();
321
                if( op2==null ) {
322
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GT_operator(),lexer);
323
                }
324
                op1 = codeBuilder.gt(op1, op2);
325
                break;
326
            case Token.OP_LE:
327
                lexer.next();
328
                op2 = parse_sum();
329
                if( op2==null ) {
330
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LE_operator(),lexer);
331
                }
332
                op1 = codeBuilder.le(op1, op2);
333
                break;
334
            case Token.OP_GE:
335
                lexer.next();
336
                op2 = parse_sum();
337
                if( op2==null ) {
338
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GE_operator(),lexer);
339
                }
340
                op1 = codeBuilder.ge(op1, op2);
341
                break;
342
            case Token.OP_EQ:
343
                lexer.next();
344
                op2 = parse_sum();
345
                if( op2==null ) {
346
                    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
                }
362
                op1 = codeBuilder.eq(op1, op2);
363
                break;
364
            case Token.OP_NE:
365
                lexer.next();
366
                op2 = parse_sum();
367
                if( op2==null ) {
368
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_NEQ_operator(),lexer);
369
                }
370
                op1 = codeBuilder.ne(op1, op2);
371
                break;
372
            case Token.PRED_IS: {
373
                    lexer.next();
374
                    Token next = lexer.look();
375
                    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
                    }
407
                }
408
                break;
409
            case Token.ISNULL:
410
                lexer.next();
411
                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
412
                break;
413
            case Token.OP_REGEXP:
414
                lexer.next();
415
                op2 = parse_sum();
416
                if( op2==null ) {
417
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_REGEXP_operator(),lexer);
418
                }
419
                op1 = codeBuilder.regexp(op1, op2);
420
                break;
421
            case Token.PRED_LIKE:
422
                lexer.next();
423
                op2 = parse_sum();
424
                if( op2==null ) {
425
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LIKE_operator(),lexer);
426
                }
427
                op1 = codeBuilder.like(op1, op2);
428
                break;
429
            case Token.PRED_ILIKE:
430
                lexer.next();
431
                op2 = parse_sum();
432
                if( op2==null ) {
433
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_ILIKE_operator(),lexer);
434
                }
435
                op1 = codeBuilder.ilike(op1, op2);
436
                break;
437
            default:
438
                return op1;
439
            }
440
        }
441
    }
442

    
443
    public Code parse_sum() {
444
        Code op1 = parse_factor();
445
        Code op2;
446
        while( true ) {
447
            Token token = lexer.look();
448
            switch( token.getType() ) {
449
            case Token.OP_CONCAT:
450
                lexer.next();
451
                op2 = parse_factor();
452
                op1 = codeBuilder.concat(op1, op2);
453
                break;
454
            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
    public Code parse_factor() {
471
        Code op1 = parse_getattr();
472
        Code op2;
473
        while( true ) {
474
            Token token = lexer.look();
475
            switch( token.getType() ) {
476
            case Token.OP_MULT:
477
                lexer.next();
478
                op2 = parse_getattr();
479
                if( op2==null ) {
480
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MULT_operator(),lexer);
481
                }
482
                op1 = codeBuilder.mult(op1, op2);
483
                break;
484
            case Token.OP_DIV:
485
                lexer.next();
486
                op2 = parse_getattr();
487
                if( op2==null ) {
488
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_DIV_operator(),lexer);
489
                }
490
                op1 = codeBuilder.div(op1, op2);
491
                break;
492
            case Token.OP_MOD:
493
                lexer.next();
494
                op2 = parse_getattr();
495
                if( op2==null ) {
496
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MOD_operator(),lexer);
497
                }
498
                op1 = codeBuilder.mod(op1, op2);
499
                break;
500
            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
            default:
514
                return op1;
515
            }
516
        }
517
    }
518

    
519
    public Code parse_getattr() {
520
        Code op1 = parse_colon();
521
        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
                    throw new ExpressionSyntaxException(
532
                        I18N.An_attribute_identifier_was_expected_and_XliteralX_was_found(next.getLiteral()),
533
                        lexer
534
                    );
535
                }
536
                String id = (String) next.getLiteral();
537
                lexer.next();
538
                next = lexer.look();
539
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
540
                    lexer.next();
541
                    Codes args = parse_expressions(",");
542
                    next = lexer.next();
543
                    if( next.getType() != Token.PARENTHESIS_CLOSE ) {
544
                        throw new ExpressionSyntaxException(
545
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
546
                            lexer
547
                        );
548
                    }
549
                    op1 = codeBuilder.method(op1, id, args);
550
                } else {
551
                    op1 = codeBuilder.getattr(op1, id);
552
                }
553
                break;
554
            default:
555
                return op1;
556
            }
557
        }
558
    }    
559

    
560
    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
            String mode_specifier = "IN";
572
            if( token.getType() == Token.IDENTIFIER )  {
573
                switch(token.getLiteral().trim().toUpperCase()) {
574
                    case "IN":
575
                        lexer.next();
576
                        mode_specifier = "IN";
577
                        break;
578
                    case "OUT":
579
                        lexer.next();
580
                        mode_specifier = "OUT";
581
                        break;
582
                    case "INOUT":
583
                        lexer.next();
584
                        mode_specifier = "INOUT";
585
                        break;
586
                }
587
            }
588
            Code op = parse_termino();
589
            return codeBuilder.$HostExpression(op, mode_specifier);
590
        }
591
        return parse_termino();
592
    }
593
    
594
    @SuppressWarnings("UnusedAssignment")
595
    public Code parse_termino() {
596

    
597
        Token token = lexer.look();
598
        switch( token.getType() ) {
599
        case Token.PARENTHESIS_OPEN: {
600
                lexer.next();
601
                Code value = parse_expression();
602
                Token next = lexer.next();
603
                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
                }
617
                return value;
618
            }
619
        case Token.IDENTIFIER: {
620
                Code code = parse_grammars();
621
                if( code!=null ) {
622
                    return code;
623
                }
624
                if( this.grammars.isReservedWord(token.getLiteral()) ) {
625
                    return null;
626
                }
627
                lexer.next();
628
                String id = (String) token.getLiteral();
629
                Token next = lexer.look();
630
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
631
                    next = lexer.next();
632
                    Codes args = parse_arguments();
633
                    next = lexer.next();
634
                    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
                    }
648
                    // 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
                    return codeBuilder.function(id, args);
657
                } else {
658
                    if( StringUtils.equalsIgnoreCase(id, "TRUE") ) {
659
                        return codeBuilder.constant(true);
660
                    }
661
                    if( StringUtils.equalsIgnoreCase(id, "FALSE") ) {
662
                        return codeBuilder.constant(false);
663
                    }
664
                    return codeBuilder.identifier(id);
665
                }
666
            }
667
        case Token.STRING_LITERAL: 
668
            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
        case Token.OP_SUBST:
686
            lexer.next();
687
            Code code = parse_termino();
688
            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
                throw new ExpressionSyntaxException(I18N.A_numeric_constant_was_expected_after_the_unary_operator_minus(),lexer);
695
            }
696
            return codeBuilder.negate(code);
697
        case Token.EOF:
698
            throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer);
699
        default:
700
            return parse_grammars();
701
        }
702
    }
703

    
704
    public Codes parse_expressions(String sep) {
705
        BaseCodes codes = null;
706
        while( true ) {
707
            Code code = parse_expression();
708
            if( code!=null ) {
709
                if( codes == null ) {
710
                    codes = (BaseCodes) codeBuilder.args();
711
                }
712
                codes.add(code);
713
            }
714
            Token next = lexer.look();
715
            String literal = next.getLiteral();
716
            if( literal == null ) {
717
                return codes;
718
            }
719
            literal = literal.trim();
720
            if( sep.equals(literal) ) {
721
                lexer.next(); // Consume el ",".
722
            } else {
723
                return codes;
724
            }
725
        }
726
    }
727

    
728
    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
            if( next.is(":","=","=>") ) {
736
                ((AbstractLexicalAnalyzer)lexer).drop_state();
737
                return key;
738
            }
739
        }
740
        ((AbstractLexicalAnalyzer)lexer).restore_state();
741
        return null;
742
    }
743
    
744
    public Codes parse_arguments() {
745
        String sep = ",";
746
        BaseCodes codes = null;
747
        Map<String,Code> kwargs = null;
748
        while( true ) {
749
            String key = getKeyArgument();
750
            if( key == null ) {
751
                if( kwargs != null ) {
752
                    throw new ExpressionSyntaxException(I18N.nonkeyword_arg_after_keyword_arg(),lexer);
753
                }
754
                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
            }
768
            Token next = lexer.look();
769
            if( !next.is(sep) ) {
770
                break;
771
            }
772
            lexer.next(); // Consume el ",".
773
        }
774
        if( kwargs!=null ) {
775
            if( codes == null ) {
776
                codes = (BaseCodes) codeBuilder.args();
777
            }
778
            Code code = codeBuilder.dict(kwargs);
779
            codes.add(code);
780
        }
781
        return codes;
782
    }
783

    
784
    private Code parse_grammars() {
785
        StatementContext context = new DefaultStatementContext();
786
        Code code;
787
        BaseCodes args = (BaseCodes) this.codeBuilder.args();
788
        context.trace("compiler.parse_gramars");
789
        Statement stmt = this.grammars.getApplicableStatement(context);
790
        while( stmt!=null ) {
791
            code = stmt.parse(context);
792
            args.add(code);
793
            stmt = this.grammars.getApplicableStatement(context);
794
        }
795
        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
    }
808
}