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

History | View | Annotate | Download (13.3 KB)

1 44139 jjdelcerro
package org.gvsig.expressionevaluator.impl;
2
3
import java.util.ArrayList;
4
import java.util.List;
5
import org.apache.commons.lang3.ArrayUtils;
6
import org.apache.commons.lang3.StringUtils;
7
import org.gvsig.expressionevaluator.Code;
8
import org.gvsig.expressionevaluator.Code.Caller;
9
import org.gvsig.expressionevaluator.Codes;
10
import org.gvsig.expressionevaluator.ExpressionSyntaxException;
11
import org.gvsig.expressionevaluator.LexicalAnalyzer.Token;
12
import org.gvsig.expressionevaluator.Statement;
13
import org.gvsig.expressionevaluator.Statement.CompoundRule;
14
import org.gvsig.expressionevaluator.Statement.ConditionalRule;
15
import org.gvsig.expressionevaluator.Statement.Rule;
16
import org.gvsig.expressionevaluator.Statement.StatementContext;
17
import org.gvsig.expressionevaluator.impl.function.programming.CodeBlockFunction;
18
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCodes;
19
import org.gvsig.expressionevaluator.impl.function.programming.ListFunction;
20
21
/**
22
 *
23
 * @author jjdelcerro
24
 */
25
public class DefaultStatement implements Statement {
26
27
    private final List<Rule> rules;
28
    private String codeId;
29
    private ArgsBuilder argsBuilder;
30
    private final String name;
31
32
    public interface RepeatRule extends CompoundRule {
33
34
        public String getClassifier();
35
    }
36
37 44144 jjdelcerro
    public class RuleRequireAnyToken implements Rule {
38 44139 jjdelcerro
39
        private final String[] required_token;
40
41 44144 jjdelcerro
        public RuleRequireAnyToken(String... required_token) {
42 44139 jjdelcerro
            this.required_token = required_token;
43
        }
44
45
        public void parse(StatementContext context) {
46
            Token token = context.look_token();
47
            if (!token.is(this.required_token)) {
48
                throw new ExpressionSyntaxException(
49
                        I18N.A_XTokenX_was_expected_and_XliteralX_was_found(
50
                                StringUtils.join(this.required_token),
51
                                token.getLiteral()
52
                        ),
53
                        context.getLexicalAnalyzer()
54
                );
55
            }
56
            context.next_token();
57
        }
58
59
        private boolean isApplicable(StatementContext context) {
60
            Token token = context.look_token();
61
            return token.is(this.required_token);
62
        }
63
64
        @Override
65
        public String toString() {
66
            return "require_token(" + StringUtils.join(this.required_token) + ")";
67
        }
68
69
    }
70
71
    public class RuleRequireIdentifier implements Rule {
72
73
        private final String id;
74
75
        public RuleRequireIdentifier(String id) {
76
            this.id = id;
77
        }
78
79
        public void parse(StatementContext context) {
80
            Token token = context.look_token();
81
            if (token.getType() != Token.IDENTIFIER) {
82
                throw new ExpressionSyntaxException(
83
                        I18N.An_identifier_was_expected_and_XliteralX_was_found(token.getLiteral()),
84
                        context.getLexicalAnalyzer()
85
                );
86
            }
87
            String identifier = (String) token.getLiteral();
88
            Code code = context.getCodeBuilder().constant(identifier);
89
            context.setCode(id, code);
90
            context.next_token();
91
        }
92
93
        @Override
94
        public String toString() {
95
            return "require_identifier('" + this.id + "')";
96
        }
97
    }
98
99
    public class RuleRequireExpression implements Rule {
100
101
        private final String id;
102
103
        public RuleRequireExpression(String id) {
104
            this.id = id;
105
        }
106
107
        public void parse(StatementContext context) {
108
            Code code = context.parse_expression();
109
            if (code == null) {
110
                throw new ExpressionSyntaxException(context.getLexicalAnalyzer());
111
            }
112
            context.setCode(id, code);
113
        }
114
115
        @Override
116
        public String toString() {
117
            return "require_expression('" + this.id + "')";
118
        }
119
    }
120
121
    public class RuleRequiereExpressions implements Rule {
122
123
        private final String id;
124
        private final String separator;
125
126
        public RuleRequiereExpressions(String id, String separator) {
127
            this.id = id;
128
            this.separator = separator;
129
        }
130
131
        public void parse(StatementContext context) {
132
            Codes codes = context.parse_expressions(this.separator);
133
            if (codes == null) {
134
                throw new ExpressionSyntaxException(context.getLexicalAnalyzer());
135
            }
136
            Code code = context.getCodeBuilder().function(CodeBlockFunction.NAME, codes);
137
            context.setCode(id, code);
138
        }
139
140
        @Override
141
        public String toString() {
142
            return "require_expressions('" + this.id + "', '" + this.separator + "')";
143
        }
144
    }
145
146 44144 jjdelcerro
    public class RuleOptionalAnyToken implements ConditionalRule {
147 44139 jjdelcerro
148
        private final String[] optional_token;
149
        private final List<Rule> onTrueRules;
150
        private final List<Rule> onFalseRules;
151
152 44144 jjdelcerro
        public RuleOptionalAnyToken(String... optional_token) {
153 44139 jjdelcerro
            this.optional_token = optional_token;
154
            this.onTrueRules = new ArrayList<>();
155
            this.onFalseRules = new ArrayList<>();
156
        }
157
158
        public void parse(StatementContext context) {
159
            Token token = context.look_token();
160
            if (token.is(this.optional_token)) {
161
                context.next_token();
162
                for (Rule rule : this.onTrueRules) {
163
                    rule.parse(context);
164
                }
165
            } else {
166
                for (Rule rule : this.onFalseRules) {
167
                    rule.parse(context);
168
                }
169
            }
170
        }
171
172 44144 jjdelcerro
        public RuleOptionalAnyToken addRuleOnTrue(Rule rule) {
173 44139 jjdelcerro
            this.onTrueRules.add(rule);
174
            return this;
175
        }
176
177 44144 jjdelcerro
        public RuleOptionalAnyToken addRuleOnFalse(Rule rule) {
178 44139 jjdelcerro
            this.onFalseRules.add(rule);
179
            return this;
180
        }
181
182
        @Override
183
        public String toString() {
184
            return "optional_token(" + StringUtils.join(this.optional_token) + ") rules:" + StringUtils.join(onTrueRules, ",");
185
        }
186
    }
187
188 44144 jjdelcerro
    public class RuleRepeatUntilAnyTokens implements RepeatRule {
189 44139 jjdelcerro
190
        private final String[] exit_tokens;
191
        private final List<Rule> rules;
192
        private int counter;
193
194 44144 jjdelcerro
        public RuleRepeatUntilAnyTokens(String[] exit_tokens) {
195 44139 jjdelcerro
            this.exit_tokens = exit_tokens;
196
            this.rules = new ArrayList<>();
197
        }
198
199
        public void parse(StatementContext context) {
200
            String save = context.getCodeClassifier();
201
            try {
202
                this.counter = 1;
203
                while (true) {
204
                    Token token = context.look_token();
205
                    if (token.is(this.exit_tokens)) {
206
                        break;
207
                    }
208
                    context.setCodeClassifier(String.valueOf(counter).trim());
209
                    for (Rule rule : rules) {
210
                        rule.parse(context);
211
                    }
212
                    this.counter = this.counter + 1;
213
                }
214
            } finally {
215
                context.setCodeClassifier(save);
216
            }
217
        }
218
219 44144 jjdelcerro
        public RuleRepeatUntilAnyTokens addRule(Rule rule) {
220 44139 jjdelcerro
            this.rules.add(rule);
221
            return this;
222
        }
223
224
        @Override
225
        public String getClassifier() {
226
            String s = String.valueOf(counter).trim();
227
            return s;
228
        }
229
230
        @Override
231
        public String toString() {
232
            return "repeat_until_tokens('" + ArrayUtils.toString(this.exit_tokens) + "') rules:" + StringUtils.join(rules, ",");
233
        }
234
    }
235
236
    public class RuleOptionalIdentifiers implements Rule {
237
238
        private final String id;
239
        private final String separator;
240
241
        public RuleOptionalIdentifiers(String id, String separator) {
242
            this.id = id;
243
            this.separator = separator;
244
        }
245
246
        public void parse(StatementContext context) {
247
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
248
            Token token = context.look_token();
249
            while (token.getType() == Token.IDENTIFIER) {
250
                String identifier = (String) token.getLiteral();
251
                Code code = context.getCodeBuilder().constant(identifier);
252
                args.add(code);
253
                context.next_token();
254
                token = context.look_token();
255
                if (!token.is(this.separator)) {
256
                    break;
257
                }
258
                context.next_token();
259
                token = context.look_token();
260
            }
261
            Code code = null;
262
            if (args.size() != 0) {
263
                code = context.getCodeBuilder().function(ListFunction.NAME, args);
264
            }
265
            context.setCode(id, code);
266
        }
267
268
        @Override
269
        public String toString() {
270
            return "optional_identifiers('" + id + "', '" + this.separator + "')";
271
        }
272
    }
273
274
    private static class ArgsBuilderFromNames implements ArgsBuilder {
275
276
        private final String[] argNames;
277
278
        public ArgsBuilderFromNames(String[] argNames) {
279
            this.argNames = argNames;
280
        }
281
282
        public Codes build(StatementContext context) {
283
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
284
            for (String argName : argNames) {
285
                if (argName.contains("#")) {
286
                    int n = 1;
287
                    while (true) {
288
                        String argNameX = StringUtils.replace(argName, "#", String.valueOf(n).trim(), 1);
289
                        Code code = context.getCode(argNameX);
290
                        if (code == null) {
291
                            break;
292
                        }
293
                        args.add(code);
294
                        n++;
295
                    }
296
                } else {
297
                    Code code = context.getCode(argName);
298
                    args.add(code);
299
                }
300
            }
301
            return args;
302
        }
303
    }
304
305
    private static class ArgsBuilderExpand extends ArgsBuilderFromNames {
306
307
        public ArgsBuilderExpand(String[] argNames) {
308
            super(argNames);
309
        }
310
311
        public Codes build(StatementContext context) {
312
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
313
314
            Codes base_args = super.build(context);
315
            for (Code arg : base_args) {
316
                if( arg.code() == Code.CALLER &&
317
                    ((Caller)arg).name().equals(CodeBlockFunction.NAME) ) {
318 44198 jjdelcerro
                    Codes block_args = ((Caller)arg).parameters();
319 44139 jjdelcerro
                    for (Code block_arg : block_args) {
320
                        args.add(block_arg);
321
                    }
322
                } else {
323
                    args.add(arg);
324
                }
325
            }
326
            return args;
327
        }
328
    }
329
330
    public DefaultStatement(String name) {
331
        this.rules = new ArrayList<>();
332
        this.codeId = null;
333
        this.argsBuilder = null;
334
        this.name = name;
335
    }
336
337
    public String getName() {
338
        return name;
339
    }
340
341
    @Override
342 44144 jjdelcerro
    public Rule require_any_token(String... token) {
343
        return new RuleRequireAnyToken(token);
344 44139 jjdelcerro
    }
345
346
    @Override
347
    public Rule require_identifier(String id) {
348
        return new RuleRequireIdentifier(id);
349
    }
350
351
    @Override
352
    public Rule require_expression(String id) {
353
        return new RuleRequireExpression(id);
354
    }
355
356
    @Override
357
    public Rule require_expressions(String id, String separator) {
358
        return new RuleRequiereExpressions(id, separator);
359
    }
360
361
    @Override
362 44144 jjdelcerro
    public ConditionalRule optional_any_token(String... id) {
363
        return new RuleOptionalAnyToken(id);
364 44139 jjdelcerro
    }
365
366
    @Override
367
    public Rule optional_identifiers(String id, String separator) {
368
        return new RuleOptionalIdentifiers(id, separator);
369
    }
370
371
    @Override
372 44144 jjdelcerro
    public CompoundRule repeat_until_any_tokens(String... tokens) {
373
        return new RuleRepeatUntilAnyTokens(tokens);
374 44139 jjdelcerro
    }
375
376
    @Override
377
    public Statement addRule(Rule rule) {
378
        this.rules.add(rule);
379
        return this;
380
    }
381
382
    @Override
383
    public boolean isApplicable(StatementContext context) {
384
        if (this.rules.isEmpty()) {
385
            return false;
386
        }
387
        Rule rule = this.rules.get(0);
388 44144 jjdelcerro
        if (!(rule instanceof RuleRequireAnyToken)) {
389 44139 jjdelcerro
            return false;
390
        }
391 44144 jjdelcerro
        return ((RuleRequireAnyToken) rule).isApplicable(context);
392 44139 jjdelcerro
    }
393
394
    @Override
395
    public ArgsBuilder args_names(String... args) {
396
        ArgsBuilder x = new ArgsBuilderFromNames(args);
397
        return x;
398
    }
399
400
    @Override
401
    public ArgsBuilder args_expand(String... args) {
402
        ArgsBuilder x = new ArgsBuilderExpand(args);
403
        return x;
404
    }
405
406
    @Override
407
    public void code(String id, ArgsBuilder argsBuilder) {
408
        this.codeId = id;
409
        this.argsBuilder = argsBuilder;
410
    }
411
412
    @Override
413
    public Code parse(StatementContext context) {
414
        for (Rule rule : rules) {
415
            rule.parse(context);
416
        }
417
        Codes args = this.argsBuilder.build(context);
418
419
        Code code;
420
        if (codeId == null) {
421
            code = args.get(0);
422
        } else {
423
            if (args.size() == 0) {
424
                code = context.getCodeBuilder().function(codeId, null);
425
            } else {
426
                code = context.getCodeBuilder().function(codeId, args);
427
            }
428
        }
429
        return code;
430
    }
431
432
    @Override
433
    public String toString() {
434
        return this.getName() + " " + StringUtils.join(this.rules, ";");
435
436
    }
437
}