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

History | View | Annotate | Download (26.5 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
        }
38
        
39
        private State state;
40
        private final Stack<State> states;
41

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

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

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

    
73
        @Override
74
        public LexicalAnalyzer getLexicalAnalyzer() {
75
            return lexer;
76
        }
77

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

    
91
        @Override
92
        public Code getCode(String id) {
93
            return this.state.codes.get(id.toUpperCase());
94
        }
95
        
96
        @Override
97
        public void setCodeClassifier(String classifier) {
98
            this.state.codeClassifier = classifier;
99
        }
100

    
101
        @Override
102
        public String getCodeClassifier() {
103
            return this.state.codeClassifier;
104
        }
105

    
106
        @Override
107
        public CodeBuilder getCodeBuilder() {
108
            return codeBuilder;
109
        }
110

    
111
        @Override
112
        public Token look_token() {
113
            return lexer.look();
114
        }
115

    
116
        @Override
117
        public Token next_token() {
118
            return lexer.next();
119
        }
120

    
121
        @Override
122
        public Code parse_expression(boolean allow_assignement) {
123
            return DefaultCompiler.this.parse_expression(allow_assignement);
124
        }
125

    
126
        @Override
127
        public Codes parse_expressions(String separator) {
128
            return DefaultCompiler.this.parse_expressions(separator);
129
        }
130
        
131
        @Override
132
        public boolean isReservedWord(String s) {
133
            return grammars.isReservedWord(s);
134
        }
135
        
136
        @Override
137
        public void trace(String msg) {
138
//            LexicalAnalyzer lex = this.getLexicalAnalyzer();
139
//            String s = StringUtils.left(lex.getSource(), lex.getPosition()) + "[*]" + StringUtils.mid(lex.getSource(), lex.getPosition(), 200);
140
//            if( s.length()>200 ) {
141
//                s = "..."+StringUtils.mid(s, lex.getPosition()-100, 200)+"...";
142
//            }            
143
//            System.out.println(msg+". "+s);
144
        } 
145
    }
146

    
147
    private boolean objectAccessSupported;
148
    private LexicalAnalyzer lexer;
149
    private CodeBuilder codeBuilder;
150
    private final GrammarSet grammars;
151
    protected ExpressionEvaluatorManager manager;
152
    //
153
    // https://www.postgresql.org/docs/9.1/static/functions.html
154
    //
155

    
156
    public DefaultCompiler(ExpressionEvaluatorManager manager) {
157
        this.manager = manager;
158
        this.grammars = new DefaultGrammarSet();
159
        this.lexer = new SQLLexicalAnalyzer();
160
        this.codeBuilder = new DefaultCodeBuilder(manager);
161
        this.objectAccessSupported = true;
162
    }
163

    
164
    @Override
165
    public Compiler clone() throws CloneNotSupportedException {
166
        DefaultCompiler other = (DefaultCompiler) super.clone();
167
        other.lexer = lexer.clone();
168
        other.codeBuilder = codeBuilder.clone();
169
        
170
        return other;
171
    }
172

    
173
    @Override
174
    public void setLexicalAnalyzer(LexicalAnalyzer lexer) {
175
        this.lexer = lexer;
176
    }
177

    
178
    @Override
179
    public LexicalAnalyzer getLexicalAnalyzer() {
180
        return this.lexer;
181
    }
182
    
183
    @Override
184
    public void setCodeBuilder(CodeBuilder codeBuilder) {
185
        this.codeBuilder = codeBuilder;
186
    }
187

    
188
    @Override
189
    public CodeBuilder getCodeBuilder() {
190
        return this.codeBuilder;
191
    }
192
    
193
    @Override
194
    public boolean isObjectAccessSupported() {
195
        return this.objectAccessSupported;
196
    }
197

    
198
    @Override
199
    public void setObjectAccessSupported(boolean objectAccessSupported) {
200
        this.objectAccessSupported = objectAccessSupported;
201
    }
202

    
203
    @Override
204
    public GrammarSet getGrammars() {
205
        return this.grammars;
206
    }
207

    
208
    @Override
209
    public Code compileExpression(String expression) {
210
        this.lexer.setSource(expression.trim());
211
        Code code = parse_expression();
212
        if( !this.lexer.isEOF() ) {
213
            throw new ExpressionSyntaxException(lexer);
214
        }
215
        return code;
216
    }
217
    
218
    public Code parse_expression() {
219
        return this.parse_expression(true);
220
    }
