Statistics
| Revision:

svn-gvsig-desktop / trunk / extSymbology / src / org / gvsig / symbology / fmap / labeling / parse / LabelExpressionParser.jj @ 18755

History | View | Annotate | Download (13.1 KB)

1
/**
2
 * JavaCC file
3
 */
4
 
5
options {
6
  JDK_VERSION = "1.5";
7
  STATIC = false;
8
}
9
PARSER_BEGIN(LabelExpressionParser)
10
package org.gvsig.symbology.fmap.labeling.parse;
11

    
12
import org.apache.log4j.Logger;
13
import com.hardcode.gdbms.engine.instruction.EvaluationException;
14
import com.hardcode.gdbms.engine.values.*;
15
import java.io.*;
16
import java.util.*;
17
import org.gvsig.symbology.fmap.labeling.lang.Symbol;
18
import org.gvsig.symbology.fmap.labeling.lang.Function;
19

    
20

    
21
public class LabelExpressionParser {  
22
	private static Hashtable<String, Function> function_table = new Hashtable<String, Function>(); 
23

    
24
	private Hashtable<String, Symbol> symbol_table = new Hashtable<String, Symbol>();
25
	private Stack stack = new Stack();
26
	
27
	public static void addFunction(Class functionClass) {
28
		try {
29
			Function f = (Function) functionClass.newInstance();
30
			function_table.put(f.getName(), f);
31
		} catch (Exception e) {
32
			Logger.getLogger(LabelExpressionParser.class).error("couldn't install function '"+functionClass.getName(), e);
33
		};
34
	}
35
	
36
	public Object pop() {
37
		return stack.pop();
38
	}
39
	
40
	public static void main(String args[]) throws ParseException {
41

    
42
           LabelExpressionParser parser = new LabelExpressionParser(System.in);
43
           
44
           parser.putSymbol(new Symbol(
45
           						"TIPNOMCALL", 
46
           						Symbol.DATA_TYPE_STRING,
47
           						ValueFactory.createValue("Yaba daba doo...")
48
           						)
49
           					); 
50
           parser.putSymbol(new Symbol(
51
           						"LONGITUD", 
52
           						Symbol.DATA_TYPE_FLOATING,
53
           						ValueFactory.createValue(4.0)
54
           						)
55
           					); 
56
           while (true) {
57
        	try {
58
				String[] texts = parser.LabelExpression();
59
				for (int i = 0; i < texts.length; i++) {
60
					System.out.println("Text at field "+i+": "+texts[i]);
61
				}
62
        	} catch (ParseException e) {
63
        		System.err.println(e.getMessage());
64
        		System.exit(-1);
65
        	}
66
           }
67
	}
68
	
69
	public void putSymbol(Symbol sym) {
70
		symbol_table.put(sym.getName(), sym);
71
	}
72
}
73

    
74
class LabelField {
75
	String text;
76
	int pos;
77
	
78
	public LabelField(String text, int pos) {
79
		this.text = text;
80
		this.pos = pos;
81
	}
82
}
83

    
84
class LabelFieldComparator implements Comparator<LabelField> {
85
	public int compare(LabelField o1, LabelField o2) {
86
		if (o1 != null && o2 == null) return -1;
87
		if (o1 == null && o2 != null) return  1;
88
		if (o1 == null && o2 == null) return  0;
89
		if (o1.pos <= o2.pos) return -1;
90
		else return 1;
91
	}
92
}
93
PARSER_END(LabelExpressionParser)
94

    
95
SKIP :
96
{
97
 	" "
98
|	"\r"
99
|	"\t"
100
|	"\n"
101
}
102

    
103

    
104
TOKEN : /* OPERATORS */
105
{
106
	< PLUS: "+" >
107
|	< MINUS: "-" >
108
|	< MULTIPLY: "*" >
109
|	< DIVIDE: "/" >
110
|	< GT: ">" >
111
|	< LT: "<" >
112
|	< NOT: "!" >
113
|	< EQ: "==" >
114
|	< LE: "<=" >
115
|	< GE: ">=" >
116
|	< NE: "!=" >
117
|	< OR: "||" >
118
|	< AND: "&&" >
119
}
120
TOKEN : /* MISC */
121
{
122
	< #DOT: "." >
123
|	< OPEN_SQ_BRACKETS : "[" >
124
|	< CLOSE_SQ_BRACKETS : "]" >
125
|	< OPEN_PARENTHESIS : "(" >
126
|	< CLOSE_PARENTHESIS : ")" >
127
|	< DOUBLE_QUOTE : "\"" >	
128
|	< COMMA : "," >
129
|	< EOEXPR : ";" >
130
}
131
TOKEN : /* CONSTANTS AND IDENTIFIERS */
132
{
133
	< BOOLEAN: "true" | "false" >	
134
|	< IDENTIFIER: ( <LETTER> ) ( <LETTER>|<DIGIT> )* >
135
|	< #LETTER: ( ["_","$","%"] | ( ["a"-"z"] ) | ( ["A"-"Z"] ) ) >
136
}
137
TOKEN : /* NUMBER */
138
{
139
    < #DIGIT: ["0"-"9"] >
140
|	< INTEGER: ( <DIGIT> )+ >
141
|	< FLOATING_POINT: (<DIGIT>)+ "." (<DIGIT>)* (<EXPONENT>)? (["f","F","d","D"])?
142
      | <DOT> (<DIGIT>)+ (<EXPONENT>)? (["f","F","d","D"])?
143
      | (<DIGIT>)+ <EXPONENT> (["f","F","d","D"])?
144
      | (<DIGIT>)+ (<EXPONENT>)? ["f","F","d","D"] >
145
|	< #EXPONENT: ["e","E"] (["+","-"])? (<DIGIT>)+ >
146
}
147
TOKEN: /* STRING */
148
{
149
	< STRING: ( <DOUBLE_QUOTE> ( <CHAR_STRING> )* <DOUBLE_QUOTE> )>
150
|	< CHAR_STRING : ~[ "\"", ";","\n","\r"] >
151
}
152

    
153

    
154
TOKEN : /* LABELING TOKENS */
155
{
156
	< FIELD_IDENTIFIER: <OPEN_SQ_BRACKETS> <CHAR_STRING> <CLOSE_SQ_BRACKETS> >
157
}
158

    
159
/*
160
 * The grammar.
161
 */
