/jEdit/tags/jedit-4-0-pre4/bsh/bsh.jjt
# · Unknown · 1195 lines · 1089 code · 106 blank · 0 comment · 0 complexity · cb41e2878bc3dc093a926d24cf66fd82 MD5 · raw file
- /*****************************************************************************
- * *
- * This file is part of the BeanShell Java Scripting distribution. *
- * Documentation and updates may be found at http://www.beanshell.org/ *
- * *
- * Sun Public License Notice: *
- * *
- * The contents of this file are subject to the Sun Public License Version *
- * 1.0 (the "License"); you may not use this file except in compliance with *
- * the License. A copy of the License is available at http://www.sun.com *
- * *
- * The Original Code is BeanShell. The Initial Developer of the Original *
- * Code is Pat Niemeyer. Portions created by Pat Niemeyer are Copyright *
- * (C) 2000. All Rights Reserved. *
- * *
- * GNU Public License Notice: *
- * *
- * Alternatively, the contents of this file may be used under the terms of *
- * the GNU Lesser General Public License (the "LGPL"), in which case the *
- * provisions of LGPL are applicable instead of those above. If you wish to *
- * allow use of your version of this file only under the terms of the LGPL *
- * and not to allow others to use your version of this file under the SPL, *
- * indicate your decision by deleting the provisions above and replace *
- * them with the notice and other provisions required by the LGPL. If you *
- * do not delete the provisions above, a recipient may use your version of *
- * this file under either the SPL or the LGPL. *
- * *
- * Patrick Niemeyer (pat@pat.net) *
- * Author of Learning Java, O'Reilly & Associates *
- * http://www.pat.net/~pat/ *
- * *
- *****************************************************************************/
- /*
- Notes:
- There is probably a lot of room for improvement in here.
- All of the syntactic lookaheads have been commented with:
- SYNTACTIC_LOOKAHEAD
- These are probably expensive and we may want to start weeding them out
- where possible.
- */
- options {
- JAVA_UNICODE_ESCAPE=true;
- STATIC=false;
- MULTI=true;
- NODE_DEFAULT_VOID=true;
- NODE_SCOPE_HOOK=true;
- NODE_PREFIX="BSH";
- /* Print grammar debugging info as we parse
- DEBUG_PARSER=true; */
- /* Print detailed lookahead debugging info
- DEBUG_LOOKAHEAD=true; */
- }
- PARSER_BEGIN(Parser)
- package bsh;
- import java.io.Reader;
- class Parser {
- void jjtreeOpenNodeScope(Node n) {
- ((SimpleNode)n).firstToken = getToken(1);
- }
- void jjtreeCloseNodeScope(Node n) {
- ((SimpleNode)n).lastToken = getToken(0);
- }
- /**
- Re-initialize the input stream and token source.
- */
- void reInitInput( Reader in ) {
- ReInit(in);
- }
- /**
- Explicitly re-initialize just the token reader.
- This seems to be necessary to avoid certain looping errors when
- reading bogus input. See Interpreter.
- */
- void reInitTokenInput( Reader in ) {
- jj_input_stream.ReInit( in,
- jj_input_stream.getEndLine(),
- jj_input_stream.getEndColumn() );
- }
- }
- PARSER_END(Parser)
- SKIP : /* WHITE SPACE */
- {
- " " | "\t" | "\r" | "\f"
- | "\n"
- | < NONPRINTABLE: (["\u0000"-"\u0020", "\u0080"-"\u00ff"])+ >
- }
- SPECIAL_TOKEN : /* COMMENTS */
- {
- /*
- Single line comments fail on the last line of a file with no terminating
- linefeed. I thought the <EOF> would fix that, but no...
- <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* "<EOF>"|("\n"|"\r"|"\r\n")>
- */
- <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
- | <HASH_BANG_COMMENT: "#!" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
- | <FORMAL_COMMENT: "/**" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
- | <MULTI_LINE_COMMENT: "/*" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
- }
- TOKEN : /* RESERVED WORDS AND LITERALS */
- {
- < BOOLEAN: "boolean" >
- | < BREAK: "break" >
- | < CLASS: "class" >
- | < BYTE: "byte" >
- | < CASE: "case" >
- | < CATCH: "catch" >
- | < CHAR: "char" >
- | < CONST: "const" >
- | < CONTINUE: "continue" >
- | < _DEFAULT: "default" >
- | < DO: "do" >
- | < DOUBLE: "double" >
- | < ELSE: "else" >
- | < FALSE: "false" >
- | < FINAL: "final" >
- | < FINALLY: "finally" >
- | < FLOAT: "float" >
- | < FOR: "for" >
- | < GOTO: "goto" >
- | < IF: "if" >
- | < IMPORT: "import" >
- | < INSTANCEOF: "instanceof" >
- | < INT: "int" >
- | < INTERFACE: "interface" >
- | < LONG: "long" >
- | < NEW: "new" >
- | < NULL: "null" >
- | < PRIVATE: "private" >
- | < PROTECTED: "protected" >
- | < PUBLIC: "public" >
- | < RETURN: "return" >
- | < SHORT: "short" >
- | < STATIC: "static" >
- | < SWITCH: "switch" >
- | < THROW: "throw" >
- | < TRUE: "true" >
- | < TRY: "try" >
- | < VOID: "void" >
- | < WHILE: "while" >
- }
- TOKEN : /* LITERALS */
- {
- < INTEGER_LITERAL:
- <DECIMAL_LITERAL> (["l","L"])?
- | <HEX_LITERAL> (["l","L"])?
- | <OCTAL_LITERAL> (["l","L"])?
- >
- |
- < #DECIMAL_LITERAL: ["1"-"9"] (["0"-"9"])* >
- |
- < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])+ >
- |
- < #OCTAL_LITERAL: "0" (["0"-"7"])* >
- |
- < FLOATING_POINT_LITERAL:
- (["0"-"9"])+ "." (["0"-"9"])* (<EXPONENT>)? (["f","F","d","D"])?
- | "." (["0"-"9"])+ (<EXPONENT>)? (["f","F","d","D"])?
- | (["0"-"9"])+ <EXPONENT> (["f","F","d","D"])?
- | (["0"-"9"])+ (<EXPONENT>)? ["f","F","d","D"]
- >
- |
- < #EXPONENT: ["e","E"] (["+","-"])? (["0"-"9"])+ >
- |
- < CHARACTER_LITERAL:
- "'"
- ( (~["'","\\","\n","\r"])
- | ("\\"
- ( ["n","t","b","r","f","\\","'","\""]
- | ["0"-"7"] ( ["0"-"7"] )?
- | ["0"-"3"] ["0"-"7"] ["0"-"7"]
- )
- )
- )
- "'"
- >
- |
- < STRING_LITERAL:
- "\""
- ( (~["\"","\\","\n","\r"])
- | ("\\"
- ( ["n","t","b","r","f","\\","'","\""]
- | ["0"-"7"] ( ["0"-"7"] )?
- | ["0"-"3"] ["0"-"7"] ["0"-"7"]
- )
- )
- )*
- "\""
- >
- }
- TOKEN : /* IDENTIFIERS */
- {
- < IDENTIFIER: <LETTER> (<LETTER>|<DIGIT>)* >
- |
- < #LETTER:
- [
- "\u0024",
- "\u0041"-"\u005a",
- "\u005f",
- "\u0061"-"\u007a",
- "\u00c0"-"\u00d6",
- "\u00d8"-"\u00f6",
- "\u00f8"-"\u00ff",
- "\u0100"-"\u1fff",
- "\u3040"-"\u318f",
- "\u3300"-"\u337f",
- "\u3400"-"\u3d2d",
- "\u4e00"-"\u9fff",
- "\uf900"-"\ufaff"
- ]
- >
- |
- < #DIGIT:
- [
- "\u0030"-"\u0039",
- "\u0660"-"\u0669",
- "\u06f0"-"\u06f9",
- "\u0966"-"\u096f",
- "\u09e6"-"\u09ef",
- "\u0a66"-"\u0a6f",
- "\u0ae6"-"\u0aef",
- "\u0b66"-"\u0b6f",
- "\u0be7"-"\u0bef",
- "\u0c66"-"\u0c6f",
- "\u0ce6"-"\u0cef",
- "\u0d66"-"\u0d6f",
- "\u0e50"-"\u0e59",
- "\u0ed0"-"\u0ed9",
- "\u1040"-"\u1049"
- ]
- >
- }
- TOKEN : /* SEPARATORS */
- {
- < LPAREN: "(" >
- | < RPAREN: ")" >
- | < LBRACE: "{" >
- | < RBRACE: "}" >
- | < LBRACKET: "[" >
- | < RBRACKET: "]" >
- | < SEMICOLON: ";" >
- | < COMMA: "," >
- | < DOT: "." >
- }
- TOKEN : /* OPERATORS */
- {
- < ASSIGN: "=" >
- | < GT: ">" >
- | < GTX: "@gt" >
- | < LT: "<" >
- | < LTX: "@lt" >
- | < BANG: "!" >
- | < TILDE: "~" >
- | < HOOK: "?" >
- | < COLON: ":" >
- | < EQ: "==" >
- | < LE: "<=" >
- | < LEX: "@lteq" >
- | < GE: ">=" >
- | < GEX: "@gteq" >
- | < NE: "!=" >
- | < BOOL_OR: "||" >
- | < BOOL_ORX: "@or" >
- | < BOOL_AND: "&&" >
- | < BOOL_ANDX: "@and" >
- | < INCR: "++" >
- | < DECR: "--" >
- | < PLUS: "+" >
- | < MINUS: "-" >
- | < STAR: "*" >
- | < SLASH: "/" >
- | < BIT_AND: "&" >
- | < BIT_ANDX: "@bitwise_and" >
- | < BIT_OR: "|" >
- | < BIT_ORX: "@bitwise_or" >
- | < XOR: "^" >
- | < MOD: "%" >
- | < LSHIFT: "<<" >
- | < LSHIFTX: "@left_shift" >
- | < RSIGNEDSHIFT: ">>" >
- | < RSIGNEDSHIFTX: "@right_shift" >
- | < RUNSIGNEDSHIFT: ">>>" >
- | < RUNSIGNEDSHIFTX: "@right_unsigned_shift" >
- | < PLUSASSIGN: "+=" >
- | < MINUSASSIGN: "-=" >
- | < STARASSIGN: "*=" >
- | < SLASHASSIGN: "/=" >
- | < ANDASSIGN: "&=" >
- | < ANDASSIGNX: "@and_assign" >
- | < ORASSIGN: "|=" >
- | < ORASSIGNX: "@or_assign" >
- | < XORASSIGN: "^=" >
- | < MODASSIGN: "%=" >
- | < LSHIFTASSIGN: "<<=" >
- | < LSHIFTASSIGNX: "@left_shift_assign" >
- | < RSIGNEDSHIFTASSIGN: ">>=" >
- | < RSIGNEDSHIFTASSIGNX: "@right_shift_assign" >
- | < RUNSIGNEDSHIFTASSIGN: ">>>=" >
- | < RUNSIGNEDSHIFTASSIGNX: "@right_unsigned_shift_assign" >
- }
- boolean Line() :
- {}
- {
- <EOF> {
- Interpreter.debug("End of File!");
- return true;
- }
- |
- (
- /*
- SYNTACTIC_LOOKAHEAD
- I'm guessing this is expensive, but I don't know how to work around
- it... Is there another syntactic indication that we are working
- through an expression as opposed to a statement?
- What is the difference? Well, some statements don't require a
- semicolon and they don't return vlues... We could probably broaden
- bsh to allow everything to return a value, but the semi-colon thing
- is tougher. You don't want to have to say if ( foo ) { } ;
- Maybe we can invert ths and enumerate all of those types of
- statements in a special lookahead that's cheaper??
- */
- LOOKAHEAD( Expression() ";" )
- Expression() ";"
- |
- BlockStatement()
- )
- {
- return false;
- }
- }
- /*****************************************
- * THE JAVA LANGUAGE GRAMMAR STARTS HERE *
- *****************************************/
- void MethodDeclaration() #MethodDeclaration :
- { Token t = null; }
- {
- // SYNTACTIC_LOOKAHEAD
- // this one seems cheap enough
- LOOKAHEAD( MethodDeclarationTypeLookahead() )
- ReturnType() t = <IDENTIFIER> { jjtThis.name = t.image; }
- FormalParameters() Block()
- |
- t = <IDENTIFIER> { jjtThis.name = t.image; }
- FormalParameters() Block()
- }
- void MethodDeclarationLookahead() : { }
- {
- // SYNTACTIC_LOOKAHEAD
- // this one seems cheap enough
- LOOKAHEAD( MethodDeclarationTypeLookahead() )
- ReturnType() <IDENTIFIER> FormalParameters() "{"
- |
- <IDENTIFIER> FormalParameters() "{"
- }
- void MethodDeclarationTypeLookahead() : { }
- {
- ReturnType() <IDENTIFIER> "("
- }
- void ImportDeclaration() #ImportDeclaration :
- {
- Token t = null;
- }
- {
- LOOKAHEAD( 2 )
- "import" AmbiguousName() [ t = "." "*" ] ";" {
- if ( t != null )
- jjtThis.importPackage = true;
- }
- |
- // bsh super import statement
- "import" "*" ";" {
- jjtThis.superImport = true;
- }
- }
- void VariableDeclarator() #VariableDeclarator :
- { Token t; }
- {
- t=<IDENTIFIER> [ "=" VariableInitializer() ] { jjtThis.name = t.image; }
- }
- /*
- Can get rid of this if we ignore postfix array dimensions in declarations.
- I don't like them and I don't want to deal with them right now.
- void VariableDeclaratorId() #VariableDeclaratorId :
- { Token t; }
- {
- t=<IDENTIFIER> { jjtThis.name = t.image; }
- ( "[" "]" { jjtThis.addArrayDimension(); } )*
- }
- */
- void VariableInitializer() :
- {}
- {
- ArrayInitializer()
- |
- Expression()
- }
- void ArrayInitializer() #ArrayInitializer :
- {}
- {
- "{" [ VariableInitializer()
- ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ] "}"
- }
- void FormalParameters() #FormalParameters :
- {}
- {
- "(" [ FormalParameter() ( "," FormalParameter() )* ] ")"
- }
- /*
- void FormalParameter() #FormalParameter :
- { Token t; }
- {
- // added [] to Type for bsh. Removed [ final ] - is that legal?
- [ LOOKAHEAD(2) Type() ] t=<IDENTIFIER> { jjtThis.name = t.image; }
- }
- */
- void FormalParameter() #FormalParameter :
- { Token t; }
- {
- // added [] to Type for bsh. Removed [ final ] - is that legal?
- LOOKAHEAD(2) Type() t=<IDENTIFIER> { jjtThis.name = t.image; }
- |
- t=<IDENTIFIER> { jjtThis.name = t.image; }
- }
- /*
- Type, name and expression syntax follows.
- */
- void Type() #Type :
- { }
- {
- /*
- The embedded lookahead is (was?) necessary to disambiguate for
- PrimaryPrefix. ( )* is a choice point. It took me a while to
- figure out where to put that. This stuff is annoying.
- */
- ( PrimitiveType() | AmbiguousName() )
- ( LOOKAHEAD(2) "[" "]" { jjtThis.addArrayDimension(); } )*
- }
- /*
- Originally called ResultType in the grammar
- */
- void ReturnType() #ReturnType :
- { }
- {
- "void" { jjtThis.isVoid = true; }
- |
- Type()
- }
- void PrimitiveType() #PrimitiveType :
- { } {
- "boolean" { jjtThis.type = Boolean.TYPE; }
- | "char" { jjtThis.type = Character.TYPE; }
- | "byte" { jjtThis.type = Byte.TYPE; }
- | "short" { jjtThis.type = Short.TYPE; }
- | "int" { jjtThis.type = Integer.TYPE; }
- | "long" { jjtThis.type = Long.TYPE; }
- | "float" { jjtThis.type = Float.TYPE; }
- | "double" { jjtThis.type = Double.TYPE; }
- }
- void AmbiguousName() #AmbiguousName :
- /*
- * A lookahead of 2 is required below since "Name" can be followed
- * by a ".*" when used in the context of an "ImportDeclaration".
- */
- {
- Token t;
- StringBuffer s;
- }
- {
- t = <IDENTIFIER> {
- s = new StringBuffer(t.image);
- }
- ( LOOKAHEAD(2) "." t = <IDENTIFIER> {
- s.append("."+t.image);
- }
- )* {
- jjtThis.text = s.toString();
- }
- }
- /*
- * Expression syntax follows.
- */
- void Expression() :
- { }
- {
- /**
- SYNTACTIC_LOOKAHEAD
- This is probably expensive. Can we simplify it somehow?
- */
- LOOKAHEAD( LHSPrimaryExpression() AssignmentOperator() )
- Assignment()
- |
- ConditionalExpression()
- }
- void Assignment() #Assignment :
- { int op ; }
- {
- LHSPrimaryExpression()
- op = AssignmentOperator() {
- jjtThis.operator = op;
- }
- Expression()
- }
- int AssignmentOperator() :
- { Token t; }
- {
- ( "=" | "*=" | "/=" | "%=" | "+=" | "-=" | "&=" | "^=" | "|=" |
- "<<=" | "@left_shift_assign" | ">>=" | "@right_shift_assign" |
- ">>>=" | "@right_unsigned_shift_assign" )
- {
- t = getToken(0);
- return t.kind;
- }
- }
- void ConditionalExpression() :
- { }
- {
- ConditionalOrExpression() [ "?" Expression() ":" ConditionalExpression()
- #TernaryExpression(3) ]
- }
- void ConditionalOrExpression() :
- { Token t=null; }
- {
- ConditionalAndExpression()
- ( ( t = "||" | t = "@or" )
- ConditionalAndExpression()
- { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
- }
- void ConditionalAndExpression() :
- { Token t=null; }
- {
- InclusiveOrExpression()
- ( ( t = "&&" | t = "@and" )
- InclusiveOrExpression()
- { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
- }
- void InclusiveOrExpression() :
- { Token t=null; }
- {
- ExclusiveOrExpression()
- ( ( t = "|" | t = "@bitwise_or" )
- ExclusiveOrExpression()
- { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
- }
- void ExclusiveOrExpression() :
- { Token t=null; }
- {
- AndExpression() ( t="^" AndExpression()
- { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
- }
- void AndExpression() :
- { Token t=null; }
- {
- EqualityExpression()
- ( ( t = "&" | t = "@bitwise_and" )
- EqualityExpression()
- { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
- }
- void EqualityExpression() :
- { Token t = null; }
- {
- InstanceOfExpression() ( ( t= "==" | t= "!=" ) InstanceOfExpression()
- { jjtThis.kind = t.kind; } #BinaryExpression(2)
- )*
- }
- void InstanceOfExpression() :
- { Token t = null; }
- {
- RelationalExpression()
- [ t = "instanceof" Type() { jjtThis.kind = t.kind; } #BinaryExpression(2) ]
- }
- void RelationalExpression() :
- { Token t = null; }
- {
- ShiftExpression()
- ( ( t = "<" | t = "@lt" | t = ">" | t = "@gt" |
- t = "<=" | t = "@lteq" | t = ">=" | t = "@gteq" )
- ShiftExpression()
- { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
- }
- void ShiftExpression() :
- { Token t = null; }
- {
- AdditiveExpression()
- ( ( t = "<<" | t = "@left_shift" | t = ">>" | t = "@right_shift" |
- t = ">>>" | t = "@right_unsigned_shift" )
- AdditiveExpression()
- { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
- }
- void AdditiveExpression() :
- { Token t = null; }
- {
- MultiplicativeExpression()
- ( ( t= "+" | t= "-" ) MultiplicativeExpression() { jjtThis.kind = t.kind; }
- #BinaryExpression(2)
- )*
- }
- void MultiplicativeExpression() :
- { Token t = null; }
- {
- UnaryExpression() ( ( t= "*" | t= "/" | t= "%" )
- UnaryExpression() { jjtThis.kind = t.kind; } #BinaryExpression(2) )*
- }
- void UnaryExpression() :
- { Token t = null; }
- {
- ( t="+" | t="-" ) UnaryExpression()
- { jjtThis.kind = t.kind; } #UnaryExpression(1)
- |
- PreIncrementExpression()
- |
- PreDecrementExpression()
- |
- UnaryExpressionNotPlusMinus()
- }
- void PreIncrementExpression() :
- { Token t = null; }
- {
- t="++" LHSPrimaryExpression()
- { jjtThis.kind = t.kind; } #UnaryExpression(1)
- }
- void PreDecrementExpression() :
- { Token t = null; }
- {
- t="--" LHSPrimaryExpression()
- { jjtThis.kind = t.kind; } #UnaryExpression(1)
- }
- void UnaryExpressionNotPlusMinus() :
- { Token t = null; }
- {
- ( t="~" | t="!" ) UnaryExpression()
- { jjtThis.kind = t.kind; } #UnaryExpression(1)
- |
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD( CastLookahead() ) CastExpression()
- |
- PostfixExpression()
- }
- // This production is to determine lookahead only.
- void CastLookahead() : { }
- {
- LOOKAHEAD(2) "(" PrimitiveType()
- |
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD( "(" AmbiguousName() "[" ) "(" AmbiguousName() "[" "]"
- |
- "(" AmbiguousName() ")" ( "~" | "!" | "(" | <IDENTIFIER> | /* "this" | "super" | */ "new" | Literal() )
- }
- void PostfixExpression() :
- { Token t = null; }
- {
- (
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD( LHSPrimaryExpression() ("++"|"--") )
- LHSPrimaryExpression()
- [ ( t="++" | t="--" ) {
- jjtThis.kind = t.kind; jjtThis.postfix = true; } #UnaryExpression(1) ]
- |
- PrimaryExpression()
- )
- }
- void CastExpression() #CastExpression :
- { }
- {
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD( "(" PrimitiveType() ) "(" Type() ")" UnaryExpression()
- |
- "(" Type() ")" UnaryExpressionNotPlusMinus()
- }
- void PrimaryExpression() #PrimaryExpression : { }
- {
- PrimaryPrefix() ( PrimarySuffix() )*
- }
- // The MethodInvocation node here simplifies the prefix/suffix parsing a bit
- // by forcing the prefix to an object.
- void PrimaryPrefix() : { }
- {
- Literal()
- |
- "(" Expression() ")"
- |
- AllocationExpression()
- |
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD( Type() "." "class" )
- Type()
- |
- /*
- Handle method invocation OR straight ambigous name...
- (probably should just write this as two rules more clearly)
- */
- ( AmbiguousName() [ Arguments() ] ) #MethodInvocation(>1)
- /*
- |
- LOOKAHEAD( "void" "." "class" )
- */
- }
- void PrimarySuffix() #PrimarySuffix :
- {
- Token t = null;
- }
- {
- LOOKAHEAD(2)
- "." "class" {
- jjtThis.operation = BSHPrimarySuffix.CLASS;
- }
- |
- "[" Expression() "]" {
- jjtThis.operation = BSHPrimarySuffix.INDEX;
- }
- |
- // Field access or method invocation
- "." t = <IDENTIFIER> [ Arguments() ] {
- jjtThis.operation = BSHPrimarySuffix.NAME;
- jjtThis.field = t.image;
- }
- |
- "{" Expression() "}" {
- jjtThis.operation = BSHPrimarySuffix.PROPERTY;
- }
- /*
- For inner classes
- |
- LOOKAHEAD(2)
- "." AllocationExpression()
- */
- }
- /*
- Begin LHS part of the grammar --
- The reason this stuff is duplicated (e.g. LHSPrimaryPrefix and
- PrimaryPrefix) is that the whole grammar splits based on whether we
- are preparig to do an assignment or not. This is an important issue
- to revisit in the future.
- */
- /**
- The method invocation is here to force this to an object type in order
- to simplify the suffix processing.
- */
- void LHSPrimaryPrefix() : { }
- {
- /*
- Method invocation or simple ambiguous name.
- (probably should just write this as two rules more clearly)
- */
- ( AmbiguousName() [ Arguments() ] ) #MethodInvocation(>1)
- }
- void LHSPrimaryExpression() #LHSPrimaryExpression : { }
- {
- LHSPrimaryPrefix() ( LHSPrimarySuffix( ) )*
- }
- void LHSPrimarySuffix() #LHSPrimarySuffix :
- {
- Token t=null, t1, t2 = null;
- }
- {
- // Indexed to a field
- "[" Expression() "]" {
- jjtThis.operation = BSHLHSPrimarySuffix.INDEX;
- }
- |
- // Field access or method invocation followed by field access
- "." t1 = <IDENTIFIER> [ Arguments() "." t2 = <IDENTIFIER> ] {
- jjtThis.operation = BSHLHSPrimarySuffix.NAME;
- if ( t2 == null )
- jjtThis.field = t1.image;
- else {
- jjtThis.method = t1.image;
- jjtThis.field = t2.image;
- }
- }
- |
- "{" Expression() "}" {
- jjtThis.operation = BSHLHSPrimarySuffix.PROPERTY;
- }
- }
- /*
- -- End LHS part of the grammar
- */
- void Literal() #Literal :
- {
- Token x;
- boolean b;
- String literal;
- char ch;
- }
- {
- x = <INTEGER_LITERAL>
- {
- literal = x.image;
- ch = literal.charAt(literal.length()-1);
- if(ch == 'l' || ch == 'L')
- {
- literal = literal.substring(0,literal.length()-1);
- // This really should be Long.decode, but there isn't one. As a result,
- // hex and octal literals ending in 'l' or 'L' don't work.
- jjtThis.value = new Primitive( new Long( literal ) );
- }
- else
- jjtThis.value = new Primitive( Integer.decode( literal ) );
- }
- |
- x = <FLOATING_POINT_LITERAL>
- {
- literal = x.image;
- ch = literal.charAt(literal.length()-1);
- if(ch == 'f' || ch == 'F')
- {
- literal = literal.substring(0,literal.length()-1);
- jjtThis.value = new Primitive( new Float( literal ) );
- }
- else
- {
- if(ch == 'd' || ch == 'D')
- literal = literal.substring(0,literal.length()-1);
- jjtThis.value = new Primitive( new Double( literal ) );
- }
- }
- |
- x = <CHARACTER_LITERAL> {
- try {
- jjtThis.charSetup( x.image.substring(1, x.image.length() - 1) );
- } catch ( Exception e ) {
- throw new ParseException("Error parsing character: "+x.image);
- }
- }
- |
- x = <STRING_LITERAL> {
- try {
- jjtThis.stringSetup( x.image.substring(1, x.image.length() - 1) );
- } catch ( Exception e ) {
- throw new ParseException("Error parsing string: "+x.image);
- }
- }
- |
- b = BooleanLiteral() {
- jjtThis.value = new Primitive( new Boolean(b) ); }
- |
- NullLiteral() {
- jjtThis.value = Primitive.NULL;
- }
- |
- VoidLiteral() {
- jjtThis.value = Primitive.VOID; }
- }
- boolean BooleanLiteral() :
- {}
- {
- "true" { return true; }
- |
- "false" { return false; }
- }
- void NullLiteral() :
- {}
- {
- "null"
- }
- void VoidLiteral() :
- {}
- {
- "void"
- }
- void Arguments() #Arguments :
- { }
- {
- "(" [ ArgumentList() ] ")"
- }
- // leave these on the stack for Arguments() to handle
- void ArgumentList() :
- { }
- {
- Expression()
- ( "," Expression() )*
- }
- void AllocationExpression() #AllocationExpression :
- { }
- {
- LOOKAHEAD(2)
- "new" PrimitiveType() ArrayDimensions()
- |
- "new" AmbiguousName()
- (
- ArrayDimensions()
- |
- // SYNTACTIC_LOOKAHEAD
- Arguments() [ LOOKAHEAD(2) Block() ]
- )
- }
- void ArrayDimensions() #ArrayDimensions :
- {}
- {
- LOOKAHEAD(2)
- ( LOOKAHEAD(2) "[" Expression() "]" { jjtThis.addArrayDimension(); } )+
- // Removed trailing "[]" identifiers. Specify array dims fully.
- |
- ( "[" "]" { jjtThis.addArrayDimension(); } )+ ArrayInitializer()
- }
- /*
- * Statement syntax follows.
- */
- void Statement() : { }
- {
- LOOKAHEAD(2)
- LabeledStatement()
- |
- Block()
- |
- EmptyStatement()
- |
- StatementExpression() ";"
- |
- SwitchStatement()
- |
- IfStatement()
- |
- WhileStatement()
- |
- DoStatement()
- |
- ForStatement()
- |
- BreakStatement()
- |
- ContinueStatement()
- |
- ReturnStatement()
- |
- ThrowStatement()
- |
- TryStatement()
- }
- void LabeledStatement() :
- {}
- {
- <IDENTIFIER> ":" Statement()
- }
- void Block() #Block :
- {}
- {
- "{" ( BlockStatement() )* "}"
- }
- void BlockStatement() :
- {}
- {
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD( MethodDeclarationLookahead() ) MethodDeclaration()
- |
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD([ "final" ] Type() <IDENTIFIER>)
- TypedVariableDeclaration() ";"
- |
- Statement()
- /* end */
- |
- // Allow BeanShell imports in any block
- ImportDeclaration()
- }
- void EmptyStatement() :
- {}
- {
- ";"
- }
- void StatementExpression() :
- /*
- * The last expansion of this production accepts more than the legal
- * Java expansions for StatementExpression.
- */
- { }
- {
- PreIncrementExpression()
- |
- PreDecrementExpression()
- |
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD( PrimaryExpression() AssignmentOperator() )
- Assignment() { }
- |
- PostfixExpression()
- }
- void SwitchStatement() #SwitchStatement :
- {}
- {
- "switch" "(" Expression() ")" "{"
- ( SwitchLabel() ( BlockStatement() )* )*
- "}"
- }
- void SwitchLabel() #SwitchLabel :
- {}
- {
- "case" Expression() ":"
- |
- "default" ":" { jjtThis.isDefault = true; }
- }
- void IfStatement() #IfStatement :
- /*
- * The disambiguating algorithm of JavaCC automatically binds dangling
- * else's to the innermost if statement. The LOOKAHEAD specification
- * is to tell JavaCC that we know what we are doing.
- */
- {}
- {
- "if" "(" Expression() ")" Statement() [ LOOKAHEAD(1) "else" Statement() ]
- }
- void WhileStatement() #WhileStatement :
- {}
- {
- "while" "(" Expression() ")" Statement()
- }
- /*
- Do statement is just a While statement with a special hook to execute
- at least once.
- */
- void DoStatement() #WhileStatement :
- {}
- {
- "do" Statement() "while" "(" Expression() ")" ";"
- { jjtThis.isDoStatement=true; }
- }
- void ForStatement() #ForStatement :
- {}
- {
- "for" "(" [ ForInit() { jjtThis.hasForInit=true; } ]
- ";" [ Expression() { jjtThis.hasExpression=true; } ]
- ";" [ ForUpdate() { jjtThis.hasForUpdate=true; } ] ")"
- Statement()
- }
- void ForInit() :
- { Token t = null; }
- {
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD( [ t="final" ] Type() <IDENTIFIER> )
- TypedVariableDeclaration()
- |
- StatementExpressionList()
- }
- /**
- Declared a typed variable.
- Untyped variables are not declared per-se but are handled by the part
- of the grammar that deals with assignments.
- */
- void TypedVariableDeclaration() #TypedVariableDeclaration :
- {
- Token t = null;
- }
- {
- [ t="final" ] Type()
- VariableDeclarator() ( "," VariableDeclarator() )*
- {
- jjtThis.isFinal = (t!=null);
- }
- }
- void StatementExpressionList() #StatementExpressionList :
- {}
- {
- StatementExpression() ( "," StatementExpression() )*
- }
- void ForUpdate() :
- {}
- {
- StatementExpressionList()
- }
- void BreakStatement() #ReturnStatement :
- {}
- {
- "break" [ <IDENTIFIER> ] ";" { jjtThis.kind = BREAK; }
- }
- void ContinueStatement() #ReturnStatement :
- {}
- {
- "continue" [ <IDENTIFIER> ] ";" { jjtThis.kind = CONTINUE; }
- }
- void ReturnStatement() #ReturnStatement :
- {}
- {
- "return" [ Expression() ] ";" { jjtThis.kind = RETURN; }
- }
- void ThrowStatement() #ThrowStatement :
- {}
- {
- "throw" Expression() ";"
- }
- void TryStatement() #TryStatement:
- /*
- * Semantic check required here to make sure that at least one
- * finally/catch is present.
- */
- {}
- {
- "try" Block()
- ( "catch" "(" FormalParameter() ")" Block() )*
- [ "finally" Block() ]
- }