221

    
222
    public Code parse_expression(boolean allow_assignement) {
223
        Code code = parse_relational();
224
        if( code != null && allow_assignement) {
225
            Token token = lexer.look();
226
            if( token.is("AS") ) {
227
                lexer.next();
228
                token = lexer.look();
229
                if( token.getType() != Token.IDENTIFIER ) {
230
                    throw new ExpressionSyntaxException(
231
                        I18N.An_identifier_was_expected_and_XliteralX_was_found(token.getLiteral()),
232
                        lexer
233
                    );                    
234
                }
235
                token = lexer.next();
236
                code = codeBuilder.let(token.getLiteral(),code);
237
            }
238
        }
239
        return code;
240
    }
241

    
242
    public Code parse_relational() {
243
        Code op1 = parse_not();
244
        Code op2;
245
        while( true ) {
246
            Token token = lexer.look();
247
            switch( token.getType() ) {
248
            case Token.OP_OR:
249
                lexer.next();
250
                op2 = parse_not();
251
                if( op2==null ) {
252
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_OR_operator(),lexer);
253
                }
254
                op1 = codeBuilder.or(op1, op2);
255
                break;
256
            case Token.OP_AND:
257
                lexer.next();
258
                op2 = parse_not();
259
                if( op2==null ) {
260
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_AND_operator(),lexer);
261
                }
262
                op1 = codeBuilder.and(op1, op2);
263
                break;
264
            default:
265
                return op1;
266
            }
267
        }
268
    }
269

    
270
    public Code parse_not() {
271
        Code op1;
272
        Token token = lexer.look();
273
        if( token.getType() == Token.OP_NOT ) {
274
            lexer.next();
275
            op1 = parse_conditional();
276
            op1 = codeBuilder.not(op1);
277
        } else {
278
            op1 = parse_conditional();
279
        }
280
        return op1;
281
    }
282

    
283
    public Code parse_conditional() {
284
        Code op1 = parse_sum();
285
        Code op2;
286
        while( true ) {
287
            Token token = lexer.look();
288
            switch( token.getType() ) {
289
            case Token.OP_LT:
290
                lexer.next();
291
                op2 = parse_sum();
292
                if( op2==null ) {
293
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LT_operator(),lexer);
294
                }
295
                op1 = codeBuilder.lt(op1, op2);
296
                break;
297
            case Token.OP_GT:
298
                lexer.next();
299
                op2 = parse_sum();
300
                if( op2==null ) {
301
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GT_operator(),lexer);
302
                }
303
                op1 = codeBuilder.gt(op1, op2);
304
                break;
305
            case Token.OP_LE:
306
                lexer.next();
307
                op2 = parse_sum();
308
                if( op2==null ) {
309
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LE_operator(),lexer);
310
                }
311
                op1 = codeBuilder.le(op1, op2);
312
                break;
313
            case Token.OP_GE:
314
                lexer.next();
315
                op2 = parse_sum();
316
                if( op2==null ) {
317
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_GE_operator(),lexer);
318
                }
319
                op1 = codeBuilder.ge(op1, op2);
320
                break;
321
            case Token.OP_EQ:
322
                lexer.next();
323
                op2 = parse_sum();
324
                if( op2==null ) {
325
                    token = lexer.look();
326
                    String tip = null;
327
                    switch(token.getType()) {
328
                        case Token.OP_GT:
329
                            tip = I18N.The_operator_greater_than_or_equal_is_ge();
330
                            break;
331
                        case Token.OP_LT:
332
                            tip = I18N.The_operator_less_than_or_equal_is_ge();
333
                            break;
334
                    }
335
                    throw new ExpressionSyntaxException(
336
                            I18N.Cant_recognize_the_second_operand_of_EQ_operator(),
337
                            lexer,
338
                            tip
339
                    );
340
                }
341
                op1 = codeBuilder.eq(op1, op2);
342
                break;
343
            case Token.OP_NE:
344
                lexer.next();
345
                op2 = parse_sum();
346
                if( op2==null ) {
347
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_NEQ_operator(),lexer);
348
                }
349
                op1 = codeBuilder.ne(op1, op2);
350
                break;
