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

History | View | Annotate | Download (13.4 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 static org.gvsig.expressionevaluator.ExpressionBuilder.FUNCTION_LIST;
11
import org.gvsig.expressionevaluator.ExpressionSyntaxException;
12
import org.gvsig.expressionevaluator.LexicalAnalyzer.Token;
13
import org.gvsig.expressionevaluator.Statement;
14
import org.gvsig.expressionevaluator.Statement.CompoundRule;
15
import org.gvsig.expressionevaluator.Statement.ConditionalRule;
16
import org.gvsig.expressionevaluator.Statement.Rule;
17
import org.gvsig.expressionevaluator.Statement.StatementContext;
18
import org.gvsig.expressionevaluator.impl.function.programming.CodeBlockFunction;
19
import org.gvsig.expressionevaluator.impl.DefaultCodeBuilder.BaseCodes;
20
import org.gvsig.expressionevaluator.impl.function.programming.ListFunction;
21

    
22
/**
23
 *
24
 * @author jjdelcerro
25
 */
26
public class DefaultStatement implements Statement {
27

    
28
    private final List<Rule> rules;
29
    private String codeId;
30
    private ArgsBuilder argsBuilder;
31
    private final String name;
32

    
33
    public interface RepeatRule extends CompoundRule {
34

    
35
        public String getClassifier();
36
    }
37

    
38
    public class RuleRequireAnyToken implements Rule {
39

    
40
        private final String[] required_token;
41

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

    
46
        public void parse(StatementContext context) {
47
            Token token = context.look_token();
48
            if (!token.is(this.required_token)) {
49
                throw new ExpressionSyntaxException(
50
                        I18N.A_XTokenX_was_expected_and_XliteralX_was_found(
51
                                StringUtils.join(this.required_token),
52
                                token.getLiteral()
53
                        ),
54
                        context.getLexicalAnalyzer()
55
                );
56
            }
57
            context.next_token();
58
        }
59

    
60
        private boolean isApplicable(StatementContext context) {
61
            Token token = context.look_token();
62
            return token.is(this.required_token);
63
        }
64

    
65
        @Override
66
        public String toString() {
67
            return "require_token(" + StringUtils.join(this.required_token) + ")";
68
        }
69

    
70
    }
71

    
72
    public class RuleRequireIdentifier implements Rule {
73

    
74
        private final String id;
75

    
76
        public RuleRequireIdentifier(String id) {
77
            this.id = id;
78
        }
79

    
80
        public void parse(StatementContext context) {
81
            Token token = context.look_token();
82
            if (token.getType() != Token.IDENTIFIER) {
83
                throw new ExpressionSyntaxException(
84
                        I18N.An_identifier_was_expected_and_XliteralX_was_found(token.getLiteral()),
85
                        context.getLexicalAnalyzer()
86
                );
87
            }
88
            String identifier = (String) token.getLiteral();
89
            Code code = context.getCodeBuilder().constant(identifier);
90
            context.setCode(id, code);
91
            context.next_token();
92
        }
93

    
94
        @Override
95
        public String toString() {
96
            return "require_identifier('" + this.id + "')";
97
        }
98
    }
99

    
100
    public class RuleRequireExpression implements Rule {
101

    
102
        private final String id;
103

    
104
        public RuleRequireExpression(String id) {
105
            this.id = id;
106
        }
107

    
108
        public void parse(StatementContext context) {
109
            Code code = context.parse_expression();
110
            if (code == null) {
111
                throw new ExpressionSyntaxException(context.getLexicalAnalyzer());
112
            }
113
            context.setCode(id, code);
114
        }
115

    
116
        @Override
117
        public String toString() {
118
            return "require_expression('" + this.id + "')";
119
        }
120
    }
121

    
122
    public class RuleRequiereExpressions implements Rule {
123

    
124
        private final String id;
125
        private final String separator;
126

    
127
        public RuleRequiereExpressions(String id, String separator) {
128
            this.id = id;
129
            this.separator = separator;
130
        }
131

    
132
        public void parse(StatementContext context) {
133
            Codes codes = context.parse_expressions(this.separator);
134
            if (codes == null) {
135
                throw new ExpressionSyntaxException(context.getLexicalAnalyzer());
136
            }
137
            Code code = context.getCodeBuilder().function(CodeBlockFunction.NAME, codes);
138
            context.setCode(id, code);
139
        }
140

    
141
        @Override
142
        public String toString() {
143
            return "require_expressions('" + this.id + "', '" + this.separator + "')";
144
        }
145
    }
146

    
147
    public class RuleOptionalAnyToken implements ConditionalRule {
148

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

    
153
        public RuleOptionalAnyToken(String... optional_token) {
154
            this.optional_token = optional_token;
155
            this.onTrueRules = new ArrayList<>();
156
            this.onFalseRules = new ArrayList<>();
157
        }
158

    
159
        public void parse(StatementContext context) {
160
            Token token = context.look_token();
161
            if (token.is(this.optional_token)) {
162
                context.next_token();
163
                for (Rule rule : this.onTrueRules) {
164
                    rule.parse(context);
165
                }
166
            } else {
167
                for (Rule rule : this.onFalseRules) {
168
                    rule.parse(context);
169
                }
170
            }
171
        }
172

    
173
        public RuleOptionalAnyToken addRuleOnTrue(Rule rule) {
174
            this.onTrueRules.add(rule);
175
            return this;
176
        }
177

    
178
        public RuleOptionalAnyToken addRuleOnFalse(Rule rule) {
179
            this.onFalseRules.add(rule);
180
            return this;
181
        }
182

    
183
        @Override
184
        public String toString() {
185
            return "optional_token(" + StringUtils.join(this.optional_token) + ") rules:" + StringUtils.join(onTrueRules, ",");
186
        }
187
    }
188

    
189
    public class RuleRepeatUntilAnyTokens implements RepeatRule {
190

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

    
195
        public RuleRepeatUntilAnyTokens(String[] exit_tokens) {
196
            this.exit_tokens = exit_tokens;
197
            this.rules = new ArrayList<>();
198
        }
199

    
200
        public void parse(StatementContext context) {
201
            String save = context.getCodeClassifier();
202
            try {
203
                this.counter = 1;
204
                while (true) {
205
                    Token token = context.look_token();
206
                    if (token.is(this.exit_tokens)) {
207
                        break;
208
                    }
209
                    context.setCodeClassifier(String.valueOf(counter).trim());
210
                    for (Rule rule : rules) {
211
                        rule.parse(context);
212
                    }
213
                    this.counter = this.counter + 1;
214
                }
215
            } finally {
216
                context.setCodeClassifier(save);
217
            }
218
        }
219

    
220
        public RuleRepeatUntilAnyTokens addRule(Rule rule) {
221
            this.rules.add(rule);
222
            return this;
223
        }
224

    
225
        @Override
226
        public String getClassifier() {
227
            String s = String.valueOf(counter).trim();
228
            return s;
229
        }
230

    
231
        @Override
232
        public String toString() {
233
            return "repeat_until_tokens('" + ArrayUtils.toString(this.exit_tokens) + "') rules:" + StringUtils.join(rules, ",");
234
        }
235
    }
236

    
237
    public class RuleOptionalIdentifiers implements Rule {
238

    
239
        private final String id;
240
        private final String separator;
241

    
242
        public RuleOptionalIdentifiers(String id, String separator) {
243
            this.id = id;
244
            this.separator = separator;
245
        }
246

    
247
        public void parse(StatementContext context) {
248
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
249
            Token token = context.look_token();
250
            while (token.getType() == Token.IDENTIFIER) {
251
                String identifier = (String) token.getLiteral();
252
                Code code = context.getCodeBuilder().constant(identifier);
253
                args.add(code);
254
                context.next_token();
255
                token = context.look_token();
256
                if (!token.is(this.separator)) {
257
                    break;
258
                }
259
                context.next_token();
260
                token = context.look_token();
261
            }
262
            Code code = null;
263
            if (args.size() != 0) {
264
                code = context.getCodeBuilder().function(FUNCTION_LIST, args);
265
            }
266
            context.setCode(id, code);
267
        }
268

    
269
        @Override
270
        public String toString() {
271
            return "optional_identifiers('" + id + "', '" + this.separator + "')";
272
        }
273
    }
274

    
275
    private static class ArgsBuilderFromNames implements ArgsBuilder {
276

    
277
        private final String[] argNames;
278

    
279
        public ArgsBuilderFromNames(String[] argNames) {
280
            this.argNames = argNames;
281
        }
282

    
283
        public Codes build(StatementContext context) {
284
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
285
            for (String argName : argNames) {
286
                if (argName.contains("#")) {
287
                    int n = 1;
288
                    while (true) {
289
                        String argNameX = StringUtils.replace(argName, "#", String.valueOf(n).trim(), 1);
290
                        Code code = context.getCode(argNameX);
291
                        if (code == null) {
292
                            break;
293
                        }
294
                        args.add(code);
295
                        n++;
296
                    }
297
                } else {
298
                    Code code = context.getCode(argName);
299
                    args.add(code);
300
                }
301
            }
302
            return args;
303
        }
304
    }
305

    
306
    private static class ArgsBuilderExpand extends ArgsBuilderFromNames {
307

    
308
        public ArgsBuilderExpand(String[] argNames) {
309
            super(argNames);
310
        }
311

    
312
        public Codes build(StatementContext context) {
313
            BaseCodes args = (BaseCodes) context.getCodeBuilder().args();
314
            
315
            Codes base_args = super.build(context);
316
            for (Code arg : base_args) {
317
                if( arg.code() == Code.CALLER && 
318
                    ((Caller)arg).name().equals(CodeBlockFunction.NAME) ) {
319
                    Codes block_args = ((Caller)arg).parameters();
320
                    for (Code block_arg : block_args) {
321
                        args.add(block_arg);
322
                    }
323
                } else {
324
                    args.add(arg);
325
                }
326
            }
327
            return args;
328
        }
329
    }
330

    
331
    public DefaultStatement(String name) {
332
        this.rules = new ArrayList<>();
333
        this.codeId = null;
334
        this.argsBuilder = null;
335
        this.name = name;
336
    }
337

    
338
    public String getName() {
339
        return name;
340
    }
341

    
342
    @Override
343
    public Rule require_any_token(String... token) {
344
        return new RuleRequireAnyToken(token);
345
    }
346

    
347
    @Override
348
    public Rule require_identifier(String id) {
349
        return new RuleRequireIdentifier(id);
350
    }
351

    
352
    @Override
353
    public Rule require_expression(String id) {
354
        return new RuleRequireExpression(id);
355
    }
356

    
357
    @Override
358
    public Rule require_expressions(String id, String separator) {
359
        return new RuleRequiereExpressions(id, separator);
360
    }
361

    
362
    @Override
363
    public ConditionalRule optional_any_token(String... id) {
364
        return new RuleOptionalAnyToken(id);
365
    }
366

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

    
372
    @Override
373
    public CompoundRule repeat_until_any_tokens(String... tokens) {
374
        return new RuleRepeatUntilAnyTokens(tokens);
375
    }
376

    
377
    @Override
378
    public Statement addRule(Rule rule) {
379
        this.rules.add(rule);
380
        return this;
381
    }
382

    
383
    @Override
384
    public boolean isApplicable(StatementContext context) {
385
        if (this.rules.isEmpty()) {
386
            return false;
387
        }
388
        Rule rule = this.rules.get(0);
389
        if (!(rule instanceof RuleRequireAnyToken)) {
390
            return false;
391
        }
392
        return ((RuleRequireAnyToken) rule).isApplicable(context);
393
    }
394

    
395
    @Override
396
    public ArgsBuilder args_names(String... args) {
397
        ArgsBuilder x = new ArgsBuilderFromNames(args);
398
        return x;
399
    }
400
    
401
    @Override
402
    public ArgsBuilder args_expand(String... args) {
403
        ArgsBuilder x = new ArgsBuilderExpand(args);
404
        return x;
405
    }
406
    
407
    @Override
408
    public void code(String id, ArgsBuilder argsBuilder) {
409
        this.codeId = id;
410
        this.argsBuilder = argsBuilder;
411
    }
412

    
413
    @Override
414
    public Code parse(StatementContext context) {
415
        for (Rule rule : rules) {
416
            rule.parse(context);
417
        }
418
        Codes args = this.argsBuilder.build(context);
419
        
420
        Code code;
421
        if (codeId == null) {
422
            code = args.get(0);
423
        } else {
424
            if (args.size() == 0) {
425
                code = context.getCodeBuilder().function(codeId, null);
426
            } else {
427
                code = context.getCodeBuilder().function(codeId, args);
428
            }
429
        }
430
        return code;
431
    }
432

    
433
    @Override
434
    public String toString() {
435
        return this.getName() + " " + StringUtils.join(this.rules, ";");
436

    
437
    }
438
}