1 /* 2 * Copyright (c) 1998, 2003, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 options { 27 JAVA_UNICODE_ESCAPE = true; 28 STATIC = false; 29 } 30 31 PARSER_BEGIN(ExpressionParser) 32 33 package com.sun.tools.example.debug.expr; 34 35 import com.sun.jdi.*; 36 import java.util.Stack; 37 import java.util.List; 38 import java.util.ArrayList; 39 40 public class ExpressionParser { 41 42 Stack stack = new Stack(); 43 VirtualMachine vm = null; 44 GetFrame frameGetter = null; 45 private static GetFrame lastFrameGetter; 46 private static LValue lastLValue; 47 48 LValue peek() { 49 return (LValue)stack.peek(); 50 } 51 52 LValue pop() { 53 return (LValue)stack.pop(); 54 } 55 56 void push(LValue lval) { 57 stack.push(lval); 58 } 59 60 public static Value getMassagedValue() throws ParseException { 61 return lastLValue.getMassagedValue(lastFrameGetter); 62 } 63 64 public interface GetFrame { 65 StackFrame get() throws IncompatibleThreadStateException; 66 } 67 68 public static Value evaluate(String expr, VirtualMachine vm, 69 GetFrame frameGetter) throws ParseException, 70 InvocationException, 71 InvalidTypeException, 72 ClassNotLoadedException, 73 IncompatibleThreadStateException { 74 // TODO StringBufferInputStream is deprecated. 75 java.io.InputStream in = new java.io.StringBufferInputStream(expr); 76 ExpressionParser parser = new ExpressionParser(in); 77 parser.vm = vm; 78 parser.frameGetter = frameGetter; 79 Value value = null; 80 parser.Expression(); 81 lastFrameGetter = frameGetter; 82 lastLValue = parser.pop(); 83 return lastLValue.getValue(); 84 } 85 86 public static void main(String args[]) { 87 ExpressionParser parser; 88 System.out.print("Java Expression Parser: "); 89 if (args.length == 0) { 90 System.out.println("Reading from standard input . . ."); 91 parser = new ExpressionParser(System.in); 92 } else if (args.length == 1) { 93 System.out.println("Reading from file " + args[0] + " . . ."); 94 try { 95 parser = new ExpressionParser(new java.io.FileInputStream(args[0])); 96 } catch (java.io.FileNotFoundException e) { 97 System.out.println("Java Parser Version 1.0.2: File " + 98 args[0] + " not found."); 99 return; 100 } 101 } else { 102 System.out.println("Usage is one of:"); 103 System.out.println(" java ExpressionParser < inputfile"); 104 System.out.println("OR"); 105 System.out.println(" java ExpressionParser inputfile"); 106 return; 107 } 108 try { 109 parser.Expression(); 110 System.out.print("Java Expression Parser: "); 111 System.out.println("Java program parsed successfully."); 112 } catch (ParseException e) { 113 System.out.print("Java Expression Parser: "); 114 System.out.println("Encountered errors during parse."); 115 } 116 } 117 118 } 119 120 PARSER_END(ExpressionParser) 121 122 123 SKIP : /* WHITE SPACE */ 124 { 125 " " 126 | "\t" 127 | "\n" 128 | "\r" 129 | "\f" 130 } 131 132 SPECIAL_TOKEN : /* COMMENTS */ 133 { 134 <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")> 135 | <FORMAL_COMMENT: "/**" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/"> 136 | <MULTI_LINE_COMMENT: "/*" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/"> 137 } 138 139 TOKEN : /* RESERVED WORDS AND LITERALS */ 140 { 141 < ABSTRACT: "abstract" > 142 | < BOOLEAN: "boolean" > 143 | < BREAK: "break" > 144 | < BYTE: "byte" > 145 | < CASE: "case" > 146 | < CATCH: "catch" > 147 | < CHAR: "char" > 148 | < CLASS: "class" > 149 | < CONST: "const" > 150 | < CONTINUE: "continue" > 151 | < _DEFAULT: "default" > 152 | < DO: "do" > 153 | < DOUBLE: "double" > 154 | < ELSE: "else" > 155 | < EXTENDS: "extends" > 156 | < FALSE: "false" > 157 | < FINAL: "final" > 158 | < FINALLY: "finally" > 159 | < FLOAT: "float" > 160 | < FOR: "for" > 161 | < GOTO: "goto" > 162 | < IF: "if" > 163 | < IMPLEMENTS: "implements" > 164 | < IMPORT: "import" > 165 | < INSTANCEOF: "instanceof" > 166 | < INT: "int" > 167 | < INTERFACE: "interface" > 168 | < LONG: "long" > 169 | < NATIVE: "native" > 170 | < NEW: "new" > 171 | < NULL: "null" > 172 | < PACKAGE: "package"> 173 | < PRIVATE: "private" > 174 | < PROTECTED: "protected" > 175 | < PUBLIC: "public" > 176 | < RETURN: "return" > 177 | < SHORT: "short" > 178 | < STATIC: "static" > 179 | < SUPER: "super" > 180 | < SWITCH: "switch" > 181 | < SYNCHRONIZED: "synchronized" > 182 | < THIS: "this" > 183 | < THROW: "throw" > 184 | < THROWS: "throws" > 185 | < TRANSIENT: "transient" > 186 | < TRUE: "true" > 187 | < TRY: "try" > 188 | < VOID: "void" > 189 | < VOLATILE: "volatile" > 190 | < WHILE: "while" > 191 } 192 193 TOKEN : /* LITERALS */ 194 { 195 < 196 INTEGER_LITERAL: 197 <DECIMAL_LITERAL> (["l","L"])? 198 | <HEX_LITERAL> (["l","L"])? 199 | <OCTAL_LITERAL> (["l","L"])? 200 > 201 | 202 < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* > 203 | 204 < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ > 205 | 206 < #OCTAL_LITERAL: "0" (["0"-"7"])* > 207 | 208 < FLOATING_POINT_LITERAL: 209 (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])? 210 | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])? 211 | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])? 212 | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"] 213 > 214 | 215 < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ > 216 | 217 < CHARACTER_LITERAL: 218 "'" 219 ( (~["'","\\","\n","\r"]) 220 | ("\\" 221 ( ["n","t","b","r","f","\\","'","\""] 222 | ["0"-"7"] ( ["0"-"7"] )? 223 | ["0"-"3"] ["0"-"7"] ["0"-"7"] 224 ) 225 ) 226 ) 227 "'" 228 > 229 | 230 < STRING_LITERAL: 231 "\"" 232 ( (~["\"","\\","\n","\r"]) 233 | ("\\" 234 ( ["n","t","b","r","f","\\","'","\""] 235 | ["0"-"7"] ( ["0"-"7"] )? 236 | ["0"-"3"] ["0"-"7"] ["0"-"7"] 237 ) 238 ) 239 )* 240 "\"" 241 > 242 } 243 244 TOKEN : /* IDENTIFIERS */ 245 { 246 < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* > 247 | 248 < #LETTER: 249 [ 250 "\u0024", 251 "\u0041"-"\u005a", 252 "\u005f", 253 "\u0061"-"\u007a", 254 "\u00c0"-"\u00d6", 255 "\u00d8"-"\u00f6", 256 "\u00f8"-"\u00ff", 257 "\u0100"-"\u1fff", 258 "\u3040"-"\u318f", 259 "\u3300"-"\u337f", 260 "\u3400"-"\u3d2d", 261 "\u4e00"-"\u9fff", 262 "\uf900"-"\ufaff" 263 ] 264 > 265 | 266 < #DIGIT: 267 [ 268 "\u0030"-"\u0039", 269 "\u0660"-"\u0669", 270 "\u06f0"-"\u06f9", 271 "\u0966"-"\u096f", 272 "\u09e6"-"\u09ef", 273 "\u0a66"-"\u0a6f", 274 "\u0ae6"-"\u0aef", 275 "\u0b66"-"\u0b6f", 276 "\u0be7"-"\u0bef", 277 "\u0c66"-"\u0c6f", 278 "\u0ce6"-"\u0cef", 279 "\u0d66"-"\u0d6f", 280 "\u0e50"-"\u0e59", 281 "\u0ed0"-"\u0ed9", 282 "\u1040"-"\u1049" 283 ] 284 > 285 } 286 287 TOKEN : /* SEPARATORS */ 288 { 289 < LPAREN: "(" > 290 | < RPAREN: ")" > 291 | < LBRACE: "{" > 292 | < RBRACE: "}" > 293 | < LBRACKET: "[" > 294 | < RBRACKET: "]" > 295 | < SEMICOLON: ";" > 296 | < COMMA: "," > 297 | < DOT: "." > 298 } 299 300 TOKEN : /* OPERATORS */ 301 { 302 < ASSIGN: "=" > 303 | < GT: ">" > 304 | < LT: "<" > 305 | < BANG: "!" > 306 | < TILDE: "~" > 307 | < HOOK: "?" > 308 | < COLON: ":" > 309 | < EQ: "==" > 310 | < LE: "<=" > 311 | < GE: ">=" > 312 | < NE: "!=" > 313 | < SC_OR: "||" > 314 | < SC_AND: "&&" > 315 | < INCR: "++" > 316 | < DECR: "--" > 317 | < PLUS: "+" > 318 | < MINUS: "-" > 319 | < STAR: "*" > 320 | < SLASH: "/" > 321 | < BIT_AND: "&" > 322 | < BIT_OR: "|" > 323 | < XOR: "^" > 324 | < REM: "%" > 325 | < LSHIFT: "<<" > 326 | < RSIGNEDSHIFT: ">>" > 327 | < RUNSIGNEDSHIFT: ">>>" > 328 | < PLUSASSIGN: "+=" > 329 | < MINUSASSIGN: "-=" > 330 | < STARASSIGN: "*=" > 331 | < SLASHASSIGN: "/=" > 332 | < ANDASSIGN: "&=" > 333 | < ORASSIGN: "|=" > 334 | < XORASSIGN: "^=" > 335 | < REMASSIGN: "%=" > 336 | < LSHIFTASSIGN: "<<=" > 337 | < RSIGNEDSHIFTASSIGN: ">>=" > 338 | < RUNSIGNEDSHIFTASSIGN: ">>>=" > 339 } 340 341 342 /***************************************** 343 * THE JAVA LANGUAGE GRAMMAR STARTS HERE * 344 *****************************************/ 345 346 /* 347 * Type, name and expression syntax follows. 348 */ 349 350 void Type() : 351 {} 352 { 353 ( PrimitiveType() | Name() ) ( "[" "]" )* 354 } 355 356 void PrimitiveType() : 357 {} 358 { 359 "boolean" 360 | 361 "char" 362 | 363 "byte" 364 | 365 "short" 366 | 367 "int" 368 | 369 "long" 370 | 371 "float" 372 | 373 "double" 374 } 375 376 377 String Name() : 378 {StringBuffer sb = new StringBuffer();} 379 { 380 <IDENTIFIER> { sb.append(token); } 381 ( LOOKAHEAD(2) "." <IDENTIFIER> { sb.append('.'); sb.append(token); } 382 )* 383 { return sb.toString(); } 384 } 385 386 void NameList() : 387 {} 388 { 389 Name() 390 ( "," Name() 391 )* 392 } 393 394 395 /* 396 * Expression syntax follows. 397 */ 398 399 void Expression() : 400 {} 401 { 402 LOOKAHEAD( PrimaryExpression() AssignmentOperator() ) 403 Assignment() 404 | 405 ConditionalExpression() 406 } 407 408 void Assignment() : 409 {} 410 { 411 PrimaryExpression() AssignmentOperator() Expression() 412 { LValue exprVal = pop(); pop().setValue(exprVal); push(exprVal);} 413 } 414 415 void AssignmentOperator() : 416 {} 417 { 418 "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | ">>>=" | "&=" | "^=" | "|=" 419 } 420 421 void ConditionalExpression() : 422 {} 423 { 424 ConditionalOrExpression() 425 [ "?" Expression() ":" ConditionalExpression() 426 { LValue falseBranch = pop(); LValue trueBranch = pop(); 427 Value cond = pop().interiorGetValue(); 428 if (cond instanceof BooleanValue) { 429 push(((BooleanValue)cond).booleanValue()? 430 trueBranch : falseBranch); 431 } else { 432 throw new ParseException("Condition must be boolean"); 433 } 434 } 435 ] 436 } 437 438 void ConditionalOrExpression() : 439 {} 440 { 441 ConditionalAndExpression() 442 ( "||" ConditionalAndExpression() 443 { throw new ParseException("operation not yet supported"); } 444 )* 445 } 446 447 void ConditionalAndExpression() : 448 {} 449 { 450 InclusiveOrExpression() 451 ( "&&" InclusiveOrExpression() 452 { throw new ParseException("operation not yet supported"); } 453 )* 454 } 455 456 void InclusiveOrExpression() : 457 {} 458 { 459 ExclusiveOrExpression() 460 ( "|" ExclusiveOrExpression() 461 { throw new ParseException("operation not yet supported"); } 462 )* 463 } 464 465 void ExclusiveOrExpression() : 466 {} 467 { 468 AndExpression() 469 ( "^" AndExpression() 470 { throw new ParseException("operation not yet supported"); } 471 )* 472 } 473 474 void AndExpression() : 475 {} 476 { 477 EqualityExpression() 478 ( "&" EqualityExpression() 479 { throw new ParseException("operation not yet supported"); } 480 )* 481 } 482 483 void EqualityExpression() : 484 {Token tok;} 485 { 486 InstanceOfExpression() 487 ( ( tok = "==" | tok = "!=" ) InstanceOfExpression() 488 { LValue left = pop(); 489 push( LValue.booleanOperation(vm, tok, pop(), left) ); } 490 )* 491 } 492 493 void InstanceOfExpression() : 494 {} 495 { 496 RelationalExpression() 497 [ "instanceof" Type() 498 { throw new ParseException("operation not yet supported"); } 499 ] 500 } 501 502 void RelationalExpression() : 503 {Token tok;} 504 { 505 ShiftExpression() 506 ( ( tok = "<" | tok = ">" | tok = "<=" | tok = ">=" ) ShiftExpression() 507 { LValue left = pop(); 508 push( LValue.booleanOperation(vm, tok, pop(), left) ); } 509 )* 510 } 511 512 void ShiftExpression() : 513 {} 514 { 515 AdditiveExpression() 516 ( ( "<<" | ">>" | ">>>" ) AdditiveExpression() 517 { throw new ParseException("operation not yet supported"); } 518 )* 519 } 520 521 void AdditiveExpression() : 522 {Token tok;} 523 { 524 MultiplicativeExpression() 525 ( ( tok = "+" | tok = "-" ) MultiplicativeExpression() 526 { LValue left = pop(); 527 push( LValue.operation(vm, tok, pop(), left, frameGetter) ); } 528 )* 529 } 530 531 void MultiplicativeExpression() : 532 {Token tok;} 533 { 534 UnaryExpression() 535 ( ( tok = "*" | tok = "/" | tok = "%" ) UnaryExpression() 536 { LValue left = pop(); 537 push( LValue.operation(vm, tok, pop(), left, frameGetter) ); } 538 )* 539 } 540 541 void UnaryExpression() : 542 {Token tok;} 543 { 544 ( tok = "+" | tok = "-" ) UnaryExpression() 545 { push( LValue.operation(vm, tok, pop(), frameGetter) ); } 546 | 547 PreIncrementExpression() 548 | 549 PreDecrementExpression() 550 | 551 UnaryExpressionNotPlusMinus() 552 } 553 554 void PreIncrementExpression() : 555 {} 556 { 557 "++" PrimaryExpression() 558 { throw new ParseException("operation not yet supported"); } 559 } 560 561 void PreDecrementExpression() : 562 {} 563 { 564 "--" PrimaryExpression() 565 { throw new ParseException("operation not yet supported"); } 566 } 567 568 void UnaryExpressionNotPlusMinus() : 569 {Token tok;} 570 { 571 ( tok = "~" | tok = "!" ) UnaryExpression() 572 { push( LValue.operation(vm, tok, pop(), frameGetter) ); } 573 | 574 LOOKAHEAD( CastLookahead() ) 575 CastExpression() 576 | 577 PostfixExpression() 578 } 579 580 // This production is to determine lookahead only. The LOOKAHEAD specifications 581 // below are not used, but they are there just to indicate that we know about 582 // this. 583 void CastLookahead() : 584 {} 585 { 586 LOOKAHEAD(2) 587 "(" PrimitiveType() 588 | 589 LOOKAHEAD("(" Name() "[") 590 "(" Name() "[" "]" 591 | 592 "(" Name() ")" ( "~" | "!" | "(" | <IDENTIFIER> | "this" | "super" | "new" | Literal() ) 593 } 594 595 void PostfixExpression() : 596 {} 597 { 598 PrimaryExpression() 599 [ "++" | "--" 600 { throw new ParseException("operation not yet supported"); } 601 ] 602 } 603 604 void CastExpression() : 605 {} 606 { 607 LOOKAHEAD(2) 608 "(" PrimitiveType() ( "[" "]" )* ")" UnaryExpression() 609 | 610 "(" Name() ( "[" "]" )* ")" UnaryExpressionNotPlusMinus() 611 } 612 613 void PrimaryExpression() : 614 {} 615 { 616 PrimaryPrefix() ( PrimarySuffix() )* 617 } 618 619 void PrimaryPrefix() : 620 {String name;} 621 { 622 Literal() 623 | 624 name = Name() 625 { push(LValue.makeName(vm, frameGetter, name)); } 626 | 627 "this" 628 { push(LValue.makeThisObject(vm, frameGetter, token)); } 629 | 630 "super" "." <IDENTIFIER> 631 { throw new ParseException("operation not yet supported"); } 632 | 633 "(" Expression() ")" 634 | 635 AllocationExpression() 636 } 637 638 void PrimarySuffix() : 639 {List argList;} 640 { 641 "[" Expression() "]" 642 { LValue index = pop(); 643 push(pop().arrayElementLValue(index)); } 644 | 645 "." <IDENTIFIER> 646 { push(pop().memberLValue(frameGetter, token.image)); } 647 | 648 argList = Arguments() 649 { peek().invokeWith(argList); } 650 } 651 652 void Literal() : 653 {} 654 { 655 <INTEGER_LITERAL> 656 { push(LValue.makeInteger(vm, token)); } 657 | 658 <FLOATING_POINT_LITERAL> 659 { push(LValue.makeFloat(vm, token)); } 660 | 661 <CHARACTER_LITERAL> 662 { push(LValue.makeCharacter(vm, token)); } 663 | 664 <STRING_LITERAL> 665 { push(LValue.makeString(vm, token)); } 666 | 667 BooleanLiteral() 668 { push(LValue.makeBoolean(vm, token)); } 669 | 670 NullLiteral() 671 { push(LValue.makeNull(vm, token)); } 672 } 673 674 void BooleanLiteral() : 675 {} 676 { 677 "true" 678 | 679 "false" 680 } 681 682 void NullLiteral() : 683 {} 684 { 685 "null" 686 } 687 688 List Arguments() : 689 {List argList = new ArrayList();} 690 { 691 "(" [ ArgumentList(argList) ] ")" 692 { return argList; } 693 } 694 695 void ArgumentList(List argList) : 696 {} 697 { 698 Expression() {argList.add(pop().interiorGetValue());} 699 ( "," Expression() {argList.add(pop().interiorGetValue());} )* 700 } 701 702 void AllocationExpression() : 703 {List argList; String className;} 704 { 705 LOOKAHEAD(2) 706 "new" PrimitiveType() ArrayDimensions() 707 | 708 "new" className = Name() ( argList = Arguments() 709 { push(LValue.makeNewObject(vm, frameGetter, className, argList)); } 710 | ArrayDimensions() 711 { throw new ParseException("operation not yet supported"); } 712 ) 713 } 714 715 /* 716 * The second LOOKAHEAD specification below is to parse to PrimarySuffix 717 * if there is an expression between the "[...]". 718 */ 719 void ArrayDimensions() : 720 {} 721 { 722 ( LOOKAHEAD(2) "[" Expression() "]" )+ ( LOOKAHEAD(2) "[" "]" )* 723 } 724