351
            case Token.PRED_IS: {
352
                    lexer.next();
353
                    Token next = lexer.look();
354
                    switch(next.getType()) {
355
                        case Token.NOTNULL:
356
                            lexer.next();
357
                            op1 = codeBuilder.is(op1, codeBuilder.constant(null));
358
                            op1 = codeBuilder.not(op1);
359
                            break;
360
                        case Token.OP_NOT:
361
                            lexer.next();
362
                            next = lexer.look();
363
                            if( next.getType() == Token.NULL ) {
364
                                lexer.next();
365
                                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
366
                            } else {
367
                                op2 = parse_sum();
368
                                if( op2==null ) {
369
                                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_IS_operator(),lexer);
370
                                }
371
                                op1 = codeBuilder.is(op1, op2);
372
                            }
373
                            op1 = codeBuilder.not(op1);
374
                            break;
375
                        case Token.NULL:
376
                            lexer.next();
377
                            op1 = codeBuilder.is(op1, codeBuilder.constant(null));
378
                            break;
379
                        default:    
380
                            op2 = parse_sum();
381
                            if( op2==null ) {
382
                                throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_IS_operator(),lexer);
383
                            }
384
                            op1 = codeBuilder.is(op1, op2);
385
                    }
386
                }
387
                break;
388
            case Token.ISNULL:
389
                lexer.next();
390
                op1 = codeBuilder.is(op1, codeBuilder.constant(null));
391
                break;
392
            case Token.OP_REGEXP:
393
                lexer.next();
394
                op2 = parse_sum();
395
                if( op2==null ) {
396
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_REGEXP_operator(),lexer);
397
                }
398
                op1 = codeBuilder.regexp(op1, op2);
399
                break;
400
            case Token.PRED_LIKE:
401
                lexer.next();
402
                op2 = parse_sum();
403
                if( op2==null ) {
404
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_LIKE_operator(),lexer);
405
                }
406
                op1 = codeBuilder.like(op1, op2);
407
                break;
408
            case Token.PRED_ILIKE:
409
                lexer.next();
410
                op2 = parse_sum();
411
                if( op2==null ) {
412
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_ILIKE_operator(),lexer);
413
                }
414
                op1 = codeBuilder.ilike(op1, op2);
415
                break;
416
            default:
417
                return op1;
418
            }
419
        }
420
    }
421

    
422
    public Code parse_sum() {
423
        Code op1 = parse_factor();
424
        Code op2;
425
        while( true ) {
426
            Token token = lexer.look();
427
            switch( token.getType() ) {
428
            case Token.OP_CONCAT:
429
                lexer.next();
430
                op2 = parse_factor();
431
                op1 = codeBuilder.concat(op1, op2);
432
                break;
433
            case Token.OP_ADD:
434
                lexer.next();
435
                op2 = parse_factor();
436
                op1 = codeBuilder.add(op1, op2);
437
                break;
438
            case Token.OP_SUBST:
439
                lexer.next();
440
                op2 = parse_factor();
441
                op1 = codeBuilder.subst(op1, op2);
442
                break;
443
            default:
444
                return op1;
445
            }
446
        }
447
    }
448

    
449
    public Code parse_factor() {
450
        Code op1 = parse_getattr();
451
        Code op2;
452
        while( true ) {
453
            Token token = lexer.look();
454
            switch( token.getType() ) {
455
            case Token.OP_MULT:
456
                lexer.next();
457
                op2 = parse_getattr();
458
                if( op2==null ) {
459
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MULT_operator(),lexer);
460
                }
461
                op1 = codeBuilder.mult(op1, op2);
462
                break;
463
            case Token.OP_DIV:
464
                lexer.next();
465
                op2 = parse_getattr();
466
                if( op2==null ) {
467
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_DIV_operator(),lexer);
468
                }
469
                op1 = codeBuilder.div(op1, op2);
470
                break;
471
            case Token.OP_MOD:
472
                lexer.next();
473
                op2 = parse_getattr();
474
                if( op2==null ) {
475
                    throw new ExpressionSyntaxException(I18N.Cant_recognize_the_second_operand_of_MOD_operator(),lexer);
476
                }
477
                op1 = codeBuilder.mod(op1, op2);
478
                break;
479
            case Token.OPEN_BRACKET:
480
                lexer.next();
481
                Code codeIndex = parse_expression();
482
                if( codeIndex == null ) {
483
                    throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer);
484
                }
485
                token = lexer.look();
486
                if( token.getType()!=Token.CLOSED_BRACKET) {
487
                    throw new ExpressionSyntaxException(I18N.A_XTokenX_was_expected_and_XliteralX_was_found("]", token.getLiteral()),lexer);
488
                }
489
                lexer.next();
490
                Code code = codeBuilder.getitem(op1, codeIndex);
491
                return code;
492
            default:
493
                return op1;
