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 / DefaultStatement.java @ 44592

History | View | Annotate | Download (19.5 KB)

1 44139 jjdelcerro
package org.gvsig.expressionevaluator.impl;
2
3
import java.util.ArrayList;
4
import java.util.List;
5 44379 jjdelcerro
import java.util.Objects;
6 44139 jjdelcerro
import org.apache.commons.lang3.ArrayUtils;
7
import org.apache.commons.lang3.StringUtils;
8
import org.gvsig.expressionevaluator.Code;
9
import org.gvsig.expressionevaluator.Code.Caller;
10
import org.gvsig.expressionevaluator.Codes;
11 44262 jjdelcerro
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_LIST;
12 44139 jjdelcerro
import org.gvsig.expressionevaluator.ExpressionSyntaxException;
13
import org.gvsig.expressionevaluator.LexicalAnalyzer.Token;
14
import org.gvsig.expressionevaluator.Statement;
15
import org.gvsig.expressionevaluator.Statement.CompoundRule;
16
import org.gvsig.expressionevaluator.Statement.ConditionalRule;
17
import org.gvsig.expressionevaluator.Statement.Rule;
18
import org.gvsig.expressionevaluator.Statement.StatementContext;
19
import org.gvsig.expressionevaluator.impl.function.programming.CodeBlockFunction;
20
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCodes;
21
22
/**
23
 *
24
 * @author jjdelcerro
25
 */
