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
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
    public class RuleRequireAnyToken implements Rule {
38

    
39
        private final String[] required_token;
40

    
41
        public RuleRequireAnyToken(String... required_token) {
42
            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
    public class RuleOptionalAnyToken implements ConditionalRule {
147

    
148
        private final String[] optional_token;
149
        private final List<Rule> onTrueRules;
150
        private final List<Rule> onFalseRules;
151

    
152
        public RuleOptionalAnyToken(String... optional_token) {
153
            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
        public RuleOptionalAnyToken addRuleOnTrue(Rule rule) {
173
            this.onTrueRules.add(rule);
174
            return this;
175
        }
176

    
177
        public RuleOptionalAnyToken addRuleOnFalse(Rule rule) {
178
            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
    public class RuleRepeatUntilAnyTokens implements RepeatRule {
189

    
190
        private final String[] exit_tokens;
191
        private final List<Rule> rules;
192
        private int counter;
193

    
194
        public RuleRepeatUntilAnyTokens(String[] exit_tokens) {
195
            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
        public RuleRepeatUntilAnyTokens addRule(Rule rule) {
220
            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
                    Codes block_args = ((Caller)arg).parameters();
319
                    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
    public Rule require_any_token(String... token) {
343
        return new RuleRequireAnyToken(token);
344
    }
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
    public ConditionalRule optional_any_token(String... id) {
363
        return new RuleOptionalAnyToken(id);
364
    }
365

    
366
    @Override
367
    public Rule optional_identifiers(String id, String separator) {
368
        return new RuleOptionalIdentifiers(id, separator);
369
    }
370

    
371
    @Override
372
    public CompoundRule repeat_until_any_tokens(String... tokens) {
373
        return new RuleRepeatUntilAnyTokens(tokens);
374
    }
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
        if (!(rule instanceof RuleRequireAnyToken)) {
389
            return false;
390
        }
391
        return ((RuleRequireAnyToken) rule).isApplicable(context);
392
    }
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
}