494
            }
495
        }
496
    }
497

    
498
    public Code parse_getattr() {
499
        Code op1 = parse_termino();
500
        if( !isObjectAccessSupported() ) {
501
            return op1;
502
        }
503
        while( true ) {
504
            Token next = lexer.look();
505
            switch( next.getType() ) {
506
            case Token.OP_GETATTR:
507
                lexer.next();
508
                next = lexer.look();
509
                if( next.getType()!=Token.IDENTIFIER ) {
510
                    throw new ExpressionSyntaxException(
511
                        I18N.An_attribute_identifier_was_expected_and_XliteralX_was_found(next.getLiteral()),
512
                        lexer
513
                    );
514
                }
515
                String id = (String) next.getLiteral();
516
                lexer.next();
517
                next = lexer.look();
518
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
519
                    lexer.next();
520
                    Codes args = parse_expressions(",");
521
                    next = lexer.next();
522
                    if( next.getType() != Token.PARENTHESIS_CLOSE ) {
523
                        throw new ExpressionSyntaxException(
524
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
525
                            lexer
526
                        );
527
                    }
528
                    op1 = codeBuilder.method(op1, id, args);
529
                } else {
530
                    op1 = codeBuilder.getattr(op1, id);
531
                }
532
                break;
533
            default:
534
                return op1;
535
            }
536
        }
537
    }    
538

    
539
    @SuppressWarnings("UnusedAssignment")
540
    public Code parse_termino() {
541

    
542
        Token token = lexer.look();
543
        switch( token.getType() ) {
544
        case Token.PARENTHESIS_OPEN: {
545
                lexer.next();
546
                Code value = parse_expression();
547
                Token next = lexer.next();
548
                switch(next.getType()) {
549
                    case Token.PARENTHESIS_CLOSE:
550
                        break;
551
                    case Token.EOF:
552
                        throw new ExpressionSyntaxException(
553
                            I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(),
554
                            lexer
555
                        );
556
                    default:
557
                        throw new ExpressionSyntaxException(
558
                            I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
559
                            lexer
560
                        );
561
                }
562
                return value;
563
            }
564
        case Token.IDENTIFIER: {
565
                Code code = parse_grammars();
566
                if( code!=null ) {
567
                    return code;
568
                }
569
                if( this.grammars.isReservedWord(token.getLiteral()) ) {
570
                    return null;
571
                }
572
                lexer.next();
573
                String id = (String) token.getLiteral();
574
                Token next = lexer.look();
575
                if( next.getType() == Token.PARENTHESIS_OPEN ) {
576
                    next = lexer.next();
577
                    Codes args = parse_arguments();
578
                    next = lexer.next();
579
                    switch(next.getType()) {
580
                        case Token.PARENTHESIS_CLOSE:
581
                            break;
582
                        case Token.EOF:
583
                            throw new ExpressionSyntaxException(
584
                                I18N.Closing_parenthesis_was_expected_and_end_of_source_was_found(),
585
                                lexer
586
                            );
587
                        default:
588
                            throw new ExpressionSyntaxException(
589
                                I18N.Closing_parenthesis_was_expected_and_XliteralX_was_found(next.getLiteral()),
590
                                lexer
591
                            );
592
                    }
593
                    // Optimizacion para cuando se esta invocando a la funcion dict
594
                    if( StringUtils.equalsIgnoreCase(id, FUNCTION_DICT) && args!=null && args.size()==1 ) {
595
                        code = args.get(0);
596
                        if( code.code()==Code.CALLABLE && 
597
                            StringUtils.equalsIgnoreCase(((Callable)code).name(),FUNCTION_DICT) ) {
598
                            return code;
599
                        }
600
                    }
601
                    return codeBuilder.function(id, args);
602
                } else {
603
                    if( StringUtils.equalsIgnoreCase(id, "TRUE") ) {
604
                        return codeBuilder.constant(true);
605
                    }
606
                    if( StringUtils.equalsIgnoreCase(id, "FALSE") ) {
607
                        return codeBuilder.constant(false);
608
                    }
609
                    return codeBuilder.identifier(id);
610
                }
611
            }
612
        case Token.STRING_LITERAL:
613
            lexer.next();
614
            return codeBuilder.constant(token.getValue());
615
        case Token.INTEGER_LITERAL:
616
            lexer.next();
617
            return codeBuilder.constant(token.getValue());
618
        case Token.FLOATING_POINT_LITERAL:
619
            lexer.next();
620
            return codeBuilder.constant(token.getValue());
621
        case Token.NULL:
622
            lexer.next();
623
            return codeBuilder.constant(null);
624
        case Token.TRUE:
625
            lexer.next();
626
            return codeBuilder.constant(true);
627
        case Token.FALSE:
628
            lexer.next();
629
            return codeBuilder.constant(false);
630
        case Token.OP_SUBST:
631
            lexer.next();
632
            Code code = parse_termino();
633
            if( code.code()==Code.CONSTANT ) {
634
                BaseConstant c = (BaseConstant)code;
635
                if( c.value() instanceof Number ) {
636
                    c.value(NegOperator.negate((Number) c.value()));
637
                    return code;
638
                }
639
                throw new ExpressionSyntaxException(I18N.A_numeric_constant_was_expected_after_the_unary_operator_minus(),lexer);
640
            }
641
            return codeBuilder.negate(code);
642
        case Token.EOF:
643
            throw new ExpressionSyntaxException(I18N.unexpected_end_of_source(),lexer);
644
        default:
645
            return parse_grammars();
646
        }
647
    }
