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