162
 
163
/* LABEL EXPRESSION */
164
String[] LabelExpression() :
165
{
166
	ArrayList<String> labelFields = new ArrayList<String>();
167
	String f;
168
}
169
{
170
	f = FieldExpression() { labelFields.add(f); }
171
	(
172
		<COMMA>
173
		f = FieldExpression() { labelFields.add(f); }
174
	)*  <EOEXPR>
175
	{ 
176
		return labelFields.toArray(new String[0]);
177
	}
178
|	<EOEXPR> { return new String[0]; }
179
}
180

    
181
/* FIELD EXPRESSIONS */
182
String FieldExpression() :
183
{
184
	Token t;
185
	String value;
186
}
187
{
188
		Expression() { value = stack.pop().toString(); }
189
		( Expression() { value += stack.pop().toString(); } ) *
190
		{ return value; }
191
}
192

    
193
void Expression(): {}
194
{
195
	AndExpression() ( <OR> AndExpression() {
196
		try {
197
			boolean a = (Boolean) stack.pop();
198
			boolean b = (Boolean) stack.pop();
199
			stack.push(ValueFactory.createValue(a || b));
200
		} catch (ClassCastException ex) {
201
			throw new SemanticException(SemanticException.TYPE_MISMATCH);
202
		}
203
	}
204
	)*
205
}
206

    
207
void AndExpression() : {}
208
{
209
	EqComparisonExpression() ( <AND> EqComparisonExpression() {
210
		try {
211
			boolean a = (Boolean) stack.pop();
212
			boolean b = (Boolean) stack.pop();
213
			stack.push(new Boolean(b && a));
214
		} catch (ClassCastException ex) {
215
			throw new SemanticException(SemanticException.TYPE_MISMATCH,
216
				"Trying to perform logical AND with non-boolean data types");
217
		}
218
	})*
219
}
220

    
221
void EqComparisonExpression(): 
222
{
223
	Token t;
224
}
225
{
226
	ComparisonExpression() ( ( t = <EQ> | t = <NE> ) ComparisonExpression() {
227
		try {
228
			Object A = stack.pop();
			Object B = stack.pop();
			boolean aInt = A.getClass().equals(Integer.class);
			boolean bInt = B.getClass().equals(Integer.class);
			if (aInt &&	bInt) {
				int a = (Integer) A;
				int b = (Integer) B;
				if (t.kind == EQ)
					stack.push(new Boolean(b==a));
				else
					stack.push(new Boolean(b!=a));
			} else {
				double a = (!aInt) ? (Double) A : new Double(A.toString());
				double b = (!bInt) ? (Double) B : new Double(B.toString());
229
				if (t.kind == EQ)
230
					stack.push(new Boolean(b==a));
231
				else
232
					stack.push(new Boolean(b!=a));
233
			}
234
		} catch (ClassCastException ex) {
235
			throw new SemanticException(SemanticException.TYPE_MISMATCH,
236
				"Trying to perform comparison '"+t.image+"' with non-numeric data types");
237
		}
238
	})*
239
}
240

    
241
void ComparisonExpression() :
242
{
243
	Token t;
244
}
245
{
246
	AdditiveExpression() ((t = <LT> | t = <GT> | t = <LE> | t = <GE> ) AdditiveExpression() {
247
		try {
248
			Object A = stack.pop();
			Object B = stack.pop();
			boolean aInt = A.getClass().equals(Integer.class);
			boolean bInt = B.getClass().equals(Integer.class);
			if (aInt &&	bInt) {
				int a = (Integer) A;
				int b = (Integer) B;
				if (t.kind == LT)
					stack.push(new Boolean(b < a));
				else if (t.kind == GT)
					stack.push(new Boolean(b > a));
				else if (t.kind == LE)
					stack.push(new Boolean(b <= a));
				else if (t.kind == GE)
					stack.push(new Boolean(b >= a));
			} else {
				 
				double a = (!aInt) ? (Double) A : new Double(A.toString());
				double b = (!bInt) ? (Double) B : new Double(B.toString());
249
				if (t.kind == LT)
250
					stack.push(new Boolean(b < a));
251
				else if (t.kind == GT)
252
					stack.push(new Boolean(b > a));
253
				else if (t.kind == LE)
254
					stack.push(new Boolean(b <= a));
255
				else if (t.kind == GE)
256
					stack.push(new Boolean(b >= a));
257
			}
258
			
259
		} catch (ClassCastException ex) {
260
			throw new SemanticException(SemanticException.TYPE_MISMATCH,
261
				"Trying to perform relational '"+t.image+"' with non-numeric data types");
262
		}
263
	})*
264
}
265

    
266
void AdditiveExpression(): 
267
{
268
	Token t;
269
}
270
{
271
	MultiplicativeExpression() ( ( t = <PLUS> | t = <MINUS> ) MultiplicativeExpression() {
272
		try {
273
			Object A = stack.pop();
			Object B = stack.pop();
			boolean aInt = A.getClass().equals(Integer.class);
			boolean bInt = B.getClass().equals(Integer.class);
			if (aInt &&	bInt) {
				int a = (Integer) A;
				int b = (Integer) B;
				if (t.kind == PLUS)
					stack.push(new Integer(b + a));
				else
					stack.push(new Integer(b - a));
			} else {
				 
				double a = (!aInt) ? (Double) A : new Double(A.toString());
				double b = (!bInt) ? (Double) B : new Double(B.toString());
274
				if (t.kind == PLUS)
275
					stack.push(new Double(b + a));
276
				else
277
					stack.push(new Double(b - a));
278
			}
279
		} catch (ClassCastException ex) {
280
			throw new SemanticException(SemanticException.TYPE_MISMATCH,
281
				"Trying to perform ADD '"+t.image+"' with non-numeric data types");
282
		}
283
	})*
284
}
285

    
286
void MultiplicativeExpression(): 
287
{
288
	Token t;
289
}
290
{
291
	ArithmeticUnaryExpression() ( ( t = <MULTIPLY> | t = <DIVIDE> ) ArithmeticUnaryExpression() {
292
		try {
293
			Object A = stack.pop();
			Object B = stack.pop();
			boolean aInt = A.getClass().equals(Integer.class);
			boolean bInt = B.getClass().equals(Integer.class);
			if (aInt &&	bInt) {
				int a = (Integer) A;
				int b = (Integer) B;
				if (t.kind == PLUS)
					stack.push(new Integer(b * a));
				else
					stack.push(new Integer(b / a));
			} else {
				
				double a = (!aInt) ? (Double) A : new Double(A.toString());
				double b = (!bInt) ? (Double) B : new Double(B.toString());
294
				if (t.kind == MULTIPLY)
295
					stack.push(new Double(b * a));
296
				else
297
					stack.push(new Double(b / a));
298
			}
299
		} catch (ClassCastException ex) {
300
			throw new SemanticException(SemanticException.TYPE_MISMATCH,
301
				"Trying to perform MULT '"+t.image+"' with non-numeric data types");
302
		}
303
	})*
304
}
305

    
306
void ArithmeticUnaryExpression(): 
307
{
308
	Token t;
309
}
310
{
311
	 ( t = <PLUS> | t = <MINUS> ) ArithmeticUnaryExpression() {
312
		try {
313
			Object A = stack.pop();
314
			if (A.getClass().equals(Integer.class)) {
315
				int a = (Integer) A;
316
				if (t.kind == PLUS)
317
					stack.push(new Integer(a));
318
				else
319
					stack.push(new Integer(-a));
320
			} else {
321
				 
322
				double a = (Double) A;
323
				if (t.kind == PLUS)
324
					stack.push(new Double(a));
325
				else
326
					stack.push(new Double(-a));
327
			}
328
		} catch (ClassCastException ex) {
329
			throw new SemanticException(SemanticException.TYPE_MISMATCH,
330
				"Trying to perform UNARY '"+t.image+"' with non-numeric data types");
331
		}
332
	}
333
| BooleanUnaryExpression()
334
}
335

    
336
void BooleanUnaryExpression(): 
337
{
338
	Token t;
339
}
340
{
341
	 t = <NOT> ArithmeticUnaryExpression() {
342
		try {
343
			boolean a = (Boolean) stack.pop();
344
			stack.push(new Boolean(!a));
345
		} catch (ClassCastException ex) {
346
			throw new SemanticException(SemanticException.TYPE_MISMATCH,
347
				"Trying to perform UNARY '"+t.image+"' with non-numeric data types");
348
		}
349
	}
350
| PrimitiveExpression()
351
}
352

    
353
void PrimitiveExpression():
354
{
355
	Token t;
356
}
357
{
358
	Literal()
359
|	LOOKAHEAD(2)
360
	Function()
361
|   <OPEN_SQ_BRACKETS> t = <IDENTIFIER> <CLOSE_SQ_BRACKETS>
362
	{ String name = t.image.trim();  }
363
	{ Symbol sym = symbol_table.get(name); }
364
	{ if (sym == null) 
365
		throw new SemanticException(SemanticException.UNDEFINED_SYMBOL,
366
				"Symbol "+name+" undefined"); }
367
	{ switch (sym.getDataType()) {
368
		case Symbol.DATA_TYPE_INT: 
369
			stack.push(new Integer(((Value) sym.getValue()).toString()));
370
			break;
371
		case Symbol.DATA_TYPE_FLOATING: 
372
			stack.push(new Double(((Value) sym.getValue()).toString())); 
373
			break;
374
		case Symbol.DATA_TYPE_STRING:
375
			stack.push(((StringValue) sym.getValue()).toString());
376
			break;
377
		case Symbol.DATA_TYPE_NULL:
378
			stack.push(null);
379
			break;
380
		case Symbol.DATA_TYPE_BOOLEAN:
381
			stack.push(new Boolean(((Value) sym.getValue()).toString()));
382
			break;
383
		case Symbol.DATA_TYPE_DATE:
384
			stack.push(((DateValue) sym.getValue()).getValue());
385
			break;
386
		default:
387
		throw new SemanticException(SemanticException.TYPE_MISMATCH,
388
				"Unknown type for "+name);
389
	  }
390
	}
391
|	<OPEN_PARENTHESIS> Expression() <CLOSE_PARENTHESIS>
392
}
393

    
394
void Function():
395
{
396
	Token t;
397
	int argCount;
398
	String name;
399
}
400
{
401
	t = <IDENTIFIER> {name = t.image;} argCount = Arguments() 
402
		{ Function f = function_table.get(name); 
403
		  if (f == null) 
404
			throw new SemanticException(SemanticException.UNDEFINED_SYMBOL,
405
				"Symbol "+name+" undefined"); 
406
//		  if (sym.getSymbolType() == Symbol.SYMBOL_TYPE_FUNCTION) {
407
//		 	Function f = (Function) sym.getValue();
408
		 	if (f.getArgumentCount() != argCount) {
409
			 	throw new SemanticException(SemanticException.TYPE_MISMATCH,
410
		 	    	"Function '"+name+"' requires "+f.getArgumentCount()+", "+argCount+" were provided.");
411
		 	}
412
		 	ArrayList<Object> argList = new ArrayList<Object>();
413
		 	for (int i = 0; i <= argCount-1; i++) {
414
			 	argList.add(0, stack.pop());
415
		 	} 
416
		 	try {
417
		 		stack.push(f.evaluate(argList.toArray(new Object[0])));
418
			} catch (EvaluationException evEx) {
419
				throw new Error("Aquesta excepció no deuria de llançar-se així, deuria de ser una extensió de parse exception (o bé repensar-se el funcinament!!!");
420
			}
421
		 	
422
//	  	  } else {
//			throw new SemanticException(SemanticException.TYPE_MISMATCH,
//					"Tye symbol '"+name+"' is not a function");
//	  	  }
423
		}
424
}
425

    
426
void Literal() : 
427
{
428
	Token t;
429
}
430

    
431
{
432
	t = <INTEGER> 		 { stack.push(new Integer(t.image)); }
433
|	t = <FLOATING_POINT> { stack.push(new Double(t.image));  }
434
|	t = <BOOLEAN>		 { stack.push(new Boolean(t.image)); }
435
|	t = <STRING> 		 { stack.push(t.image.substring(1, t.image.length()-1)); }
436
}
437

    
438
int Arguments():
439
{
440
	int argCount = 0;
441
}
442
{
443
	<OPEN_PARENTHESIS> ( Expression()	{ argCount++; }
444
	(	<COMMA> Expression() 			{ argCount++; }
445
	)*
446
	) <CLOSE_PARENTHESIS>
447
	{ return argCount; }
448
}
449