648

    
649
    public Codes parse_expressions(String sep) {
650
        BaseCodes codes = null;
651
        while( true ) {
652
            Code code = parse_expression();
653
            if( code!=null ) {
654
                if( codes == null ) {
655
                    codes = (BaseCodes) codeBuilder.args();
656
                }
657
                codes.add(code);
658
            }
659
            Token next = lexer.look();
660
            String literal = next.getLiteral();
661
            if( literal == null ) {
662
                return codes;
663
            }
664
            literal = literal.trim();
665
            if( sep.equals(literal) ) {
666
                lexer.next(); // Consume el ",".
667
            } else {
668
                return codes;
669
            }
670
        }
671
    }
672

    
673
    private String getKeyArgument() {
674
        ((AbstractLexicalAnalyzer)lexer).save_state();
675
        Token next = lexer.look();
676
        if( next.getType()==Token.IDENTIFIER ) {
677
            String key = next.getLiteral();
678
            lexer.next(); 
679
            next = lexer.next();
680
            if( next.is(":","=","=>") ) {
681
                ((AbstractLexicalAnalyzer)lexer).drop_state();
682
                return key;
683
            }
684
        }
685
        ((AbstractLexicalAnalyzer)lexer).restore_state();
686
        return null;
687
    }
688
    
689
    public Codes parse_arguments() {
690
        String sep = ",";
691
        BaseCodes codes = null;
692
        Map<String,Code> kwargs = null;
693
        while( true ) {
694
            String key = getKeyArgument();
695
            if( key == null ) {
696
                if( kwargs != null ) {
697
                    throw new ExpressionSyntaxException(I18N.nonkeyword_arg_after_keyword_arg(),lexer);
698
                }
699
                Code code = parse_expression();
700
                if( code!=null ) {
701
                    if( codes == null ) {
702
                        codes = (BaseCodes) codeBuilder.args();
703
                    }
704
                    codes.add(code);
705
                }
706
            } else {
707
                if( kwargs == null ) {
708
                    kwargs = new HashMap<>();
709
                }
710
                Code code = parse_expression();
711
                kwargs.put(key, code);
712
            }
713
            Token next = lexer.look();
714
            if( !next.is(sep) ) {
715
                break;
716
            }
717
            lexer.next(); // Consume el ",".
718
        }
719
        if( kwargs!=null ) {
720
            if( codes == null ) {
721
                codes = (BaseCodes) codeBuilder.args();
722
            }
723
            Code code = codeBuilder.dict(kwargs);
724
            codes.add(code);
725
        }
726
        return codes;
727
    }
728

    
729
    private Code parse_grammars() {
730
        StatementContext context = new DefaultStatementContext();
731
        Code code;
732
        BaseCodes args = (BaseCodes) this.codeBuilder.args();
733
        context.trace("compiler.parse_gramars");
734
        Statement stmt = this.grammars.getApplicableStatement(context);
735
        while( stmt!=null ) {
736
            code = stmt.parse(context);
737
            args.add(code);
738
            stmt = this.grammars.getApplicableStatement(context);
739
        }
740
        switch(args.size()) {
741
            case 0 :
742
                code = null;
743
                break;
744
            case 1 :
745
                code = args.get(0);
746
                break;
747
            default:
748
                code = this.codeBuilder.function(CodeBlockFunction.NAME, args);
749
                break;
750
        }
751
        return code;
752
    }
753
}