root / trunk / extensions / extSymbology / src / org / gvsig / symbology / fmap / labeling / parse / LabelExpressionParser.jj @ 22278
History | View | Annotate | Download (13.2 KB)
1 |
|
---|---|
2 |
options{ |
3 |
STATIC = false; |
4 |
LOOKAHEAD = 1; |
5 |
|
6 |
} |
7 |
PARSER_BEGIN(LabelExpressionParser) |
8 |
|
9 |
/* gvSIG. Sistema de Información Geográfica de la Generalitat Valenciana |
10 |
* |
11 |
* Copyright (C) 2004 IVER T.I. and Generalitat Valenciana. |
12 |
* |
13 |
* This program is free software; you can redistribute it and/or |
14 |
* modify it under the terms of the GNU General Public License |
15 |
* as published by the Free Software Foundation; either version 2 |
16 |
* of the License, or (at your option) any later version. |
17 |
* |
18 |
* This program is distributed in the hope that it will be useful, |
19 |
* but WITHOUT ANY WARRANTY; without even the implied warranty of |
20 |
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
21 |
* GNU General Public License for more details. |
22 |
* |
23 |
* You should have received a copy of the GNU General Public License |
24 |
* along with this program; if not, write to the Free Software |
25 |
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307,USA. |
26 |
* |
27 |
* For more information, contact: |
28 |
* |
29 |
* Generalitat Valenciana |
30 |
* Conselleria d'Infraestructures i Transport |
31 |
* Av. Blasco Ibáñez, 50 |
32 |
* 46010 VALENCIA |
33 |
* SPAIN |
34 |
* |
35 |
* +34 963862235 |
36 |
* gvsig@gva.es |
37 |
* www.gvsig.gva.es |
38 |
* |
39 |
* or |
40 |
* |
41 |
* IVER T.I. S.A |
42 |
* Salamanca 50 |
43 |
* 46005 Valencia |
44 |
* Spain |
45 |
* |
46 |
* +34 963163400 |
47 |
* dac@iver.es |
48 |
*/ |
49 |
package org.gvsig.symbology.fmap.labeling.parse; |
50 |
import java.util.*; |
51 |
import java.io.*; |
52 |
|
53 |
|
54 |
import com.hardcode.gdbms.engine.values.*; |
55 |
import org.gvsig.symbology.fmap.rendering.filter.operations.*; |
56 |
import org.gvsig.symbology.fmap.labeling.parse.*; |
57 |
import org.gvsig.symbology.fmap.labeling.lang.functions.*; |
58 |
/** |
59 |
* @author Pepe Vidal Salvador - jose.vidal.salvador@iver.es |
60 |
* @author Jaume Dominguez Faus - jaume.dominguez@gmail.com |
61 |
* |
62 |
*/ |
63 |
public class LabelExpressionParser{ |
64 |
protected Stack stack = new Stack(); |
65 |
protected static OperatorsFactory operators = OperatorsFactory.getInstance(); |
66 |
protected Hashtable<String, Value> symbols = new Hashtable<String, Value>(); |
67 |
protected ArrayList<String> classNames = new ArrayList<String>(); |
68 |
|
69 |
public ArrayList<String> getClassNames (){ |
70 |
return classNames; |
71 |
} |
72 |
|
73 |
public void addClassName(String name){ |
74 |
|
75 |
for (int i = 0; i < classNames.size(); i++) { |
76 |
if(classNames.get(i).compareTo(name)==0) |
77 |
return; |
78 |
} |
79 |
classNames.add(name); |
80 |
|
81 |
} |
82 |
|
83 |
public Hashtable<String,Value> getSymbols(){ |
84 |
|
85 |
return symbols; |
86 |
|
87 |
} |
88 |
|
89 |
public Object pop() throws ExpressionException { |
90 |
|
91 |
Object popObject = stack.pop(); |
92 |
Object result = ((Expression)popObject).evaluate(symbols); |
93 |
|
94 |
if(result instanceof String) { |
95 |
return new String (result.toString()); |
96 |
} |
97 |
else if (result instanceof Boolean) { |
98 |
return new Boolean (result.toString()); |
99 |
} |
100 |
else if (result instanceof Double) { |
101 |
return Double.valueOf(result.toString()); |
102 |
} |
103 |
else if (result instanceof Integer) { |
104 |
return Integer.valueOf(result.toString()); |
105 |
} |
106 |
return null; |
107 |
|
108 |
} |
109 |
|
110 |
public Stack getStack(){ |
111 |
|
112 |
return this.stack; |
113 |
|
114 |
} |
115 |
|
116 |
public LabelExpressionParser(StringReader reader, Hashtable<String, Value> symbolsTable) { |
117 |
|
118 |
this(reader); |
119 |
this.symbols = symbolsTable; |
120 |
|
121 |
} |
122 |
|
123 |
/** |
124 |
* it is default because it is used in the unit tests |
125 |
* but this method is not part of the public API, so |
126 |
* don't use it! |
127 |
*/ |
128 |
void putSymbol(String string, Value value){ |
129 |
|
130 |
this.symbols.put(string,value); |
131 |
|
132 |
} |
133 |
|
134 |
public static String tokenFor(int tokenCode) { |
135 |
|
136 |
return tokenImage[tokenCode].replaceAll("\"", ""); |
137 |
|
138 |
} |
139 |
|
140 |
public void setOperatorsFactory (OperatorsFactory opFac) { |
141 |
|
142 |
this.operators = opFac; |
143 |
|
144 |
} |
145 |
|
146 |
public static void main(String[]args)throws ParseException,ExpressionException{ |
147 |
|
148 |
Hashtable<String, Value> symbols = new Hashtable<String, Value>(); |
149 |
LabelExpressionParser parser = new LabelExpressionParser(new StringReader("3:4:2:Substring(\"My taylor is rich!\", 3, 9):(true && false);")); |
150 |
symbols.put("RD_6",ValueFactory.createValue(2)); |
151 |
operators.addOperator(IndexOfFunction.class); |
152 |
operators.addOperator(SubstringFunction.class); |
153 |
parser.setOperatorsFactory(operators); |
154 |
parser.LabelExpression(); |
155 |
parser.getStack(); |
156 |
Object[] result = (Object[]) ((Expression)(parser.getStack().pop())).evaluate(symbols); |
157 |
for (int i = 0; i < result.length; i++) { |
158 |
System.out.print(result[i].toString()+"\n"); |
159 |
} |
160 |
} |
161 |
} |
162 |
PARSER_END(LabelExpressionParser) |
163 |
SKIP : |
164 |
{ |
165 |
" " |
166 |
| "\r" |
167 |
| "\t" |
168 |
| "\n" |
169 |
} |
170 |
|
171 |
|
172 |
TOKEN : /* OPERATORS */ |
173 |
{ |
174 |
< PLUS: "+" > |
175 |
| < MINUS: "-" > |
176 |
| < MULTIPLY: "*" > |
177 |
| < DIVIDE: "/" > |
178 |
| < GT: ">" > |
179 |
| < LT: "<" > |
180 |
| < NOT: "!" > |
181 |
| < EQ: "==" > |
182 |
| < LE: "<=" > |
183 |
| < GE: ">=" > |
184 |
| < NE: "!=" > |
185 |
| < OR: "||" > |
186 |
| < AND: "&&" > |
187 |
} |
188 |
TOKEN : /* MISC */ |
189 |
{ |
190 |
< #DOT: "." > |
191 |
| < OPEN_SQ_BRACKETS : "[" > |
192 |
| < CLOSE_SQ_BRACKETS : "]" > |
193 |
| < OPEN_PARENTHESIS : "(" > |
194 |
| < CLOSE_PARENTHESIS : ")" > |
195 |
| < DOUBLE_QUOTE : "\"" > |
196 |
| < COMMA : "," > |
197 |
| < EOFIELD : ":" > |
198 |
| < EOEXPR : ";" > |
199 |
} |
200 |
TOKEN : /* CONSTANTS AND IDENTIFIERS */ |
201 |
{ |
202 |
< BOOLEAN: "true" | "false" > |
203 |
| < NULL: "null"> |
204 |
| < IDENTIFIER: ( <LETTER> ) ( <LETTER>|<DIGIT> )* > |
205 |
| < #LETTER: ( ["_","$","%"] | ( ["a"-"z"] ) | ( ["A"-"Z"] ) ) > |
206 |
} |
207 |
TOKEN : /* NUMBER */ |
208 |
{ |
209 |
< #DIGIT: ["0"-"9"] > |
210 |
| < INTEGER: ( <DIGIT> )+ > |
211 |
| < FLOATING_POINT: (<DIGIT>)+ "." (<DIGIT>)* (<EXPONENT>)? (["f","F","d","D"])? |
212 |
| <DOT> (<DIGIT>)+ (<EXPONENT>)? (["f","F","d","D"])? |
213 |
| (<DIGIT>)+ <EXPONENT> (["f","F","d","D"])? |
214 |
| (<DIGIT>)+ (<EXPONENT>)? ["f","F","d","D"] > |
215 |
| < #EXPONENT: ["e","E"] (["+","-"])? (<DIGIT>)+ > |
216 |
} |
217 |
TOKEN: /* STRING */ |
218 |
{ |
219 |
< STRING: ( <DOUBLE_QUOTE> ( <CHAR_STRING> )* <DOUBLE_QUOTE> )> |
220 |
| < CHAR_STRING : ~[ "\"", ";","\n","\r"] > |
221 |
} |
222 |
|
223 |
|
224 |
TOKEN : /* LABELING TOKENS */ |
225 |
{ |
226 |
< FIELD_IDENTIFIER: <OPEN_SQ_BRACKETS> <CHAR_STRING> <CLOSE_SQ_BRACKETS> > |
227 |
} |
228 |
|
229 |
|
230 |
/* LABEL EXPRESSION */ |
231 |
//We have to use this function if we want to evaluate an String which contains different Expressions |
232 |
//inside |
233 |
void LabelExpression() : |
234 |
{ |
235 |
|
236 |
} |
237 |
{ |
238 |
|
239 |
Expression() ( |
240 |
|
241 |
LOOKAHEAD(2)<EOFIELD> Expression() { |
242 |
Expression leftExpression = (Expression)stack.pop(); |
243 |
Expression rightExpression = (Expression)stack.pop(); |
244 |
|
245 |
Expression labelExpr = new LabelExpressionOperator(); |
246 |
labelExpr.addArgument(0, rightExpression); |
247 |
labelExpr.addArgument(0, leftExpression); |
248 |
|
249 |
stack.push(labelExpr); |
250 |
|
251 |
} |
252 |
| Expression(){ |
253 |
Expression leftExpression2 = (Expression)stack.pop(); |
254 |
Expression rightExpression2 = (Expression)stack.pop(); |
255 |
|
256 |
Expression fieldExpr = new FieldExpressionOperator(); |
257 |
fieldExpr.addArgument(0, rightExpression2); |
258 |
fieldExpr.addArgument(0, leftExpression2); |
259 |
|
260 |
stack.push(fieldExpr); |
261 |
})* |
262 |
// <EOEXPR> |
263 |
|
264 |
//| <EOEXPR> |
265 |
|
266 |
} |
267 |
|
268 |
void Expression():{}{ |
269 |
AndExpression()(<OR>AndExpression(){ |
270 |
Expression leftExpression = (Expression)stack.pop(); |
271 |
Expression rightExpression = (Expression)stack.pop(); |
272 |
|
273 |
Expression orExpr = new OrOperator(); |
274 |
orExpr.addArgument(0, rightExpression); |
275 |
orExpr.addArgument(0, leftExpression); |
276 |
|
277 |
stack.push(orExpr); |
278 |
|
279 |
} |
280 |
)* |
281 |
} |
282 |
void AndExpression():{ |
283 |
Token x; |
284 |
} |
285 |
{ |
286 |
EqCompExpression()((x = <AND>)EqCompExpression(){ |
287 |
Expression rightExpression = (Expression)stack.pop(); |
288 |
Expression leftExpression = (Expression)stack.pop(); |
289 |
|
290 |
Expression func = new AndOperator(); |
291 |
|
292 |
func.addArgument(0, rightExpression); |
293 |
func.addArgument(0, leftExpression); |
294 |
|
295 |
stack.push(func); |
296 |
} |
297 |
)* |
298 |
} |
299 |
void EqCompExpression():{ |
300 |
Token x; |
301 |
} |
302 |
{ |
303 |
ComparisonExpression()((x = <EQ> |
304 |
| x = <NE>)ComparisonExpression(){ |
305 |
Expression rightExpression = (Expression)stack.pop(); |
306 |
Expression leftExpression = (Expression)stack.pop(); |
307 |
Expression func = null; |
308 |
|
309 |
if (x.kind == EQ)func = new EqOperator(); |
310 |
else if (x.kind == NE)func = new NeOperator(); |
311 |
|
312 |
func.addArgument(0, rightExpression); |
313 |
func.addArgument(0, leftExpression); |
314 |
|
315 |
stack.push(func); |
316 |
} |
317 |
)* |
318 |
} |
319 |
void ComparisonExpression():{ |
320 |
Token x; |
321 |
} |
322 |
{ |
323 |
AdditiveExpression()((x = <LT> |
324 |
| x = <LE> |
325 |
| x = <GT> |
326 |
| x = <GE>)AdditiveExpression(){ |
327 |
Expression rightExpression = (Expression)stack.pop(); |
328 |
Expression leftExpression = (Expression)stack.pop(); |
329 |
Expression func = null; |
330 |
|
331 |
|
332 |
if (x.kind == LT)func = new LessThanOperator(); |
333 |
else if (x.kind == LE)func = new LessThanOrEqualsOperator(); |
334 |
else if (x.kind == GT)func = new GreaterThanOperator(); |
335 |
else if (x.kind == GE)func = new GreaterThanOrEqualsOperator(); |
336 |
|
337 |
func.addArgument(0, rightExpression); |
338 |
func.addArgument(0, leftExpression); |
339 |
|
340 |
stack.push(func); |
341 |
} |
342 |
)* |
343 |
} |
344 |
void AdditiveExpression():{ |
345 |
Token x; |
346 |
} |
347 |
{ |
348 |
MultiplicativeExpression()((x = <PLUS> |
349 |
| x = <MINUS>)MultiplicativeExpression(){ |
350 |
Expression rightExpression = (Expression)stack.pop(); |
351 |
Expression leftExpression = (Expression)stack.pop(); |
352 |
Expression func = null; |
353 |
|
354 |
if (x.kind == PLUS)func = new AddOperator(); |
355 |
else func = new MinusOperator(); |
356 |
|
357 |
func.addArgument(0, rightExpression); |
358 |
func.addArgument(0, leftExpression); |
359 |
|
360 |
stack.push(func); |
361 |
} |
362 |
)* |
363 |
} |
364 |
void MultiplicativeExpression():{ |
365 |
Token x; |
366 |
} |
367 |
{ |
368 |
UnaryElement()((x = <MULTIPLY> |
369 |
| x = <DIVIDE>)UnaryElement(){ |
370 |
try{ |
371 |
Expression A = (Expression) stack.pop(); |
372 |
Expression B = (Expression) stack.pop(); |
373 |
boolean aInt = (((Expression) A).evaluate(symbols) instanceof Integer); |
374 |
boolean bInt = (((Expression) B).evaluate(symbols) instanceof Integer); |
375 |
if (aInt && bInt) { |
376 |
int a = (Integer) A.evaluate(symbols); |
377 |
int b = (Integer) B.evaluate(symbols); |
378 |
if (x.kind == MULTIPLY) |
379 |
stack.push(new NumericalConstant(new Integer(b * a))); |
380 |
else |
381 |
stack.push(new NumericalConstant(new Integer(b / a))); |
382 |
} else { |
383 |
|
384 |
double a = new Double(((Expression)A).evaluate(symbols).toString()); |
385 |
double b = new Double(((Expression)B).evaluate(symbols).toString()); |
386 |
if (x.kind == MULTIPLY) |
387 |
stack.push(new NumericalConstant(new Double(b * a))); |
388 |
else |
389 |
stack.push(new NumericalConstant(new Double(b / a))); |
390 |
}}catch (ClassCastException ex) { |
391 |
ex.printStackTrace(); |
392 |
} catch (ExpressionException e) { |
393 |
e.printStackTrace(); |
394 |
} |
395 |
|
396 |
})* |
397 |
} |
398 |
void UnaryElement():{ |
399 |
Token x = null; |
400 |
} |
401 |
{ |
402 |
(x = <PLUS> |
403 |
| x = <MINUS>)UnaryElement(){ |
404 |
try{ |
405 |
Object A = stack.pop(); |
406 |
if ((((Expression) A).evaluate(symbols) instanceof Integer)) { |
407 |
int a = (Integer) ((Expression) A).evaluate(symbols); |
408 |
if (x.kind == PLUS) |
409 |
stack.push(new NumericalConstant(new Integer(a))); |
410 |
else |
411 |
stack.push(new NumericalConstant(new Integer(-a))); |
412 |
} else { |
413 |
double a = (Double) ((Expression) A).evaluate(symbols); |
414 |
if (x.kind == PLUS) |
415 |
stack.push(new NumericalConstant(new Double(a))); |
416 |
else |
417 |
stack.push(new NumericalConstant(new Double(-a))); |
418 |
} |
419 |
} catch (ClassCastException ex) { |
420 |
ex.printStackTrace(); |
421 |
}catch (ExpressionException ex) { |
422 |
ex.printStackTrace(); |
423 |
} |
424 |
} |
425 |
|
426 |
| BooleanUnaryElement() |
427 |
} |
428 |
|
429 |
void BooleanUnaryElement(): |
430 |
{ |
431 |
Token t; |
432 |
} |
433 |
{ |
434 |
t = <NOT> UnaryElement() { |
435 |
Expression rightExpression = (Expression)stack.pop(); |
436 |
Expression func = new NotOperator(); |
437 |
func.addArgument(0, rightExpression); |
438 |
stack.push(func); |
439 |
} |
440 |
| Element() |
441 |
} |
442 |
|
443 |
|
444 |
void Element():{ |
445 |
Token x; |
446 |
String y = "[$,A-Z,_,a-z]([$,A-Z,_,a-z]|[0-9])*"; |
447 |
} |
448 |
{ |
449 |
|
450 |
("["x = <IDENTIFIER>"]"){ |
451 |
|
452 |
ReplaceOperator func = new ReplaceOperator(); |
453 |
func.addArgument(x.image); |
454 |
stack.push(func); |
455 |
addClassName(x.image); |
456 |
|
457 |
} |
458 |
| (x = <INTEGER>){ |
459 |
NumericalConstant intC = new NumericalConstant(Integer.valueOf(x.image)); |
460 |
stack.push(intC); |
461 |
} |
462 |
| (x = <FLOATING_POINT>){ |
463 |
NumericalConstant doubleC = new NumericalConstant(Double.valueOf(x.image)); |
464 |
stack.push(doubleC); |
465 |
} |
466 |
|(x = <STRING>) { |
467 |
StringConstant stringValue = new StringConstant(x.image.substring(1, x.image.length()-1)); |
468 |
stack.push(stringValue); |
469 |
} |
470 |
| (x = <BOOLEAN>){ |
471 |
BooleanConstant boolValue = new BooleanConstant(x.image); |
472 |
stack.push(boolValue); |
473 |
} |
474 |
| x = <NULL>{ |
475 |
NullConstant nullValue = new NullConstant(); |
476 |
stack.push(nullValue); |
477 |
} |
478 |
| LOOKAHEAD(2)function() |
479 |
| "("Expression()")" |
480 |
} |
481 |
void function():{ |
482 |
String functionName; |
483 |
int argCount = 0; |
484 |
Expression function; |
485 |
Token x; |
486 |
} |
487 |
{ |
488 |
LOOKAHEAD(2) |
489 |
<IDENTIFIER>{ |
490 |
functionName = token.image; |
491 |
} |
492 |
argCount = Arguments(){ |
493 |
try { |
494 |
function = (Expression) operators.functions.get(functionName).newInstance(); |
495 |
} |
496 |
catch (Exception e){ |
497 |
throw new ParseException("Problem with function '"+functionName+"': "+e.toString()); |
498 |
} |
499 |
if (function == null)throw new ParseException("Nonexisting function name '"+functionName+"'"); |
500 |
for (int i = 0; |
501 |
i<argCount; |
502 |
i++){ |
503 |
Expression arg = (Expression)stack.pop(); |
504 |
function.addArgument(0, arg); |
505 |
} |
506 |
stack.push(function); |
507 |
} |
508 |
|(x = <IDENTIFIER>){ |
509 |
StringConstant stringValue = new StringConstant(x.image); |
510 |
stack.push(stringValue); |
511 |
} |
512 |
} |
513 |
int Arguments():{ |
514 |
int argCount = 0; |
515 |
} |
516 |
{ |
517 |
<OPEN_PARENTHESIS>[argCount = ArgumentList()]<CLOSE_PARENTHESIS>{ |
518 |
return argCount; |
519 |
} |
520 |
} |
521 |
int ArgumentList():{ |
522 |
int argCount = 0; |
523 |
} |
524 |
{ |
525 |
Expression(){ |
526 |
argCount++; |
527 |
} |
528 |
(<COMMA>Expression(){ |
529 |
argCount++; |
530 |
} |
531 |
)*{ |
532 |
return argCount; |
533 |
} |
534 |
} |