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 @ 44397
History | View | Annotate | Download (16.3 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 | public class RuleRequireExpression implements Rule { |
||
104 | |||
105 | private final String id; |
||
106 | |||
107 | public RuleRequireExpression(String id) { |
||
108 | this.id = id;
|
||
109 | } |
||
110 | |||
111 | 44379 | jjdelcerro | @Override
|
112 | 44139 | jjdelcerro | 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 | 44379 | jjdelcerro | |
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 | 44139 | jjdelcerro | 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 | 44379 | jjdelcerro | @Override
|
163 | 44139 | jjdelcerro | 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 | 44379 | jjdelcerro | Code code; |
169 | if( codes.size()==1 ) { |
||
170 | code = codes.get(0);
|
||
171 | } else {
|
||
172 | code = context.getCodeBuilder().function(CodeBlockFunction.NAME, codes); |
||
173 | } |
||
174 | 44139 | jjdelcerro | context.setCode(id, code); |
175 | } |
||
176 | |||
177 | @Override
|
||
178 | public String toString() { |
||
179 | return "require_expressions('" + this.id + "', '" + this.separator + "')"; |
||
180 | } |
||
181 | } |
||
182 | |||
183 | 44144 | jjdelcerro | public class RuleOptionalAnyToken implements ConditionalRule { |
184 | 44139 | jjdelcerro | |
185 | private final String[] optional_token; |
||
186 | private final List<Rule> onTrueRules; |
||
187 | private final List<Rule> onFalseRules; |
||
188 | |||
189 | 44144 | jjdelcerro | public RuleOptionalAnyToken(String... optional_token) { |
190 | 44139 | jjdelcerro | this.optional_token = optional_token;
|
191 | this.onTrueRules = new ArrayList<>(); |
||
192 | this.onFalseRules = new ArrayList<>(); |
||
193 | } |
||
194 | |||
195 | 44379 | jjdelcerro | @Override
|
196 | 44139 | jjdelcerro | 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 | 44379 | jjdelcerro | @Override
|
211 | 44144 | jjdelcerro | public RuleOptionalAnyToken addRuleOnTrue(Rule rule) {
|
212 | 44139 | jjdelcerro | this.onTrueRules.add(rule);
|
213 | return this; |
||
214 | } |
||
215 | |||
216 | 44379 | jjdelcerro | @Override
|
217 | 44144 | jjdelcerro | public RuleOptionalAnyToken addRuleOnFalse(Rule rule) {
|
218 | 44139 | jjdelcerro | 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 | 44144 | jjdelcerro | public class RuleRepeatUntilAnyTokens implements RepeatRule { |
229 | 44139 | jjdelcerro | |
230 | private final String[] exit_tokens; |
||
231 | private final List<Rule> rules; |
||
232 | private int counter; |
||
233 | |||
234 | 44144 | jjdelcerro | public RuleRepeatUntilAnyTokens(String[] exit_tokens) { |
235 | 44139 | jjdelcerro | this.exit_tokens = exit_tokens;
|
236 | this.rules = new ArrayList<>(); |
||
237 | } |
||
238 | |||
239 | 44379 | jjdelcerro | @Override
|
240 | 44139 | jjdelcerro | 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 | 44379 | jjdelcerro | @Override
|
261 | 44144 | jjdelcerro | public RuleRepeatUntilAnyTokens addRule(Rule rule) {
|
262 | 44139 | jjdelcerro | 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 | 44379 | jjdelcerro | @Override
|
289 | 44139 | jjdelcerro | 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 | 44384 | jjdelcerro | if( context.isReservedWord(identifier) ) {
|
295 | break;
|
||
296 | } |
||
297 | 44139 | jjdelcerro | 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 | 44262 | jjdelcerro | code = context.getCodeBuilder().function(FUNCTION_LIST, args); |
310 | 44139 | jjdelcerro | } |
311 | context.setCode(id, code); |
||
312 | } |
||
313 | |||
314 | @Override
|
||
315 | public String toString() { |
||
316 | return "optional_identifiers('" + id + "', '" + this.separator + "')"; |
||
317 | } |
||
318 | } |
||
319 | |||
320 | 44384 | jjdelcerro | public static class ArgsBuilderFromNames implements ArgsBuilder { |
321 | 44139 | jjdelcerro | |
322 | private final String[] argNames; |
||
323 | |||
324 | 44384 | jjdelcerro | public ArgsBuilderFromNames(String... argNames) { |
325 | 44139 | jjdelcerro | this.argNames = argNames;
|
326 | } |
||
327 | |||
328 | 44379 | jjdelcerro | @Override
|
329 | 44139 | jjdelcerro | 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 | 44384 | jjdelcerro | if( code != null) { |
346 | args.add(code); |
||
347 | } |
||
348 | 44139 | jjdelcerro | } |
349 | } |
||
350 | return args;
|
||
351 | } |
||
352 | } |
||
353 | |||
354 | 44384 | jjdelcerro | public static class ArgsBuilderExpand extends ArgsBuilderFromNames { |
355 | 44139 | jjdelcerro | |
356 | 44384 | jjdelcerro | public ArgsBuilderExpand(String... argNames) { |
357 | 44139 | jjdelcerro | super(argNames);
|
358 | } |
||
359 | |||
360 | 44379 | jjdelcerro | @Override
|
361 | 44139 | jjdelcerro | 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 | 44198 | jjdelcerro | Codes block_args = ((Caller)arg).parameters(); |
369 | 44139 | jjdelcerro | 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 | 44384 | jjdelcerro | 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 | 44139 | jjdelcerro | public DefaultStatement(String name) { |
429 | this.rules = new ArrayList<>(); |
||
430 | 44384 | jjdelcerro | this.stmtBuilder = null; |
431 | 44139 | jjdelcerro | this.name = name;
|
432 | } |
||
433 | |||
434 | 44379 | jjdelcerro | @Override
|
435 | 44139 | jjdelcerro | public String getName() { |
436 | return name;
|
||
437 | } |
||
438 | |||
439 | @Override
|
||
440 | 44144 | jjdelcerro | public Rule require_any_token(String... token) { |
441 | return new RuleRequireAnyToken(token); |
||
442 | 44139 | jjdelcerro | } |
443 | |||
444 | @Override
|
||
445 | public Rule require_identifier(String id) { |
||
446 | return new RuleRequireIdentifier(id); |
||
447 | } |
||
448 | |||
449 | @Override
|
||
450 | 44379 | jjdelcerro | public Rule set_expression(String id, Object value) { |
451 | return new RuleSetExpression(id, value); |
||
452 | } |
||
453 | |||
454 | @Override
|
||
455 | 44139 | jjdelcerro | 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 | 44144 | jjdelcerro | public ConditionalRule optional_any_token(String... id) { |
466 | return new RuleOptionalAnyToken(id); |
||
467 | 44139 | jjdelcerro | } |
468 | |||
469 | @Override
|
||
470 | public Rule optional_identifiers(String id, String separator) { |
||
471 | return new RuleOptionalIdentifiers(id, separator); |
||
472 | } |
||
473 | |||
474 | @Override
|
||
475 | 44144 | jjdelcerro | public CompoundRule repeat_until_any_tokens(String... tokens) { |
476 | return new RuleRepeatUntilAnyTokens(tokens); |
||
477 | 44139 | jjdelcerro | } |
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 | 44144 | jjdelcerro | if (!(rule instanceof RuleRequireAnyToken)) { |
492 | 44139 | jjdelcerro | return false; |
493 | } |
||
494 | 44144 | jjdelcerro | return ((RuleRequireAnyToken) rule).isApplicable(context);
|
495 | 44139 | jjdelcerro | } |
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 | 44384 | jjdelcerro | public void code(final String id, final ArgsBuilder argsBuilder) { |
511 | this.builder(new StatementBuilderBase(id, argsBuilder)); |
||
512 | 44139 | jjdelcerro | } |
513 | |||
514 | 44384 | jjdelcerro | public void builder(StatementBuilder builder) { |
515 | this.stmtBuilder = builder;
|
||
516 | } |
||
517 | |||
518 | 44139 | jjdelcerro | @Override
|
519 | public Code parse(StatementContext context) {
|
||
520 | 44379 | jjdelcerro | // System.err.println("start parse "+this.getName());
|
521 | 44139 | jjdelcerro | for (Rule rule : rules) {
|
522 | rule.parse(context); |
||
523 | } |
||
524 | 44384 | jjdelcerro | Code code = this.stmtBuilder.build(context);
|
525 | 44139 | jjdelcerro | return code;
|
526 | } |
||
527 | |||
528 | @Override
|
||
529 | public String toString() { |
||
530 | return this.getName() + " " + StringUtils.join(this.rules, ";"); |
||
531 | |||
532 | } |
||
533 | } |