Revision 44738 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/DefaultStatement.java

View differences:

DefaultStatement.java
5 5
import java.util.Objects;
6 6
import org.apache.commons.lang3.ArrayUtils;
7 7
import org.apache.commons.lang3.StringUtils;
8
import org.apache.commons.lang3.tuple.ImmutablePair;
9
import org.apache.commons.lang3.tuple.Pair;
8 10
import org.gvsig.expressionevaluator.Code;
9 11
import org.gvsig.expressionevaluator.Code.Caller;
10 12
import org.gvsig.expressionevaluator.Codes;
......
18 20
import org.gvsig.expressionevaluator.Statement.StatementContext;
19 21
import org.gvsig.expressionevaluator.impl.function.programming.CodeBlockFunction;
20 22
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCodes;
23
import org.gvsig.expressionevaluator.spi.AbstractLexicalAnalyzer;
21 24

  
22 25
/**
23 26
 *
......
31 34
//    private String codeId;
32 35
//    private ArgsBuilder argsBuilder;
33 36

  
37
    public interface IsApplicableRule extends Rule {
38
      public boolean isApplicable(StatementContext context);
39
    }
40
    
34 41
    public interface RepeatRule extends CompoundRule {
35 42

  
36 43
        public String getClassifier();
37 44
    }
38 45

  
39
    public class RuleRequireAnyToken implements Rule {
46
    public class RuleRequireAnyToken implements IsApplicableRule {
40 47

  
41 48
        private final String[] required_token;
42 49

  
......
46 53

  
47 54
        @Override
48 55
        public void parse(StatementContext context) {
56
            context.trace(this.toString()+".parse");
49 57
            Token token = context.look_token();
50 58
            if (!token.is(this.required_token)) {
51 59
                throw new ExpressionSyntaxException(
......
59 67
            context.next_token();
60 68
        }
61 69

  
62
        private boolean isApplicable(StatementContext context) {
63
            Token token = context.look_token();
64
            return token.is(this.required_token);
70
        @Override
71
        public boolean isApplicable(StatementContext context) {
72
            Token token = context.next_token();
73
            boolean r = token.is(this.required_token);
74
            context.trace(this.toString()+".isApplicable return "+r);
75
            return r;
65 76
        }
66 77

  
67 78
        @Override
......
71 82

  
72 83
    }
73 84

  
74
    public class RuleRequireIdentifier implements Rule {
85
    public class RuleRequireIdentifier implements IsApplicableRule {
75 86

  
76 87
        private final String id;
77 88

  
......
81 92

  
82 93
        @Override
83 94
        public void parse(StatementContext context) {
95
            context.trace(this.toString()+".parse");
84 96
            Token token = context.look_token();
85 97
            if (token.getType() != Token.IDENTIFIER) {
86 98
                throw new ExpressionSyntaxException(
......
95 107
        }
96 108

  
97 109
        @Override
110
        public boolean isApplicable(StatementContext context) {
111
            Token token = context.next_token();
112
            boolean r = token.getType() == Token.IDENTIFIER;
113
            context.trace(this.toString()+".isApplicable return "+r);
114
            return r;
115
        }
116
        
117
        @Override
98 118
        public String toString() {
99 119
            return "require_identifier('" + this.id + "')";
100 120
        }
......
110 130

  
111 131
        @Override
112 132
        public void parse(StatementContext context) {
133
            context.trace(this.toString()+".parse");
113 134
            Token token = context.look_token();
114 135
            if (token.getType() != Token.STRING_LITERAL) {
115 136
                throw new ExpressionSyntaxException(
......
139 160

  
140 161
        @Override
141 162
        public void parse(StatementContext context) {
163
            context.trace(this.toString()+".parse");
142 164
            Code code = context.parse_expression();
143 165
            if (code == null) {
144 166
                throw new ExpressionSyntaxException(context.getLexicalAnalyzer());
......
165 187

  
166 188
        @Override
167 189
        public void parse(StatementContext context) {
190
            context.trace(this.toString()+".parse");
168 191
            if( this.value instanceof Code ) {
169 192
                context.setCode(id, (Code) this.value);
170 193
            } else {
......
190 213

  
191 214
        @Override
192 215
        public void parse(StatementContext context) {
216
            context.trace(this.toString()+".parse");
193 217
            Codes codes = context.parse_expressions(this.separator);
194 218
            if (codes == null) {
195 219
                throw new ExpressionSyntaxException(context.getLexicalAnalyzer());
......
259 283

  
260 284
        @Override
261 285
        public void parse(StatementContext context) {
286
            context.trace(this.toString()+".parse");
262 287
            Token token = context.look_token();
263 288
            if (token.is(this.optional_token)) {
264 289
                context.next_token();
......
286 311

  
287 312
        @Override
288 313
        public String toString() {
289
            return "optional_token(" + StringUtils.join(this.optional_token) + ") rules:" + StringUtils.join(onTrueRules, ",");
314
            return "optional_token(" + StringUtils.join(this.optional_token) + ") onTrue:" + StringUtils.join(onTrueRules, ",")+", onFalse:" + StringUtils.join(onFalseRules, ",");
290 315
        }
291 316
    }
292 317

  
318
    public class RuleSwitchToken implements SwichTokenRule {
319

  
320
        private final List<Pair<String,Rule[]>> caseRules;
321
        private Rule[] defaultRule;
322

  
323
        public RuleSwitchToken() {
324
            this.caseRules = new ArrayList<>();
325
        }
326

  
327
        @Override
328
        public void parse(StatementContext context) {
329
            context.trace(this.toString()+".parse");
330
            Token token = context.look_token();
331
            for (Pair<String, Rule[]> caseRule : caseRules) {
332
              if( token.is(caseRule.getKey()) ) {
333
                context.next_token();
334
                for (Rule rule : caseRule.getValue()) {
335
                  rule.parse(context);
336
                }
337
                return;
338
              }
339
            }
340
            if( defaultRule!=null ) {
341
              for (Rule rule : defaultRule) {
342
                rule.parse(context);
343
              }
344
            }
345
        }
346

  
347
        @Override
348
        public SwichTokenRule addCase(String token, Rule... rules) {
349
            this.caseRules.add(new ImmutablePair(token,rules));
350
            return this;
351
        }
352

  
353
        @Override
354
        public SwichTokenRule addDefault(Rule... rules) {
355
            this.defaultRule = rules;
356
            return this;
357
        }
358

  
359
        @Override
360
        public String toString() {
361
            return "switch_token() rules:" + StringUtils.join(this.caseRules,",") + " default: " + defaultRule;
362
        }
363
    }
364

  
293 365
    public class RuleRepeatUntilAnyTokens implements RepeatRule {
294 366

  
295 367
        private final String[] exit_tokens;
......
303 375

  
304 376
        @Override
305 377
        public void parse(StatementContext context) {
378
            context.trace(this.toString()+".parse");
306 379
            String save = context.getCodeClassifier();
307 380
            try {
308 381
                this.counter = 1;
......
340 413
        }
341 414
    }
342 415

  
416
    public class RuleRepeat implements RepeatRule {
417

  
418
        private final List<Rule> rules;
419
        private int counter;
420

  
421
        public RuleRepeat() {
422
            this.rules = new ArrayList<>();
423
        }
424

  
425
        @Override
426
        public void parse(StatementContext context) {
427
            context.trace(this.toString()+".parse");
428
            String save = context.getCodeClassifier();
429
            try {
430
                this.counter = 1;
431
                boolean breakloop = false;
432
                while (!breakloop) {
433
                    context.setCodeClassifier(String.valueOf(counter).trim());
434
                    for (Rule rule : rules) {
435
                      try {
436
                        rule.parse(context);
437
                      } catch(BreakLoopException ex) {
438
                        breakloop = true;
439
                        break;
440
                      }
441
                    }
442
                    this.counter = this.counter + 1;
443
                }
444
            } finally {
445
                context.setCodeClassifier(save);
446
            }
447
        }
448

  
449
        @Override
450
        public RuleRepeat addRule(Rule rule) {
451
            this.rules.add(rule);
452
            return this;
453
        }
454

  
455
        @Override
456
        public String getClassifier() {
457
            String s = String.valueOf(counter).trim();
458
            return s;
459
        }
460

  
461
        @Override
462
        public String toString() {
463
            return "repeat() rules:" + StringUtils.join(rules, ",");
464
        }
465
    }
466

  
467
    public static class BreakLoopException extends RuntimeException {
468
      
469
    }
470
    
471
    public static class RuleBreakLoop implements Rule {
472

  
473
        public RuleBreakLoop() {
474
        }
475

  
476
        @Override
477
        public void parse(StatementContext context) {
478
          context.trace(this.toString()+".parse");
479
          throw new BreakLoopException();
480
        }
481

  
482
        @Override
483
        public String toString() {
484
            return "break_loop()";
485
        }
486
    }
487

  
343 488
    public class RuleOptionalIdentifiers extends AbstractConditionalRule implements ConditionalRule {
344 489

  
345 490
        private final String id;
......
353 498

  
354 499
        @Override
355 500
        public void parse(StatementContext context) {
501
            context.trace(this.toString()+".parse");
356 502
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
357 503
            Token token = context.look_token();
358 504
            while (token.getType() == Token.IDENTIFIER) {
......
396 542

  
397 543
        @Override
398 544
        public void parse(StatementContext context) {
545
            context.trace(this.toString()+".parse");
399 546
            Token token = context.look_token();
400 547
            if (token.getType() == Token.STRING_LITERAL) {
401 548
                String s = (String) token.getValue();
......
416 563

  
417 564
    public static class ArgsBuilderFromNames implements ArgsBuilder {
418 565

  
419
        private final String[] argNames;
566
        protected final String[] argNames;
420 567

  
421 568
        public ArgsBuilderFromNames(String... argNames) {
422 569
            this.argNames = argNames;
423 570
        }
424 571

  
425 572
        @Override
573
        public String toString() {
574
          return "args_names("+StringUtils.join(argNames,",")+")";
575
        }
576
        
577
        @Override
426 578
        public Codes build(StatementContext context) {
579
            context.trace(this.toString()+".build");
427 580
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
428 581
            for (String argName : argNames) {
429 582
                if (argName.contains("#")) {
......
434 587
                        if (code == null) {
435 588
                            break;
436 589
                        }
437
                        args.add(code);
590
                        args.add(argNameX, code);
438 591
                        n++;
439 592
                    }
440 593
                } else {
......
442 595
//                    if( code == null) {
443 596
//                        code = context.getCodeBuilder().constant(null);
444 597
//                    }
445
                    args.add(code);
598
                    args.add(argName,code);
446 599
                }
447 600
            }
448 601
            return args;
......
456 609
        }
457 610

  
458 611
        @Override
612
        public String toString() {
613
          return "args_expand("+StringUtils.join(argNames,",")+")";
614
        }
615
        
616
        @Override
459 617
        public Codes build(StatementContext context) {
460 618
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
461 619
            
......
595 753
        if (this.rules.isEmpty()) {
596 754
            return false;
597 755
        }
598
        Rule rule = this.rules.get(0);
599
        if (!(rule instanceof RuleRequireAnyToken)) {
600
            return false;
756
        context.trace(this.getName()+".isApplicable");
757
        AbstractLexicalAnalyzer lexer = (AbstractLexicalAnalyzer) context.getLexicalAnalyzer();
758
        lexer.push_state();
759
        try {
760
          boolean applicable = false;
761
          for (Rule rule : rules) {
762
            if (!(rule instanceof IsApplicableRule)) {
763
                break;
764
            }
765
            if( !((IsApplicableRule) rule).isApplicable(context) ) {
766
              return false;
767
            }
768
            applicable = true;
769
          }
770
          context.trace(this.getName()+".isApplicable return "+applicable);
771
          return applicable;
772
        } finally {
773
          lexer.pop_state();
601 774
        }
602
        return ((RuleRequireAnyToken) rule).isApplicable(context);
603 775
    }
604 776

  
605 777
    @Override
......
619 791
        this.builder(new StatementBuilderBase(id, argsBuilder));
620 792
    }
621 793

  
794
    @Override
622 795
    public void builder(StatementBuilder builder) {
623 796
        this.stmtBuilder = builder;
624 797
    }
625 798
    
626 799
    @Override
627 800
    public Code parse(StatementContext context) {
628
//        System.err.println("start parse "+this.getName());
801
        context.trace(this.getName()+".parse");
629 802
        for (Rule rule : rules) {
630 803
            rule.parse(context);
631 804
        }
632 805
        Code code = this.stmtBuilder.build(context);
806
        context.trace(this.getName()+".return "+code);
633 807
        return code;
634 808
    }
635 809

  
......
638 812
        return this.getName() + " " + StringUtils.join(this.rules, ";");
639 813

  
640 814
    }
815

  
816
    @Override
817
    public CompoundRule repeat() {
818
      return new RuleRepeat();
819
    }
820

  
821
    @Override
822
    public Rule break_loop() {
823
      return new RuleBreakLoop();
824
    }
825
    
826
    @Override
827
    public SwichTokenRule switch_token() {
828
      return new RuleSwitchToken();
829
    }
830

  
641 831
}

Also available in: Unified diff