1 23 package org.objectweb.medor.expression.parser.string; 24 25 import org.objectweb.jorm.type.api.PType; 26 import org.objectweb.medor.expression.api.Comparator; 27 import org.objectweb.medor.expression.api.Expression; 28 import org.objectweb.medor.expression.api.ExpressionException; 29 import org.objectweb.medor.expression.api.MalformedExpressionException; 30 import org.objectweb.medor.expression.api.Operator; 31 import org.objectweb.medor.expression.lib.And; 32 import org.objectweb.medor.expression.lib.BasicOperand; 33 import org.objectweb.medor.expression.lib.BasicParameterOperand; 34 import org.objectweb.medor.expression.lib.ConditionalAnd; 35 import org.objectweb.medor.expression.lib.ConditionalOr; 36 import org.objectweb.medor.expression.lib.DivideBy; 37 import org.objectweb.medor.expression.lib.Equal; 38 import org.objectweb.medor.expression.lib.Greater; 39 import org.objectweb.medor.expression.lib.GreaterEqual; 40 import org.objectweb.medor.expression.lib.Lower; 41 import org.objectweb.medor.expression.lib.LowerEqual; 42 import org.objectweb.medor.expression.lib.Minus; 43 import org.objectweb.medor.expression.lib.Mod; 44 import org.objectweb.medor.expression.lib.Mult; 45 import org.objectweb.medor.expression.lib.NotEqual; 46 import org.objectweb.medor.expression.lib.Or; 47 import org.objectweb.medor.expression.lib.Plus; 48 import org.objectweb.medor.expression.parser.api.ParameterTypeProvider; 49 import org.objectweb.medor.expression.parser.lib.ReplaceStringPlusByConcat; 50 51 import java.util.ArrayList ; 52 import java.util.StringTokenizer ; 53 54 59 public class ExpressionParser { 60 63 67 private final static String STRCONSTTOK = "$"; 68 private final static String DELIMITERS = "$()+-=!<>&|/%*"; 69 private final static int TOKENPOS = 0; 70 private final static int STRCONSTPOS = 1; 71 72 82 public Expression parse(String exprstr, ParameterTypeProvider ptp) 83 throws ExpressionException { 84 ArrayList stringConst = new ArrayList (); 85 String exprwithoutstrconst = extractStringConst(exprstr, stringConst); 87 Expression res = buildExpr(toStringArray(exprwithoutstrconst), 89 new int[]{0, 0}, 90 stringConst, 91 ptp); 92 res = new ReplaceStringPlusByConcat().rewrite(res); 94 res.compileExpression(); 96 return res; 97 } 98 99 109 String extractStringConst(String expr, ArrayList stringConst) 110 throws MalformedExpressionException { 111 StringBuffer res = new StringBuffer (); 112 int curpos = 0; 113 do { 114 int startsc = expr.indexOf('"', curpos); 115 if (startsc == -1) { 116 break; 117 } 118 int endsc = expr.indexOf('"', startsc + 1); 119 if (endsc == -1) { 120 throw new MalformedExpressionException("Constant string starting at position" 121 + startsc + " never ended."); 122 } 123 res.append(expr.substring(curpos, startsc).replaceAll(" ", "")); 124 res.append(STRCONSTTOK); 125 stringConst.add(expr.substring(startsc + 1, endsc)); 126 curpos = endsc + 1; 127 } while (true); 128 res.append(expr.substring(curpos).replaceAll(" ", "")); 129 return res.toString(); 130 } 131 132 137 private String [] toStringArray(String str) { 138 StringTokenizer tokenizer = new StringTokenizer (str, DELIMITERS, true); 139 ArrayList tokens = new ArrayList (); 140 String [] nextToken = new String []{null}; 141 do { 142 String token = getNextToken(tokenizer, nextToken); 143 if (token == null) { 144 break; 145 } 146 tokens.add(token); 147 } while (true); 148 return (String []) tokens.toArray(new String [tokens.size()]); 149 } 150 151 160 private Expression buildExpr(String [] tokens, 161 int[] indexes, 162 ArrayList stringConst, 163 ParameterTypeProvider ptp) 164 throws MalformedExpressionException { 165 if (indexes[TOKENPOS] == tokens.length) { 166 return null; 167 } 168 Expression firstnode; 169 if (tokens[indexes[TOKENPOS]].equals("(")) { 170 firstnode = buildParenthesExpr(tokens, indexes, stringConst, ptp); 171 } else { 172 firstnode = buildAtomicOperandExpr(tokens, indexes, stringConst, ptp); 173 } 174 if ((indexes[TOKENPOS] == tokens.length) || (tokens[indexes[TOKENPOS]].equals(")"))) { 175 return firstnode; 176 } 177 Expression operator = buildNextExpr(tokens, indexes, stringConst, firstnode, ptp); 178 if (operator == null) { 179 throw new MalformedExpressionException("Wrong token found in token position " 180 + indexes[TOKENPOS] + ": " + tokens[indexes[TOKENPOS]] 181 + " (should be an operator)"); 182 } 183 return operator; 184 } 185 186 195 private Operator buildNextExpr(String [] tokens, 196 int[] indexes, 197 ArrayList stringConst, 198 Expression left, 199 ParameterTypeProvider ptp) 200 throws MalformedExpressionException { 201 if (indexes[TOKENPOS] == tokens.length) { 202 return null; 203 } 204 if (tokens[indexes[TOKENPOS]].equals(")")) { 205 return null; 206 } 207 Operator operator; 208 Expression secondnode; 209 operator = buildPri1OperatorExpr(tokens, indexes); 210 if (operator != null) { 211 if (tokens[indexes[TOKENPOS]].equals("(")) { 212 secondnode = buildParenthesExpr(tokens, indexes, stringConst, ptp); 213 } else { 214 secondnode = buildAtomicOperandExpr(tokens, indexes, stringConst, ptp); 215 } 216 Operator next = buildNextExpr(tokens, indexes, stringConst, operator, ptp); 217 operator.setExpression(0, left); 218 if (next != null) { 219 if (priorTo(operator, next)) { 220 operator.setExpression(1, secondnode); 221 return next; 222 } 223 operator.setExpression(1, next); 224 next.setExpression(0, secondnode); 225 return operator; 226 } 227 operator.setExpression(1, secondnode); 228 return operator; 229 } 230 operator = buildPri2OperatorExpr(tokens, indexes); 231 if (operator != null) { 232 if (tokens[indexes[TOKENPOS]].equals("(")) { 233 secondnode = buildParenthesExpr(tokens, indexes, stringConst, ptp); 234 } else { 235 secondnode = buildAtomicOperandExpr(tokens, indexes, stringConst, ptp); 236 } 237 Operator next = buildNextExpr(tokens, indexes, stringConst, operator, ptp); 238 operator.setExpression(0, left); 239 if (next != null) { 240 if (priorTo(operator, next)) { 241 operator.setExpression(1, secondnode); 242 return next; 243 } 244 operator.setExpression(1, next); 245 next.setExpression(0, secondnode); 246 return operator; 247 } 248 operator.setExpression(1, secondnode); 249 return operator; 250 } 251 operator = buildCompOperatorExpr(tokens, indexes); 252 if (operator != null) { 253 if (tokens[indexes[TOKENPOS]].equals("(")) { 254 secondnode = buildParenthesExpr(tokens, indexes, stringConst, ptp); 255 } else { 256 secondnode = buildExpr(tokens, indexes, stringConst, ptp); 257 } 258 Operator next = buildNextExpr(tokens, indexes, stringConst, operator, ptp); 259 operator.setExpression(0, left); 260 if (next != null) { 261 if (priorTo(operator, next)) { 262 operator.setExpression(1, secondnode); 263 return next; 264 } 265 operator.setExpression(1, next); 266 next.setExpression(0, secondnode); 267 return operator; 268 } 269 operator.setExpression(1, secondnode); 270 return operator; 271 } 272 operator = buildLogicalOperatorExpr(tokens, indexes); 273 if (operator != null) { 274 if (tokens[indexes[TOKENPOS]].equals("(")) { 275 secondnode = buildParenthesExpr(tokens, indexes, stringConst, ptp); 276 } else { 277 secondnode = buildExpr(tokens, indexes, stringConst, ptp); 278 } 279 Operator next = buildNextExpr(tokens, indexes, stringConst, operator, ptp); 280 operator.setExpression(0, left); 281 if (next != null) { 282 if (priorTo(operator, next)) { 283 operator.setExpression(1, secondnode); 284 return next; 285 } 286 operator.setExpression(1, next); 287 next.setExpression(0, secondnode); 288 return operator; 289 } 290 operator.setExpression(1, secondnode); 291 return operator; 292 } 293 throw new MalformedExpressionException("Wrong token found in token position " 294 + indexes[TOKENPOS] + ": " + tokens[indexes[TOKENPOS]] 295 + " (should be an operator)"); 296 } 297 298 307 private Expression buildParenthesExpr(String [] tokens, 308 int[] indexes, 309 ArrayList stringConst, 310 ParameterTypeProvider ptp) 311 throws MalformedExpressionException { 312 indexes[TOKENPOS]++; 313 Expression res = buildExpr(tokens, indexes, stringConst, ptp); 314 if (!tokens[indexes[TOKENPOS]].equals(")")) { 315 throw new MalformedExpressionException("Wrong token found in token position " 316 + indexes[TOKENPOS] + ": " + tokens[indexes[TOKENPOS]]); 317 } 318 indexes[TOKENPOS]++; 319 return res; 320 } 321 322 332 private Expression buildAtomicOperandExpr(String [] tokens, 333 int[] indexes, 334 ArrayList stringConst, 335 ParameterTypeProvider ptp) 336 throws MalformedExpressionException { 337 Expression res = null; 338 String operand = tokens[indexes[TOKENPOS]]; 339 if (operand.equals("$")) { res = new BasicOperand( 342 (String ) stringConst.get(indexes[STRCONSTPOS])); 343 indexes[STRCONSTPOS]++; 344 } 345 if (res == null) { if (operand.equalsIgnoreCase("true")) { 347 res = new BasicOperand(true); 348 } else if (operand.equalsIgnoreCase("false")) { 349 res = new BasicOperand(false); 350 } 351 } 352 if (res == null) { try { 354 long l = Long.parseLong(operand); 355 if (l <= Byte.MAX_VALUE && l >= Byte.MIN_VALUE) { 356 res = new BasicOperand((byte) l); 357 } else if (l <= Short.MAX_VALUE && l >= Short.MIN_VALUE) { 358 res = new BasicOperand((short) l); 359 } else if (l <= Integer.MAX_VALUE && l >= Integer.MIN_VALUE) { 360 res = new BasicOperand((int) l); 361 } else { 362 res = new BasicOperand(l); 363 } 364 } catch (NumberFormatException e) { 365 } 366 } 367 if (res == null) { try { 369 double d = Double.parseDouble(operand); 370 if (d <= Float.MAX_VALUE && d >= Float.MIN_VALUE) { 371 res = new BasicOperand((float) d); 372 } else { 373 res = new BasicOperand(d); 374 } 375 } catch (NumberFormatException e) { 376 } 377 } 378 if (res == null && Character.isLetterOrDigit(operand.charAt(0))) { 379 String paramName = tokens[indexes[TOKENPOS]]; 381 if (ptp == null) { 382 throw new MalformedExpressionException("ParameterTypeProvider required, but was null, for parameter " + paramName); 383 } 384 PType paramType = ptp.getParameterPType(paramName); 385 if (paramType == null) { 386 throw new MalformedExpressionException("Unknown type for parameter " + paramName); 387 } 388 res = new BasicParameterOperand(paramType, paramName); 389 } 390 if (res != null) { 391 indexes[TOKENPOS]++; 392 return res; 393 } 394 throw new MalformedExpressionException("Wrong token found in token position " 395 + indexes[TOKENPOS] + ": " + tokens[indexes[TOKENPOS]] 396 + " (should be a constant or a variable)"); 397 } 398 399 406 private Operator buildLogicalOperatorExpr(String [] tokens, 407 int[] indexes) { 408 Operator res; 409 if (tokens[indexes[TOKENPOS]].equals("&&")) { 410 res = new ConditionalAnd(); 411 } else if (tokens[indexes[TOKENPOS]].equals("||")) { 412 res = new ConditionalOr(); 413 } else { 414 return null; 415 } 416 indexes[TOKENPOS]++; 417 return res; 418 } 419 420 427 private Operator buildCompOperatorExpr(String [] tokens, 428 int[] indexes) { 429 Operator res; 430 if (tokens[indexes[TOKENPOS]].equals("==")) { 431 res = new Equal(); 432 } else if (tokens[indexes[TOKENPOS]].equals("!=")) { 433 res = new NotEqual(); 434 } else if (tokens[indexes[TOKENPOS]].equals("<")) { 435 res = new Lower(); 436 } else if (tokens[indexes[TOKENPOS]].equals("<=")) { 437 res = new LowerEqual(); 438 } else if (tokens[indexes[TOKENPOS]].equals(">")) { 439 res = new Greater(); 440 } else if (tokens[indexes[TOKENPOS]].equals(">=")) { 441 res = new GreaterEqual(); 442 } else { 443 return null; 444 } 445 indexes[TOKENPOS]++; 446 return res; 447 } 448 449 456 private Operator buildPri2OperatorExpr(String [] tokens, 457 int[] indexes) { 458 Operator res; 459 if (tokens[indexes[TOKENPOS]].equals("+")) { 460 res = new Plus(); 461 } else if (tokens[indexes[TOKENPOS]].equals("-")) { 462 res = new Minus(); 463 } else if (tokens[indexes[TOKENPOS]].equals("|")) { 464 res = new Or(); 465 } else { 466 return null; 467 } 468 indexes[TOKENPOS]++; 469 return res; 470 } 471 472 479 private Operator buildPri1OperatorExpr(String [] tokens, 480 int[] indexes) { 481 Operator res; 482 if (tokens[indexes[TOKENPOS]].equals("*")) { 483 res = new Mult(); 484 } else if (tokens[indexes[TOKENPOS]].equals("/")) { 485 res = new DivideBy(); 486 } else if (tokens[indexes[TOKENPOS]].equals("%")) { 487 res = new Mod(); 488 } else if (tokens[indexes[TOKENPOS]].equals("&")) { 489 res = new And(); 490 } else { 491 return null; 492 } 493 indexes[TOKENPOS]++; 494 return res; 495 } 496 497 503 private String getNextToken(StringTokenizer tokenizer, String [] nexttoken) { 504 String res; 505 if (nexttoken[0] != null) { 506 res = nexttoken[0]; 507 nexttoken[0] = null; 508 return res; 509 } 510 if (!tokenizer.hasMoreTokens()) { 511 return null; 512 } 513 res = tokenizer.nextToken(); 514 if (res.equals("=") || res.equals("<") || res.equals(">") || res.equals("!")) { 515 if (!tokenizer.hasMoreTokens()) { 516 return res; 517 } 518 nexttoken[0] = tokenizer.nextToken(); 519 if (nexttoken[0].equals("=")) { 520 nexttoken[0] = null; 521 return res + "="; 522 } 523 return res; 524 } else if (res.equals("&")) { 525 if (!tokenizer.hasMoreTokens()) { 526 return res; 527 } 528 nexttoken[0] = tokenizer.nextToken(); 529 if (nexttoken[0].equals("&")) { 530 nexttoken[0] = null; 531 return "&&"; 532 } 533 return res; 534 } else if (res.equals("|")) { 535 if (!tokenizer.hasMoreTokens()) { 536 return res; 537 } 538 nexttoken[0] = tokenizer.nextToken(); 539 if (nexttoken[0].equals("|")) { 540 nexttoken[0] = null; 541 return "||"; 542 } 543 return res; 544 } else { 545 return res; 546 } 547 } 548 549 554 private boolean isLog(Operator token) { 555 return (token instanceof ConditionalAnd) 556 || (token instanceof ConditionalOr); 557 } 558 559 564 private boolean isComp(Operator token) { 565 return (token instanceof Comparator); 566 } 567 568 573 private boolean isPri2(Operator token) { 574 return (token instanceof Plus) 575 || (token instanceof Minus) 576 || (token instanceof Or); 577 } 578 579 585 private boolean priorTo(Operator tok1, Operator tok2) { 586 if (isLog(tok1)) { 587 return false; 588 } 589 if (isComp(tok1)) { 590 return isLog(tok2); 591 } 592 if (isPri2(tok1)) { 593 return isLog(tok2) || isComp(tok2); 594 } 595 return isLog(tok2) || isComp(tok2) || isPri2(tok2); 596 } 597 } 598 | Popular Tags |