blob: cc955957751992ab788898ccd757405a509377e3 [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 1998-2003 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26options {
27 JAVA_UNICODE_ESCAPE = true;
28 STATIC = false;
29}
30
31PARSER_BEGIN(ExpressionParser)
32
33package com.sun.tools.example.debug.expr;
34
35import com.sun.jdi.*;
36import java.util.Stack;
37import java.util.List;
38import java.util.ArrayList;
39
40public 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
120PARSER_END(ExpressionParser)
121
122
123SKIP : /* WHITE SPACE */
124{
125 " "
126| "\t"
127| "\n"
128| "\r"
129| "\f"
130}
131
132SPECIAL_TOKEN : /* COMMENTS */
133{
134 <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
135| <FORMAL_COMMENT: "/**" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
136| <MULTI_LINE_COMMENT: "/*" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
137}
138
139TOKEN : /* 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
193TOKEN : /* 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
244TOKEN : /* 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
287TOKEN : /* SEPARATORS */
288{
289 < LPAREN: "(" >
290| < RPAREN: ")" >
291| < LBRACE: "{" >
292| < RBRACE: "}" >
293| < LBRACKET: "[" >
294| < RBRACKET: "]" >
295| < SEMICOLON: ";" >
296| < COMMA: "," >
297| < DOT: "." >
298}
299
300TOKEN : /* 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
350void Type() :
351{}
352{
353 ( PrimitiveType() | Name() ) ( "[" "]" )*
354}
355
356void 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
377String 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
386void NameList() :
387{}
388{
389 Name()
390 ( "," Name()
391 )*
392}
393
394
395/*
396 * Expression syntax follows.
397 */
398
399void Expression() :
400{}
401{
402 LOOKAHEAD( PrimaryExpression() AssignmentOperator() )
403 Assignment()
404|
405 ConditionalExpression()
406}
407
408void Assignment() :
409{}
410{
411 PrimaryExpression() AssignmentOperator() Expression()
412 { LValue exprVal = pop(); pop().setValue(exprVal); push(exprVal);}
413}
414
415void AssignmentOperator() :
416{}
417{
418 "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | ">>>=" | "&=" | "^=" | "|="
419}
420
421void 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
438void ConditionalOrExpression() :
439{}
440{
441 ConditionalAndExpression()
442 ( "||" ConditionalAndExpression()
443 { throw new ParseException("operation not yet supported"); }
444 )*
445}
446
447void ConditionalAndExpression() :
448{}
449{
450 InclusiveOrExpression()
451 ( "&&" InclusiveOrExpression()
452 { throw new ParseException("operation not yet supported"); }
453 )*
454}
455
456void InclusiveOrExpression() :
457{}
458{
459 ExclusiveOrExpression()
460 ( "|" ExclusiveOrExpression()
461 { throw new ParseException("operation not yet supported"); }
462 )*
463}
464
465void ExclusiveOrExpression() :
466{}
467{
468 AndExpression()
469 ( "^" AndExpression()
470 { throw new ParseException("operation not yet supported"); }
471 )*
472}
473
474void AndExpression() :
475{}
476{
477 EqualityExpression()
478 ( "&" EqualityExpression()
479 { throw new ParseException("operation not yet supported"); }
480 )*
481}
482
483void 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
493void InstanceOfExpression() :
494{}
495{
496 RelationalExpression()
497 [ "instanceof" Type()
498 { throw new ParseException("operation not yet supported"); }
499 ]
500}
501
502void 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
512void ShiftExpression() :
513{}
514{
515 AdditiveExpression()
516 ( ( "<<" | ">>" | ">>>" ) AdditiveExpression()
517 { throw new ParseException("operation not yet supported"); }
518 )*
519}
520
521void 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
531void 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
541void UnaryExpression() :
542{}
543{
544 ( "+" | "-" ) UnaryExpression()
545 { throw new ParseException("operation not yet supported"); }
546|
547 PreIncrementExpression()
548|
549 PreDecrementExpression()
550|
551 UnaryExpressionNotPlusMinus()
552}
553
554void PreIncrementExpression() :
555{}
556{
557 "++" PrimaryExpression()
558 { throw new ParseException("operation not yet supported"); }
559}
560
561void PreDecrementExpression() :
562{}
563{
564 "--" PrimaryExpression()
565 { throw new ParseException("operation not yet supported"); }
566}
567
568void UnaryExpressionNotPlusMinus() :
569{}
570{
571 ( "~" | "!" ) UnaryExpression()
572 { throw new ParseException("operation not yet supported"); }
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.
583void CastLookahead() :
584{}
585{
586 LOOKAHEAD(2)
587 "(" PrimitiveType()
588|
589 LOOKAHEAD("(" Name() "[")
590 "(" Name() "[" "]"
591|
592 "(" Name() ")" ( "~" | "!" | "(" | <IDENTIFIER> | "this" | "super" | "new" | Literal() )
593}
594
595void PostfixExpression() :
596{}
597{
598 PrimaryExpression()
599 [ "++" | "--"
600 { throw new ParseException("operation not yet supported"); }
601 ]
602}
603
604void CastExpression() :
605{}
606{
607 LOOKAHEAD(2)
608 "(" PrimitiveType() ( "[" "]" )* ")" UnaryExpression()
609|
610 "(" Name() ( "[" "]" )* ")" UnaryExpressionNotPlusMinus()
611}
612
613void PrimaryExpression() :
614{}
615{
616 PrimaryPrefix() ( PrimarySuffix() )*
617}
618
619void 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
638void 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
652void 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
674void BooleanLiteral() :
675{}
676{
677 "true"
678|
679 "false"
680}
681
682void NullLiteral() :
683{}
684{
685 "null"
686}
687
688List Arguments() :
689{List argList = new ArrayList();}
690{
691 "(" [ ArgumentList(argList) ] ")"
692 { return argList; }
693}
694
695void ArgumentList(List argList) :
696{}
697{
698 Expression() {argList.add(pop().interiorGetValue());}
699 ( "," Expression() {argList.add(pop().interiorGetValue());} )*
700}
701
702void 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 */
719void ArrayDimensions() :
720{}
721{
722 ( LOOKAHEAD(2) "[" Expression() "]" )+ ( LOOKAHEAD(2) "[" "]" )*
723}
724