26
public class DefaultStatement implements Statement {
27
28
    private final List<Rule> rules;
29
    private final String name;
30 44384 jjdelcerro
    private StatementBuilder stmtBuilder;
31
//    private String codeId;
32
//    private ArgsBuilder argsBuilder;
33 44139 jjdelcerro
34
    public interface RepeatRule extends CompoundRule {
35
36
        public String getClassifier();
37
    }
38
39 44144 jjdelcerro
    public class RuleRequireAnyToken implements Rule {
40 44139 jjdelcerro
41
        private final String[] required_token;
42
43 44144 jjdelcerro
        public RuleRequireAnyToken(String... required_token) {
44 44139 jjdelcerro
            this.required_token = required_token;
45
        }
46
47 44379 jjdelcerro
        @Override
48 44139 jjdelcerro
        public void parse(StatementContext context) {
49
            Token token = context.look_token();
50
            if (!token.is(this.required_token)) {
51
                throw new ExpressionSyntaxException(
52
                        I18N.A_XTokenX_was_expected_and_XliteralX_was_found(
53 44384 jjdelcerro
                                StringUtils.join(this.required_token,", "),
54 44139 jjdelcerro
                                token.getLiteral()
55
                        ),
56
                        context.getLexicalAnalyzer()
57
                );
58
            }
59
            context.next_token();
60
        }
61
62
        private boolean isApplicable(StatementContext context) {
63
            Token token = context.look_token();
64
            return token.is(this.required_token);
65
        }
66
67
        @Override
68
        public String toString() {
69
            return "require_token(" + StringUtils.join(this.required_token) + ")";
70
        }
71
72
    }
73
74
    public class RuleRequireIdentifier implements Rule {
75
76
        private final String id;
77
78
        public RuleRequireIdentifier(String id) {
79
            this.id = id;
80
        }
81
82 44379 jjdelcerro
        @Override
83 44139 jjdelcerro
        public void parse(StatementContext context) {
84
            Token token = context.look_token();
85
            if (token.getType() != Token.IDENTIFIER) {
86
                throw new ExpressionSyntaxException(
87
                        I18N.An_identifier_was_expected_and_XliteralX_was_found(token.getLiteral()),
88
                        context.getLexicalAnalyzer()
89
                );
90
            }
91
            String identifier = (String) token.getLiteral();
92
            Code code = context.getCodeBuilder().constant(identifier);
93
            context.setCode(id, code);
94
            context.next_token();
95
        }
96
97
        @Override
98
        public String toString() {
99
            return "require_identifier('" + this.id + "')";
100
        }
101
    }
102
103 44533 jjdelcerro
    public class RuleRequireLiteralString implements Rule {
104
105
        private final String id;
106
107
        public RuleRequireLiteralString(String id) {
108
            this.id = id;
109
        }
110
111
        @Override
112
        public void parse(StatementContext context) {
113
            Token token = context.look_token();
114
            if (token.getType() != Token.STRING_LITERAL) {
115
                throw new ExpressionSyntaxException(
116
                        I18N.A_string_literal_was_expected(),
117
                        context.getLexicalAnalyzer()
118
                );
119
            }
120 44592 jjdelcerro
            String identifier = (String) token.getValue();
121 44533 jjdelcerro
            Code code = context.getCodeBuilder().constant(identifier);
122
            context.setCode(id, code);
123
            context.next_token();
124
        }
125
126
        @Override
127
        public String toString() {
128
            return "require_literal_string('" + this.id + "')";
129
        }
130
    }
131
132 44139 jjdelcerro
    public class RuleRequireExpression implements Rule {
133
134
        private final String id;
135
136
        public RuleRequireExpression(String id) {
137
            this.id = id;
138
        }
139
140 44379 jjdelcerro
        @Override
141 44139 jjdelcerro
        public void parse(StatementContext context) {
142
            Code code = context.parse_expression();
143
            if (code == null) {
144
                throw new ExpressionSyntaxException(context.getLexicalAnalyzer());
145
            }
146
            context.setCode(id, code);
147
        }
148
149
        @Override
150
        public String toString() {
151
            return "require_expression('" + this.id + "')";
152
        }
153
    }
154
155 44379 jjdelcerro
156
    public class RuleSetExpression implements Rule {
157
158
        private final String id;
159
        private final Object value;
160
161
        public RuleSetExpression(String id, Object value) {
162
            this.id = id;
163
            this.value = value;
164
        }
165
166
        @Override
167
        public void parse(StatementContext context) {
168
            if( this.value instanceof Code ) {
169
                context.setCode(id, (Code) this.value);
170
            } else {
171
                context.setCode(id, context.getCodeBuilder().constant(value));
172
            }
173
        }
174
175
        @Override
176
        public String toString() {
177
            return "set_expression('" + this.id + "', "+Objects.toString(value)+")";
178
        }
179
    }
180
181 44139 jjdelcerro
    public class RuleRequiereExpressions implements Rule {
182
183
        private final String id;
184
        private final String separator;
185
186
        public RuleRequiereExpressions(String id, String separator) {
187
            this.id = id;
188
            this.separator = separator;
189
        }
190
191 44379 jjdelcerro
        @Override
192 44139 jjdelcerro
        public void parse(StatementContext context) {
193
            Codes codes = context.parse_expressions(this.separator);
194
            if (codes == null) {
195
                throw new ExpressionSyntaxException(context.getLexicalAnalyzer());
196
            }
197 44379 jjdelcerro
            Code code;
198
            if( codes.size()==1 ) {
199
                code = codes.get(0);
200
            } else {
201
                code = context.getCodeBuilder().function(CodeBlockFunction.NAME, codes);
202
            }
203 44139 jjdelcerro
            context.setCode(id, code);
204
        }
205
206
        @Override
207
        public String toString() {
208
            return "require_expressions('" + this.id + "', '" + this.separator + "')";
209
        }
210
    }
211
212 44533 jjdelcerro
    public abstract class AbstractConditionalRule implements ConditionalRule {
213
214
        protected final List<Rule> onTrueRules;
215
        protected final List<Rule> onFalseRules;
216
217
        public AbstractConditionalRule() {
218
            this.onTrueRules = new ArrayList<>();
219
            this.onFalseRules = new ArrayList<>();
220
        }
221
222
        protected void parseOnTrueRules(StatementContext context) {
223
            for (Rule rule : this.onTrueRules) {
224
                rule.parse(context);
225
            }
226
        }
227
228
        protected void parseOnFalseRules(StatementContext context) {
229
            for (Rule rule : this.onFalseRules) {
230
                rule.parse(context);
231
            }
232
        }
233
234
        @Override
235
        public ConditionalRule addRuleOnTrue(Rule rule) {
236
            this.onTrueRules.add(rule);
237
            return this;
238
        }
239
240
        @Override
241
        public ConditionalRule addRuleOnFalse(Rule rule) {
242
            this.onFalseRules.add(rule);
243
            return this;
244
        }
245
246
    }
247
248 44144 jjdelcerro
    public class RuleOptionalAnyToken implements ConditionalRule {
249 44139 jjdelcerro
250
        private final String[] optional_token;
251
        private final List<Rule> onTrueRules;
252
        private final List<Rule> onFalseRules;
253
254 44144 jjdelcerro
        public RuleOptionalAnyToken(String... optional_token) {
255 44139 jjdelcerro
            this.optional_token = optional_token;
256
            this.onTrueRules = new ArrayList<>();
257
            this.onFalseRules = new ArrayList<>();
258
        }
259
260 44379 jjdelcerro
        @Override
261 44139 jjdelcerro
        public void parse(StatementContext context) {
262
            Token token = context.look_token();
263
            if (token.is(this.optional_token)) {
264
                context.next_token();
265
                for (Rule rule : this.onTrueRules) {
266
                    rule.parse(context);
267
                }
268
            } else {
269
                for (Rule rule : this.onFalseRules) {
270
                    rule.parse(context);
271
                }
272
            }
273
        }
274
275 44379 jjdelcerro
        @Override
276 44144 jjdelcerro
        public RuleOptionalAnyToken addRuleOnTrue(Rule rule) {
277 44139 jjdelcerro
            this.onTrueRules.add(rule);
278
            return this;
279
        }
280
281 44379 jjdelcerro
        @Override
282 44144 jjdelcerro
        public RuleOptionalAnyToken addRuleOnFalse(Rule rule) {
283 44139 jjdelcerro
            this.onFalseRules.add(rule);
284
            return this;
285
        }
286
287
        @Override
288
        public String toString() {
289
            return "optional_token(" + StringUtils.join(this.optional_token) + ") rules:" + StringUtils.join(onTrueRules, ",");
290
        }
291
    }
292
293 44144 jjdelcerro
    public class RuleRepeatUntilAnyTokens implements RepeatRule {
294 44139 jjdelcerro
295
        private final String[] exit_tokens;
296
        private final List<Rule> rules;
297
        private int counter;
298
299 44144 jjdelcerro
        public RuleRepeatUntilAnyTokens(String[] exit_tokens) {
300 44139 jjdelcerro
            this.exit_tokens = exit_tokens;
301
            this.rules = new ArrayList<>();
302
        }
303
304 44379 jjdelcerro
        @Override
305 44139 jjdelcerro
        public void parse(StatementContext context) {
306
            String save = context.getCodeClassifier();
307
            try {
308
                this.counter = 1;
309
                while (true) {
310
                    Token token = context.look_token();
311
                    if (token.is(this.exit_tokens)) {
312
                        break;
313
                    }
314
                    context.setCodeClassifier(String.valueOf(counter).trim());
315
                    for (Rule rule : rules) {
316
                        rule.parse(context);
317
                    }
318
                    this.counter = this.counter + 1;
319
                }
320
            } finally {
321
                context.setCodeClassifier(save);
322
            }
323
        }
324
325 44379 jjdelcerro
        @Override
326 44144 jjdelcerro
        public RuleRepeatUntilAnyTokens addRule(Rule rule) {
327 44139 jjdelcerro
            this.rules.add(rule);
328
            return this;
329
        }
330
331
        @Override
332
        public String getClassifier() {
333
            String s = String.valueOf(counter).trim();
334
            return s;
335
        }
336
337
        @Override
338
        public String toString() {
339
            return "repeat_until_tokens('" + ArrayUtils.toString(this.exit_tokens) + "') rules:" + StringUtils.join(rules, ",");
340
        }
341
    }
342
343 44533 jjdelcerro
    public class RuleOptionalIdentifiers extends AbstractConditionalRule implements ConditionalRule {
344 44139 jjdelcerro
345
        private final String id;
346
        private final String separator;
347
348
        public RuleOptionalIdentifiers(String id, String separator) {
349 44533 jjdelcerro
            super();
350 44139 jjdelcerro
            this.id = id;
351
            this.separator = separator;
352
        }
353
354 44379 jjdelcerro
        @Override
355 44139 jjdelcerro
        public void parse(StatementContext context) {
356
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
357
            Token token = context.look_token();
358
            while (token.getType() == Token.IDENTIFIER) {
359
                String identifier = (String) token.getLiteral();
360 44384 jjdelcerro
                if( context.isReservedWord(identifier) ) {
361
                    break;
362
                }
363 44139 jjdelcerro
                Code code = context.getCodeBuilder().constant(identifier);
364
                args.add(code);
365
                context.next_token();
366
                token = context.look_token();
367
                if (!token.is(this.separator)) {
368
                    break;
369
                }
370
                context.next_token();
371
                token = context.look_token();
372
            }
373
            if (args.size() != 0) {
374 44533 jjdelcerro
                Code code = context.getCodeBuilder().function(FUNCTION_LIST, args);
375
                context.setCode(id, code);
376
                this.parseOnTrueRules(context);
377
            } else {
378
                this.parseOnFalseRules(context);
379 44139 jjdelcerro
            }
380
        }
381
382
        @Override
383
        public String toString() {
384
            return "optional_identifiers('" + id + "', '" + this.separator + "')";
385
        }
386
    }
387
388 44533 jjdelcerro
    public class RuleOptionalLiteralString extends AbstractConditionalRule implements ConditionalRule {
389
390
        private final String id;
391
392
        public RuleOptionalLiteralString(String id) {
393
            super();
394
            this.id = id;
395
        }
396
397
        @Override
398
        public void parse(StatementContext context) {
399
            Token token = context.look_token();
400
            if (token.getType() == Token.STRING_LITERAL) {
401 44592 jjdelcerro
                String s = (String) token.getValue();
402 44533 jjdelcerro
                Code code = context.getCodeBuilder().constant(s);
403
                context.setCode(id, code);
404
                context.next_token();
405
                this.parseOnTrueRules(context);
406
            } else {
407
                this.parseOnFalseRules(context);
408
            }
409
        }
410
411
        @Override
412
        public String toString() {
413
            return "optional_literal_string('" + id + "')";
414
        }
415
    }
416
417 44384 jjdelcerro
    public static class ArgsBuilderFromNames implements ArgsBuilder {
418 44139 jjdelcerro
419
        private final String[] argNames;
420
421 44384 jjdelcerro
        public ArgsBuilderFromNames(String... argNames) {
422 44139 jjdelcerro
            this.argNames = argNames;
423
        }
424
425 44379 jjdelcerro
        @Override
426 44139 jjdelcerro
        public Codes build(StatementContext context) {
427
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
428
            for (String argName : argNames) {
429
                if (argName.contains("#")) {
430
                    int n = 1;
431
                    while (true) {
432
                        String argNameX = StringUtils.replace(argName, "#", String.valueOf(n).trim(), 1);
433
                        Code code = context.getCode(argNameX);
434
                        if (code == null) {
435
                            break;
436
                        }
437
                        args.add(code);
438
                        n++;
439
                    }
440
                } else {
441
                    Code code = context.getCode(argName);
442 44592 jjdelcerro
//                    if( code == null) {
443
//                        code = context.getCodeBuilder().constant(null);
444
//                    }
445 44533 jjdelcerro
                    args.add(code);
446 44139 jjdelcerro
                }
447
            }
448
            return args;
449
        }
450
    }
451
452 44384 jjdelcerro
    public static class ArgsBuilderExpand extends ArgsBuilderFromNames {
453 44139 jjdelcerro
454 44384 jjdelcerro
        public ArgsBuilderExpand(String... argNames) {
455 44139 jjdelcerro
            super(argNames);
456
        }
457
458 44379 jjdelcerro
        @Override
459 44139 jjdelcerro
        public Codes build(StatementContext context) {
460
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
461
462
            Codes base_args = super.build(context);
463
            for (Code arg : base_args) {
464
                if( arg.code() == Code.CALLER &&
465
                    ((Caller)arg).name().equals(CodeBlockFunction.NAME) ) {
466 44198 jjdelcerro
                    Codes block_args = ((Caller)arg).parameters();
467 44139 jjdelcerro
                    for (Code block_arg : block_args) {
468
                        args.add(block_arg);
469
                    }
470
                } else {
471
                    args.add(arg);
472
                }
473
            }
474
            return args;
475
        }
476
    }
477
478 44384 jjdelcerro
    public static class StatementBuilderBase implements StatementBuilder {
479
        protected ArgsBuilder argsBuilder;
480
        protected String codeID;
481
482
        public StatementBuilderBase(String codeID, ArgsBuilder argsBuilder) {
483
            this.codeID = codeID;
484
            this.argsBuilder = argsBuilder;
485
        }
486
487
        @Override
488
        public String getCodeID() {
489
            return this.codeID;
490
        }
491
492
        @Override
493
        public ArgsBuilder getArgsBuilder() {
494
            return this.argsBuilder;
495
        }
496
497
        @Override
498
        public Code build(StatementContext context) {
499
            Codes args = this.getArgsBuilder().build(context);
500
            Code code = null;
501
            if (this.getCodeID() == null) {
502
                code = args.get(0);
503
            } else {
504
                if (args.size() == 0) {
505
                    code = context.getCodeBuilder().function(this.getCodeID(), null);
506
                } else {
507
                    // Si es un bloque dentro de otro, dejamos solo uno.
508
                    if( args.size()==1 &&
509
                        StringUtils.equalsIgnoreCase(CodeBlockFunction.NAME,this.getCodeID()) ) {
510
                        Code code0 = args.get(0);
511
                        if( code0.code() == Code.CALLER &&
512
                                StringUtils.equalsIgnoreCase(CodeBlockFunction.NAME,((Caller)code0).name())
513
                                ) {
514
                            code = code0;
515
                        }
516
                    }
517
                    if( code == null ) {
518
                        code = context.getCodeBuilder().function(this.getCodeID(), args);
519
                    }
520
                }
521
            }
522
            return code;
523
        }
524
    }
525
526 44139 jjdelcerro
    public DefaultStatement(String name) {
527
        this.rules = new ArrayList<>();
528 44384 jjdelcerro
        this.stmtBuilder = null;
529 44139 jjdelcerro
        this.name = name;
530
    }
531
532 44379 jjdelcerro
    @Override
533 44139 jjdelcerro
    public String getName() {
534
        return name;
535
    }
536
537
    @Override
538 44144 jjdelcerro
    public Rule require_any_token(String... token) {
539
        return new RuleRequireAnyToken(token);
540 44139 jjdelcerro
    }
541
542
    @Override
543
    public Rule require_identifier(String id) {
544
        return new RuleRequireIdentifier(id);
545
    }
546
547
    @Override
548 44533 jjdelcerro
    public Rule require_literal_string(String id) {
549
        return new RuleRequireLiteralString(id);
550
    }
551
552
    @Override
553 44379 jjdelcerro
    public Rule set_expression(String id, Object value) {
554
        return new RuleSetExpression(id, value);
555
    }
556
557
    @Override
558 44139 jjdelcerro
    public Rule require_expression(String id) {
559
        return new RuleRequireExpression(id);
560
    }
561
562
    @Override
563
    public Rule require_expressions(String id, String separator) {
564
        return new RuleRequiereExpressions(id, separator);
565
    }
566
567
    @Override
568 44144 jjdelcerro
    public ConditionalRule optional_any_token(String... id) {
569
        return new RuleOptionalAnyToken(id);
570 44139 jjdelcerro
    }
571
572
    @Override
573 44533 jjdelcerro
    public ConditionalRule optional_identifiers(String id, String separator) {
574 44139 jjdelcerro
        return new RuleOptionalIdentifiers(id, separator);
575
    }
576
577
    @Override
578 44533 jjdelcerro
    public ConditionalRule optional_literal_string(String id) {
579
        return new RuleOptionalLiteralString(id);
580
    }
581
582
    @Override
583 44144 jjdelcerro
    public CompoundRule repeat_until_any_tokens(String... tokens) {
584
        return new RuleRepeatUntilAnyTokens(tokens);
585 44139 jjdelcerro
    }
586
587
    @Override
588
    public Statement addRule(Rule rule) {
589
        this.rules.add(rule);
590
        return this;
591
    }
592
593
    @Override
594
    public boolean isApplicable(StatementContext context) {
595
        if (this.rules.isEmpty()) {
596
            return false;
597
        }
598
        Rule rule = this.rules.get(0);
599 44144 jjdelcerro
        if (!(rule instanceof RuleRequireAnyToken)) {
600 44139 jjdelcerro
            return false;
601
        }
602 44144 jjdelcerro
        return ((RuleRequireAnyToken) rule).isApplicable(context);
603 44139 jjdelcerro
    }
604
605
    @Override
606
    public ArgsBuilder args_names(String... args) {
607
        ArgsBuilder x = new ArgsBuilderFromNames(args);
608
        return x;
609
    }
610
611
    @Override
612
    public ArgsBuilder args_expand(String... args) {
613
        ArgsBuilder x = new ArgsBuilderExpand(args);
614
        return x;
615
    }
616
617
    @Override
618 44384 jjdelcerro
    public void code(final String id, final ArgsBuilder argsBuilder) {
619
        this.builder(new StatementBuilderBase(id, argsBuilder));
620 44139 jjdelcerro
    }
621
622 44384 jjdelcerro
    public void builder(StatementBuilder builder) {
623
        this.stmtBuilder = builder;
624
    }
625
626 44139 jjdelcerro
    @Override
627
    public Code parse(StatementContext context) {
628 44379 jjdelcerro
//        System.err.println("start parse "+this.getName());
629 44139 jjdelcerro
        for (Rule rule : rules) {
630
            rule.parse(context);
631
        }
632 44384 jjdelcerro
        Code code = this.stmtBuilder.build(context);
633 44139 jjdelcerro
        return code;
634
    }
635
636
    @Override
637
    public String toString() {
638
        return this.getName() + " " + StringUtils.join(this.rules, ";");
639
640
    }
641
}