KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jacorb > trading > constraint > Expression


1
2 // Copyright (C) 1998-1999
3
// Object Oriented Concepts, Inc.
4

5 // **********************************************************************
6
//
7
// Copyright (c) 1997
8
// Mark Spruiell (mark@intellisoft.com)
9
//
10
// See the COPYING file for more information
11
//
12
// **********************************************************************
13

14 package org.jacorb.trading.constraint;
15
16 import java.io.*;
17
18
19 public class Expression
20 {
21   private PropertySchema m_schema;
22   private ExprNode m_root;
23
24
25   private Expression()
26   {
27   }
28
29
30   public Expression(PropertySchema schema)
31   {
32     m_schema = schema;
33   }
34
35
36   /**
37    * Uses the given Lex object to validate an expression, throwing
38    * ParseException if an error occurred; the type of expression is
39    * returned upon successful parsing
40    */

41   public ValueType parse(Lex lex)
42     throws ParseException
43   {
44     m_root = null;
45
46     m_root = parseBoolOr(lex);
47
48     if (m_root == null)
49       throw new ParseException("invalid input");
50     else if (lex.getToken() != Lex.END)
51       throw new ParseException("unexpected input");
52
53     return m_root.getType();
54   }
55
56
57   /**
58    * Evaluates the expression using the given property source to supply
59    * values for properties used in the expression; the value of the
60    * expression is returned, or null if evaluation failed
61    */

62   public Value evaluate(PropertySource source)
63   {
64     Value result = null;
65
66     try {
67       result = m_root.evaluate(source);
68     }
69     catch (MissingPropertyException e) {
70     }
71     catch (ArithmeticException JavaDoc e) {
72     }
73
74     return result;
75   }
76
77
78   protected ExprNode parseBoolean(Lex lex)
79     throws ParseException
80   {
81     ExprNode result = null;
82
83     int token = lex.getToken();
84     if (token == Lex.TRUE_LIT || token == Lex.FALSE_LIT) {
85       result = new LiteralNode(LiteralNode.BOOLEAN, lex.getLexeme());
86       lex.nextToken();
87     }
88
89     return result;
90   }
91
92
93   protected ExprNode parseString(Lex lex)
94     throws ParseException
95   {
96     ExprNode result = null;
97
98     int token = lex.getToken();
99     if (token == Lex.STRING_LIT) {
100       result = new LiteralNode(LiteralNode.STRING, lex.getLexeme());
101       lex.nextToken();
102     }
103
104     return result;
105   }
106
107
108   protected ExprNode parseNumber(Lex lex)
109     throws ParseException
110   {
111     ExprNode result = null;
112
113     int token = lex.getToken();
114     if (token == Lex.NUMBER_LIT) {
115       result = new LiteralNode(LiteralNode.NUMBER, lex.getLexeme());
116       lex.nextToken();
117     }
118
119     return result;
120   }
121
122
123   protected ExprNode parseFactor(Lex lex)
124     throws ParseException
125   {
126     ExprNode result = null;
127
128     int token = lex.getToken();
129     if (token == Lex.LPAREN) {
130       lex.nextToken();
131       result = parseBoolOr(lex);
132       if (lex.getToken() != Lex.RPAREN)
133         throw new ParseException("missing closing parenthesis");
134       else
135         lex.nextToken();
136     }
137     else if (token == Lex.EXIST) {
138       lex.nextToken();
139       ExprNode ident = parseIdent(lex, false);
140       if (ident == null)
141         throw new ParseException("operand to 'exist' must be a property");
142       else
143         result = new ExistNode(ident);
144     }
145     else if (token == Lex.IDENT)
146       result = parseIdent(lex, true);
147     else if (token == Lex.NUMBER_LIT)
148       result = parseNumber(lex);
149     else if (token == Lex.MINUS) {
150       lex.nextToken();
151       ExprNode arg = null;
152
153       if (lex.getToken() == Lex.NUMBER_LIT)
154         arg = parseNumber(lex);
155       else if (lex.getToken() == Lex.IDENT)
156         arg = parseIdent(lex, true);
157
158       if (arg == null)
159         throw new ParseException("operand to unary '-' must be a number");
160       else
161         result = new NegNode(arg);
162     }
163     else if (token == Lex.STRING_LIT)
164       result = parseString(lex);
165     else if (token == Lex.TRUE_LIT || token == Lex.FALSE_LIT)
166       result = parseBoolean(lex);
167     else
168       throw new ParseException("unexpected factor '" + lex.getLexeme() + "'");
169
170     return result;
171   }
172
173
174   protected ExprNode parseFactorNot(Lex lex)
175     throws ParseException
176   {
177     ExprNode result = null;
178
179     int token = lex.getToken();
180     if (token == Lex.NOT) {
181       lex.nextToken();
182       ExprNode child = parseFactor(lex);
183       ValueType childType = child.getType();
184
185       if (! ValueType.isCompatible(childType.getId(), ValueType.BOOLEAN) ||
186             childType.isSequence())
187         throw new ParseException(
188           "operand to 'not' must be a boolean expression");
189       else
190         result = new NotNode(child);
191     }
192     else
193       result = parseFactor(lex);
194
195     return result;
196   }
197
198
199   protected ExprNode parseTerm(Lex lex)
200     throws ParseException
201   {
202     ExprNode result;
203
204     result = parseFactorNot(lex);
205
206     int token = lex.getToken();
207
208     while (token == Lex.MULT || token == Lex.DIV) {
209         // save the operator for use in error messages
210
String JavaDoc op = lex.getLexeme();
211
212       lex.nextToken();
213       ExprNode right = parseFactorNot(lex);
214
215       if (! result.getType().isNumber() || ! right.getType().isNumber() ||
216           result.getType().isSequence() || right.getType().isSequence())
217         throw new ParseException("operands to '" + op + "' must be numeric");
218
219       if (! ValueType.isCompatible(result.getType().getId(),
220             right.getType().getId()))
221         throw new ParseException("operands to '" + op + "' are not compatible");
222
223       if (token == Lex.MULT)
224         result = new MultiplyNode(result, right);
225       else // token == Lex.DIV
226
result = new DivideNode(result, right);
227
228       token = lex.getToken();
229     }
230
231     return result;
232   }
233
234
235   protected ExprNode parseExpr(Lex lex)
236     throws ParseException
237   {
238     ExprNode result;
239
240     result = parseTerm(lex);
241
242     int token = lex.getToken();
243
244     while (token == Lex.PLUS || token == Lex.MINUS) {
245         // save the operator for use in error messages
246
String JavaDoc op = lex.getLexeme();
247
248       lex.nextToken();
249       ExprNode right = parseTerm(lex);
250
251       if (! result.getType().isNumber() || ! right.getType().isNumber() ||
252           result.getType().isSequence() || right.getType().isSequence())
253         throw new ParseException("operands to '" + op + "' must be numeric");
254
255       if (! ValueType.isCompatible(result.getType().getId(),
256             right.getType().getId()))
257         throw new ParseException("operands to '" + op + "' are not compatible");
258
259       if (token == Lex.PLUS)
260         result = new AddNode(result, right);
261       else // token == Lex.MINUS
262
result = new SubtractNode(result, right);
263
264       token = lex.getToken();
265     }
266
267     return result;
268   }
269
270
271   protected ExprNode parseIdent(Lex lex, boolean checkType)
272     throws ParseException
273   {
274     ExprNode result = null;
275
276     int token = lex.getToken();
277     if (token == Lex.IDENT) {
278       String JavaDoc property = lex.getLexeme();
279       ValueType type = m_schema.getPropertyType(property);
280       if (type == null) {
281         if (checkType)
282           throw new ParseException("unknown property '" + property + "'");
283         else
284           type = new ValueType(ValueType.OTHER);
285       }
286
287       result = new PropertyNode(property, type);
288       lex.nextToken();
289     }
290
291     return result;
292   }
293
294
295   protected ExprNode parseExprTwiddle(Lex lex)
296     throws ParseException
297   {
298     ExprNode result;
299
300     result = parseExpr(lex);
301
302     int token = lex.getToken();
303
304     if (token == Lex.TILDE) {
305       lex.nextToken();
306       ExprNode right = parseExpr(lex);
307
308       if (! ValueType.isCompatible(result.getType().getId(), ValueType.STRING) ||
309           ! ValueType.isCompatible(right.getType().getId(), ValueType.STRING))
310         throw new ParseException("operands to '~' must be strings");
311
312         // check for presence of sequence
313
if (result.getType().isSequence() || right.getType().isSequence())
314         throw new ParseException("sequence not allowed as operand to '~'");
315
316       result = new SubstrNode(result, right);
317     }
318
319     return result;
320   }
321
322
323   protected ExprNode parseExprIn(Lex lex)
324     throws ParseException
325   {
326     ExprNode result;
327
328     result = parseExprTwiddle(lex);
329
330     int token = lex.getToken();
331
332     if (token == Lex.IN) {
333       lex.nextToken();
334
335         // the right operand to in must be a sequence
336
ExprNode right = parseIdent(lex, true);
337
338       if (right == null)
339         throw new ParseException("right operand to 'in' must be a property");
340
341         // make sure right is a sequence
342
if (! right.getType().isSequence())
343         throw new ParseException(
344           "right operand to 'in' must be a sequence property");
345
346       if (! ValueType.isCompatible(result.getType().getId(),
347             right.getType().getId()))
348         throw new ParseException("operands to 'in' are not compatible");
349
350       result = new InNode(result, right);
351     }
352
353     return result;
354   }
355
356
357   protected ExprNode parseBoolCompare(Lex lex)
358     throws ParseException
359   {
360     ExprNode result;
361
362     result = parseExprIn(lex);
363
364     int token = lex.getToken();
365
366     if (token == Lex.EQUAL) {
367       lex.nextToken();
368       ExprNode right = parseExprIn(lex);
369
370       if (! ValueType.isCompatible(result.getType().getId(),
371             right.getType().getId()) || result.getType().isSequence() ||
372             right.getType().isSequence())
373         throw new ParseException("operands to '==' are not compatible");
374
375       result = new EqNode(result, right);
376     }
377     else if (token == Lex.NOT_EQUAL) {
378       lex.nextToken();
379       ExprNode right = parseExprIn(lex);
380
381       if (! ValueType.isCompatible(result.getType().getId(),
382           right.getType().getId()) || result.getType().isSequence() ||
383           right.getType().isSequence())
384         throw new ParseException("operands to '!=' are not compatible");
385
386       result = new NeqNode(result, right);
387     }
388     else if (token == Lex.LESS) {
389       lex.nextToken();
390       ExprNode right = parseExprIn(lex);
391
392       if (! ValueType.isCompatible(result.getType().getId(),
393           right.getType().getId()) || result.getType().isSequence() ||
394           right.getType().isSequence())
395         throw new ParseException("operands to '<' are not compatible");
396
397       result = new LtNode(result, right);
398     }
399     else if (token == Lex.LESS_EQUAL) {
400       lex.nextToken();
401       ExprNode right = parseExprIn(lex);
402
403       if (! ValueType.isCompatible(result.getType().getId(),
404           right.getType().getId()) || result.getType().isSequence() ||
405           right.getType().isSequence())
406         throw new ParseException("operands to '<=' are not compatible");
407
408       result = new LeNode(result, right);
409     }
410     else if (token == Lex.GREATER) {
411       lex.nextToken();
412       ExprNode right = parseExprIn(lex);
413
414       if (! ValueType.isCompatible(result.getType().getId(),
415           right.getType().getId()) || result.getType().isSequence() ||
416           right.getType().isSequence())
417         throw new ParseException("operands to '>' are not compatible");
418
419       result = new GtNode(result, right);
420     }
421     else if (token == Lex.GREATER_EQUAL) {
422       lex.nextToken();
423       ExprNode right = parseExprIn(lex);
424
425       if (! ValueType.isCompatible(result.getType().getId(),
426           right.getType().getId()) || result.getType().isSequence() ||
427           right.getType().isSequence())
428         throw new ParseException("operands to '>=' are not compatible");
429
430       result = new GeNode(result, right);
431     }
432
433     return result;
434   }
435
436
437   protected ExprNode parseBoolAnd(Lex lex)
438     throws ParseException
439   {
440     ExprNode result;
441
442     result = parseBoolCompare(lex);
443
444     while (lex.getToken() == Lex.AND) {
445       lex.nextToken();
446       ExprNode right = parseBoolCompare(lex);
447
448       if (! ValueType.isCompatible(result.getType().getId(), ValueType.BOOLEAN) ||
449           ! ValueType.isCompatible(right.getType().getId(), ValueType.BOOLEAN) ||
450           result.getType().isSequence() || right.getType().isSequence())
451         throw new ParseException(
452           "operands to 'and' must be boolean expressions");
453
454       result = new AndNode(result, right);
455     }
456
457     return result;
458   }
459
460
461   protected ExprNode parseBoolOr(Lex lex)
462     throws ParseException
463   {
464     ExprNode result;
465
466     result = parseBoolAnd(lex);
467
468     while (lex.getToken() == Lex.OR) {
469       lex.nextToken();
470       ExprNode right = parseBoolAnd(lex);
471
472       if (! ValueType.isCompatible(result.getType().getId(), ValueType.BOOLEAN) ||
473           ! ValueType.isCompatible(right.getType().getId(), ValueType.BOOLEAN) ||
474           result.getType().isSequence() || right.getType().isSequence())
475         throw new ParseException(
476           "operands to 'or' must be boolean expressions");
477
478       result = new OrNode(result, right);
479     }
480
481     return result;
482   }
483
484
485   /************** comment out this line to enable main()
486
487   public static void main(String[] args)
488   {
489     if (args.length < 1) {
490       System.err.println("Usage: Expression expr");
491       System.exit(1);
492     }
493
494     Expression expr = new Expression(null);
495
496     try {
497       StringReader reader = new StringReader(args[0]);
498       Lex lex = new Lex(reader);
499       ValueType type = expr.parse(lex);
500       System.out.println("type of expression = " + type);
501       Value value = expr.evaluate(null);
502       System.out.println("result of expression = " + value);
503     }
504     catch (ParseException e) {
505       System.err.println("Parse error: " + e.getMessage());
506     }
507   }
508
509   /************** comment out this line to enable main() */

510 }
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
Popular Tags