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 | } |