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

History | View | Annotate | Download (16.3 KB)

1
package org.gvsig.expressionevaluator.impl;
2

    
3
import java.util.ArrayList;
4
import java.util.List;
5
import java.util.Objects;
6
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
import static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_LIST;
12
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
    private StatementBuilder stmtBuilder;
31
//    private String codeId;
32
//    private ArgsBuilder argsBuilder;
33

    
34
    public interface RepeatRule extends CompoundRule {
35

    
36
        public String getClassifier();
37
    }
38

    
39
    public class RuleRequireAnyToken implements Rule {
40

    
41
        private final String[] required_token;
42

    
43
        public RuleRequireAnyToken(String... required_token) {
44
            this.required_token = required_token;
45
        }
46

    
47
        @Override
48
        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
                                StringUtils.join(this.required_token,", "),
54
                                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
        @Override
83
        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
    public class RuleRequireExpression implements Rule {
104

    
105
        private final String id;
106

    
107
        public RuleRequireExpression(String id) {
108
            this.id = id;
109
        }
110

    
111
        @Override
112
        public void parse(StatementContext context) {
113
            Code code = context.parse_expression();
114
            if (code == null) {
115
                throw new ExpressionSyntaxException(context.getLexicalAnalyzer());
116
            }
117
            context.setCode(id, code);
118
        }
119

    
120
        @Override
121
        public String toString() {
122
            return "require_expression('" + this.id + "')";
123
        }
124
    }
125

    
126

    
127
    public class RuleSetExpression implements Rule {
128

    
129
        private final String id;
130
        private final Object value;
131

    
132
        public RuleSetExpression(String id, Object value) {
133
            this.id = id;
134
            this.value = value;
135
        }
136

    
137
        @Override
138
        public void parse(StatementContext context) {
139
            if( this.value instanceof Code ) {
140
                context.setCode(id, (Code) this.value);
141
            } else {
142
                context.setCode(id, context.getCodeBuilder().constant(value));
143
            }
144
        }
145

    
146
        @Override
147
        public String toString() {
148
            return "set_expression('" + this.id + "', "+Objects.toString(value)+")";
149
        }
150
    }
151

    
152
    public class RuleRequiereExpressions implements Rule {
153

    
154
        private final String id;
155
        private final String separator;
156

    
157
        public RuleRequiereExpressions(String id, String separator) {
158
            this.id = id;
159
            this.separator = separator;
160
        }
161

    
162
        @Override
163
        public void parse(StatementContext context) {
164
            Codes codes = context.parse_expressions(this.separator);
165
            if (codes == null) {
166
                throw new ExpressionSyntaxException(context.getLexicalAnalyzer());
167
            }
168
            Code code;
169
            if( codes.size()==1 ) {
170
                code = codes.get(0);
171
            } else {
172
                code = context.getCodeBuilder().function(CodeBlockFunction.NAME, codes);
173
            }
174
            context.setCode(id, code);
175
        }
176

    
177
        @Override
178
        public String toString() {
179
            return "require_expressions('" + this.id + "', '" + this.separator + "')";
180
        }
181
    }
182

    
183
    public class RuleOptionalAnyToken implements ConditionalRule {
184

    
185
        private final String[] optional_token;
186
        private final List<Rule> onTrueRules;
187
        private final List<Rule> onFalseRules;
188

    
189
        public RuleOptionalAnyToken(String... optional_token) {
190
            this.optional_token = optional_token;
191
            this.onTrueRules = new ArrayList<>();
192
            this.onFalseRules = new ArrayList<>();
193
        }
194

    
195
        @Override
196
        public void parse(StatementContext context) {
197
            Token token = context.look_token();
198
            if (token.is(this.optional_token)) {
199
                context.next_token();
200
                for (Rule rule : this.onTrueRules) {
201
                    rule.parse(context);
202
                }
203
            } else {
204
                for (Rule rule : this.onFalseRules) {
205
                    rule.parse(context);
206
                }
207
            }
208
        }
209

    
210
        @Override
211
        public RuleOptionalAnyToken addRuleOnTrue(Rule rule) {
212
            this.onTrueRules.add(rule);
213
            return this;
214
        }
215

    
216
        @Override
217
        public RuleOptionalAnyToken addRuleOnFalse(Rule rule) {
218
            this.onFalseRules.add(rule);
219
            return this;
220
        }
221

    
222
        @Override
223
        public String toString() {
224
            return "optional_token(" + StringUtils.join(this.optional_token) + ") rules:" + StringUtils.join(onTrueRules, ",");
225
        }
226
    }
227

    
228
    public class RuleRepeatUntilAnyTokens implements RepeatRule {
229

    
230
        private final String[] exit_tokens;
231
        private final List<Rule> rules;
232
        private int counter;
233

    
234
        public RuleRepeatUntilAnyTokens(String[] exit_tokens) {
235
            this.exit_tokens = exit_tokens;
236
            this.rules = new ArrayList<>();
237
        }
238

    
239
        @Override
240
        public void parse(StatementContext context) {
241
            String save = context.getCodeClassifier();
242
            try {
243
                this.counter = 1;
244
                while (true) {
245
                    Token token = context.look_token();
246
                    if (token.is(this.exit_tokens)) {
247
                        break;
248
                    }
249
                    context.setCodeClassifier(String.valueOf(counter).trim());
250
                    for (Rule rule : rules) {
251
                        rule.parse(context);
252
                    }
253
                    this.counter = this.counter + 1;
254
                }
255
            } finally {
256
                context.setCodeClassifier(save);
257
            }
258
        }
259

    
260
        @Override
261
        public RuleRepeatUntilAnyTokens addRule(Rule rule) {
262
            this.rules.add(rule);
263
            return this;
264
        }
265

    
266
        @Override
267
        public String getClassifier() {
268
            String s = String.valueOf(counter).trim();
269
            return s;
270
        }
271

    
272
        @Override
273
        public String toString() {
274
            return "repeat_until_tokens('" + ArrayUtils.toString(this.exit_tokens) + "') rules:" + StringUtils.join(rules, ",");
275
        }
276
    }
277

    
278
    public class RuleOptionalIdentifiers implements Rule {
279

    
280
        private final String id;
281
        private final String separator;
282

    
283
        public RuleOptionalIdentifiers(String id, String separator) {
284
            this.id = id;
285
            this.separator = separator;
286
        }
287

    
288
        @Override
289
        public void parse(StatementContext context) {
290
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
291
            Token token = context.look_token();
292
            while (token.getType() == Token.IDENTIFIER) {
293
                String identifier = (String) token.getLiteral();
294
                if( context.isReservedWord(identifier) ) {
295
                    break;
296
                }
297
                Code code = context.getCodeBuilder().constant(identifier);
298
                args.add(code);
299
                context.next_token();
300
                token = context.look_token();
301
                if (!token.is(this.separator)) {
302
                    break;
303
                }
304
                context.next_token();
305
                token = context.look_token();
306
            }
307
            Code code = null;
308
            if (args.size() != 0) {
309
                code = context.getCodeBuilder().function(FUNCTION_LIST, args);
310
            }
311
            context.setCode(id, code);
312
        }
313

    
314
        @Override
315
        public String toString() {
316
            return "optional_identifiers('" + id + "', '" + this.separator + "')";
317
        }
318
    }
319

    
320
    public static class ArgsBuilderFromNames implements ArgsBuilder {
321

    
322
        private final String[] argNames;
323

    
324
        public ArgsBuilderFromNames(String... argNames) {
325
            this.argNames = argNames;
326
        }
327

    
328
        @Override
329
        public Codes build(StatementContext context) {
330
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
331
            for (String argName : argNames) {
332
                if (argName.contains("#")) {
333
                    int n = 1;
334
                    while (true) {
335
                        String argNameX = StringUtils.replace(argName, "#", String.valueOf(n).trim(), 1);
336
                        Code code = context.getCode(argNameX);
337
                        if (code == null) {
338
                            break;
339
                        }
340
                        args.add(code);
341
                        n++;
342
                    }
343
                } else {
344
                    Code code = context.getCode(argName);
345
                    if( code != null) {
346
                        args.add(code);
347
                    }
348
                }
349
            }
350
            return args;
351
        }
352
    }
353

    
354
    public static class ArgsBuilderExpand extends ArgsBuilderFromNames {
355

    
356
        public ArgsBuilderExpand(String... argNames) {
357
            super(argNames);
358
        }
359

    
360
        @Override
361
        public Codes build(StatementContext context) {
362
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
363
            
364
            Codes base_args = super.build(context);
365
            for (Code arg : base_args) {
366
                if( arg.code() == Code.CALLER && 
367
                    ((Caller)arg).name().equals(CodeBlockFunction.NAME) ) {
368
                    Codes block_args = ((Caller)arg).parameters();
369
                    for (Code block_arg : block_args) {
370
                        args.add(block_arg);
371
                    }
372
                } else {
373
                    args.add(arg);
374
                }
375
            }
376
            return args;
377
        }
378
    }
379

    
380
    public static class StatementBuilderBase implements StatementBuilder {
381
        protected ArgsBuilder argsBuilder;
382
        protected String codeID;
383
        
384
        public StatementBuilderBase(String codeID, ArgsBuilder argsBuilder) {
385
            this.codeID = codeID;
386
            this.argsBuilder = argsBuilder;
387
        }
388
        
389
        @Override
390
        public String getCodeID() {
391
            return this.codeID;
392
        }
393

    
394
        @Override
395
        public ArgsBuilder getArgsBuilder() {
396
            return this.argsBuilder;
397
        }
398

    
399
        @Override
400
        public Code build(StatementContext context) {
401
            Codes args = this.getArgsBuilder().build(context);
402
            Code code = null;
403
            if (this.getCodeID() == null) {
404
                code = args.get(0);
405
            } else {
406
                if (args.size() == 0) {
407
                    code = context.getCodeBuilder().function(this.getCodeID(), null);
408
                } else {
409
                    // Si es un bloque dentro de otro, dejamos solo uno.
410
                    if( args.size()==1 && 
411
                        StringUtils.equalsIgnoreCase(CodeBlockFunction.NAME,this.getCodeID()) ) {
412
                        Code code0 = args.get(0);
413
                        if( code0.code() == Code.CALLER && 
414
                                StringUtils.equalsIgnoreCase(CodeBlockFunction.NAME,((Caller)code0).name())
415
                                ) {
416
                            code = code0;
417
                        }
418
                    }
419
                    if( code == null ) {
420
                        code = context.getCodeBuilder().function(this.getCodeID(), args);
421
                    }
422
                }
423
            }
424
            return code;
425
        }
426
    }
427
    
428
    public DefaultStatement(String name) {
429
        this.rules = new ArrayList<>();
430
        this.stmtBuilder = null;
431
        this.name = name;
432
    }
433

    
434
    @Override
435
    public String getName() {
436
        return name;
437
    }
438

    
439
    @Override
440
    public Rule require_any_token(String... token) {
441
        return new RuleRequireAnyToken(token);
442
    }
443

    
444
    @Override
445
    public Rule require_identifier(String id) {
446
        return new RuleRequireIdentifier(id);
447
    }
448

    
449
    @Override
450
    public Rule set_expression(String id, Object value) {
451
        return new RuleSetExpression(id, value);
452
    }
453

    
454
    @Override
455
    public Rule require_expression(String id) {
456
        return new RuleRequireExpression(id);
457
    }
458

    
459
    @Override
460
    public Rule require_expressions(String id, String separator) {
461
        return new RuleRequiereExpressions(id, separator);
462
    }
463

    
464
    @Override
465
    public ConditionalRule optional_any_token(String... id) {
466
        return new RuleOptionalAnyToken(id);
467
    }
468

    
469
    @Override
470
    public Rule optional_identifiers(String id, String separator) {
471
        return new RuleOptionalIdentifiers(id, separator);
472
    }
473

    
474
    @Override
475
    public CompoundRule repeat_until_any_tokens(String... tokens) {
476
        return new RuleRepeatUntilAnyTokens(tokens);
477
    }
478

    
479
    @Override
480
    public Statement addRule(Rule rule) {
481
        this.rules.add(rule);
482
        return this;
483
    }
484

    
485
    @Override
486
    public boolean isApplicable(StatementContext context) {
487
        if (this.rules.isEmpty()) {
488
            return false;
489
        }
490
        Rule rule = this.rules.get(0);
491
        if (!(rule instanceof RuleRequireAnyToken)) {
492
            return false;
493
        }
494
        return ((RuleRequireAnyToken) rule).isApplicable(context);
495
    }
496

    
497
    @Override
498
    public ArgsBuilder args_names(String... args) {
499
        ArgsBuilder x = new ArgsBuilderFromNames(args);
500
        return x;
501
    }
502
    
503
    @Override
504
    public ArgsBuilder args_expand(String... args) {
505
        ArgsBuilder x = new ArgsBuilderExpand(args);
506
        return x;
507
    }
508
    
509
    @Override
510
    public void code(final String id, final ArgsBuilder argsBuilder) {
511
        this.builder(new StatementBuilderBase(id, argsBuilder));
512
    }
513

    
514
    public void builder(StatementBuilder builder) {
515
        this.stmtBuilder = builder;
516
    }
517
    
518
    @Override
519
    public Code parse(StatementContext context) {
520
//        System.err.println("start parse "+this.getName());
521
        for (Rule rule : rules) {
522
            rule.parse(context);
523
        }
524
        Code code = this.stmtBuilder.build(context);
525
        return code;
526
    }
527

    
528
    @Override
529
    public String toString() {
530
        return this.getName() + " " + StringUtils.join(this.rules, ";");
531

    
532
    }
533
}