1 2 5 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 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 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 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 String 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 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 String 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 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 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 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 ExprNode right = parseIdent(lex, true); 337 338 if (right == null) 339 throw new ParseException("right operand to 'in' must be a property"); 340 341 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 510 } 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 | Popular Tags |