/jEdit/trunk/org/gjt/sp/jedit/bsh/bsh.jjt
# · Unknown · 1380 lines · 1265 code · 115 blank · 0 comment · 0 complexity · 7ed2ad8865bc061031a5554945411af9 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;
- */
- // Not sure exactly what this does
- ERROR_REPORTING=false;
- // This breaks something for interactive use on the command line,
- // but may be useful in non-interactive use.
- //CACHE_TOKENS=true;
- }
- PARSER_BEGIN(Parser)
- package org.gjt.sp.jedit.bsh;
- import java.io.*;
- import java.util.Vector;
- /**
- This is the BeanShell parser. It is used internally by the Interpreter
- class (which is probably what you are looking for). The parser knows
- only how to parse the structure of the language, it does not understand
- names, commands, etc.
- <p>
- You can use the Parser from the command line to do basic structural
- validation of BeanShell files without actually executing them. e.g.
- <code><pre>
- java bsh.Parser [ -p ] file [ file ] [ ... ]
- </pre></code>
- <p>
- The -p option causes the abstract syntax to be printed.
- <p>
- From code you'd use the Parser like this:
- <p
- <code><pre>
- Parser parser = new Parser(in);
- while( !(eof=parser.Line()) ) {
- SimpleNode node = parser.popNode();
- // use the node, etc. (See bsh.BSH* classes)
- }
- </pre></code>
- */
- public class Parser
- {
- boolean retainComments = false;
-
- public void setRetainComments( boolean b ) {
- retainComments = b;
- }
- 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);
- }
- public SimpleNode popNode()
- {
- if ( jjtree.nodeArity() > 0) // number of child nodes
- return (SimpleNode)jjtree.popNode();
- else
- return null;
- }
- /**
- 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() );
- }
- public static void main( String [] args )
- throws IOException, ParseException
- {
- boolean print = false;
- int i=0;
- if ( args[0].equals("-p") ) {
- i++;
- print=true;
- }
- for(; i< args.length; i++) {
- Reader in = new FileReader(args[i]);
- Parser parser = new Parser(in);
- parser.setRetainComments(true);
- while( !parser.Line()/*eof*/ )
- if ( print )
- System.out.println( parser.popNode() );
- }
- }
- /**
- Lookahead for the enhanced for statement.
- Expect "for" "(" and then see whether we hit ":" or a ";" first.
- */
- boolean isRegularForStatement()
- {
- int curTok = 1;
- Token tok;
- tok = getToken(curTok++);
- if ( tok.kind != FOR ) return false;
- tok = getToken(curTok++);
- if ( tok.kind != LPAREN ) return false;
- while (true)
- {
- tok = getToken(curTok++);
- switch (tok.kind) {
- case COLON:
- return false;
- case SEMICOLON:
- return true;
- case EOF:
- return false;
- }
- }
- }
- /**
- Generate a ParseException with the specified message, pointing to the
- current token.
- The auto-generated Parser.generateParseException() method does not
- provide line number info, therefore we do this.
- */
- ParseException createParseException( String message )
- {
- Token errortok = token;
- int line = errortok.beginLine, column = errortok.beginColumn;
- String mess = (errortok.kind == 0) ? tokenImage[0] : errortok.image;
- return new ParseException( "Parse error at line " + line
- + ", column " + column + " : " + message );
- }
- }
- PARSER_END(Parser)
- SKIP : /* WHITE SPACE */
- {
- " " | "\t" | "\r" | "\f"
- | "\n"
- | < NONPRINTABLE: (["\u0000"-"\u0020", "\u0080"-"\u00ff"])+ >
- }
- SPECIAL_TOKEN : /* COMMENTS */
- {
- /*
- SINGLE_LINE_COMMENT includes a hack to accept SLC at the end of a file
- with no terminanting linefeed. This is actually illegal according to
- spec, but comes up often enough to warrant it... (especially in eval()).
- */
- <SINGLE_LINE_COMMENT: "//" (~["\n","\r"])* ("\n"|"\r"|"\r\n")? >
- | <HASH_BANG_COMMENT: "#!" (~["\n","\r"])* ("\n"|"\r"|"\r\n")>
- /* Moved FORMAL_COMMENT to a real token. Modified MULTI_LINE_COMMENT to not
- catch formal comments (require no star after star) */
- | <MULTI_LINE_COMMENT:
- "/*" (~["*"])+ "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/">
- }
- TOKEN : /* RESERVED WORDS AND LITERALS */
- {
- < ABSTRACT : "abstract" >
- | < 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" >
- | < ENUM: "enum" >
- | < EXTENDS: "extends" >
- | < FALSE: "false" >
- | < FINAL: "final" >
- | < FINALLY: "finally" >
- | < FLOAT: "float" >
- | < FOR: "for" >
- | < GOTO: "goto" >
- | < IF: "if" >
- | < IMPLEMENTS: "implements" >
- | < IMPORT: "import" >
- | < INSTANCEOF: "instanceof" >
- | < INT: "int" >
- | < INTERFACE: "interface" >
- | < LONG: "long" >
- | < NATIVE: "native" >
- | < NEW: "new" >
- | < NULL: "null" >
- | < PACKAGE: "package" >
- | < PRIVATE: "private" >
- | < PROTECTED: "protected" >
- | < PUBLIC: "public" >
- | < RETURN: "return" >
- | < SHORT: "short" >
- | < STATIC: "static" >
- | < STRICTFP : "strictfp" >
- | < SWITCH: "switch" >
- | < SYNCHRONIZED: "synchronized" >
- | < TRANSIENT: "transient" >
- | < THROW: "throw" >
- | < THROWS: "throws" >
- | < TRUE: "true" >
- | < TRY: "try" >
- | < VOID: "void" >
- | < VOLATILE: "volatile" >
- | < 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"]
- )
- )
- )*
- "\""
- >
- |
- < FORMAL_COMMENT:
- "/**" (~["*"])* "*" ("*" | (~["*","/"] (~["*"])* "*"))* "/"
- >
- }
- 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" >
- }
- /*
- Thanks to Sreenivasa Viswanadha for suggesting how to get rid of expensive
- lookahead here.
- */
- boolean Line() :
- {}
- {
- <EOF> {
- Interpreter.debug("End of File!");
- return true;
- }
- |
- BlockStatement() {
- return false;
- }
- }
- /*****************************************
- * THE JAVA LANGUAGE GRAMMAR STARTS HERE *
- *****************************************/
- /*
- Gather modifiers for a class, method, or field.
- I lookahead is true then we are being called as part of a lookahead and we
- should not enforce any rules. Otherwise we validate based on context
- (field, method, class)
- */
- Modifiers Modifiers( int context, boolean lookahead ) :
- {
- Modifiers mods = null;
- }
- {
- (
- (
- "private" | "protected" | "public" | "synchronized" | "final"
- | "native" | "transient" | "volatile" | "abstract" | "static"
- | "strictfp"
- ) {
- if ( !lookahead )
- try {
- if ( mods == null ) mods = new Modifiers();
- mods.addModifier( context, getToken(0).image );
- } catch ( IllegalStateException e ) {
- throw createParseException( e.getMessage() );
- }
- }
- )* {
- return mods;
- }
- }
- /**
- */
- void ClassDeclaration() #ClassDeclaration :
- {
- Modifiers mods;
- Token name;
- int numInterfaces;
- }
- {
- mods = Modifiers( Modifiers.CLASS, false )
- ( "class" | "interface" { jjtThis.isInterface=true; } )
- name=<IDENTIFIER>
- [ "extends" AmbiguousName() { jjtThis.extend = true; } ]
- [ "implements" numInterfaces=NameList()
- { jjtThis.numInterfaces=numInterfaces; } ]
- Block()
- {
- jjtThis.modifiers = mods;
- jjtThis.name = name.image;
- }
- }
- void MethodDeclaration() #MethodDeclaration :
- {
- Token t = null;
- Modifiers mods;
- int count;
- }
- {
- mods = Modifiers( Modifiers.METHOD, false ) { jjtThis.modifiers = mods; }
- (
- LOOKAHEAD( <IDENTIFIER> "(" )
- t = <IDENTIFIER> { jjtThis.name = t.image; }
- |
- ReturnType()
- t = <IDENTIFIER> { jjtThis.name = t.image; }
- )
- FormalParameters()
- [ "throws" count=NameList() { jjtThis.numThrows=count; } ]
- ( Block() | ";" )
- }
- void PackageDeclaration () #PackageDeclaration:
- { }
- {
- "package" AmbiguousName()
- }
- void ImportDeclaration() #ImportDeclaration :
- {
- Token s = null;
- Token t = null;
- }
- {
- LOOKAHEAD( 3 )
- [ s = "static" ] "import" AmbiguousName() [ t = "." "*" ] ";"
- {
- if ( s != null ) jjtThis.staticImport = true;
- 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;
- }
- }
- /*
- this originally handled postfix array dimensions...
- void VariableDeclaratorId() #VariableDeclaratorId :
- { Token t; }
- {
- t=<IDENTIFIER> { jjtThis.name = t.image; }
- ( "[" "]" { jjtThis.addUndefinedDimension(); } )*
- }
- */
- 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; }
- |
- 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();
- }
- }
- int NameList() :
- { int count = 0; }
- {
- AmbiguousName() { ++count; } ( "," AmbiguousName() { ++count; } )*
- { return count; }
- }
- /*
- * Expression syntax follows.
- */
- void Expression() :
- { }
- {
- /**
- SYNTACTIC_LOOKAHEAD
- Note: the original grammar was cheating here and we've fixed that,
- but at the expense of another syntactic lookahead.
- */
- LOOKAHEAD( PrimaryExpression() AssignmentOperator() )
- Assignment()
- |
- ConditionalExpression()
- }
- void Assignment() #Assignment :
- { int op ; }
- {
- PrimaryExpression()
- op = AssignmentOperator() { jjtThis.operator = op; }
- // Add this for blocks, e.g. foo = { };
- //( Expression() | Block() )
- 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="++" PrimaryExpression()
- { jjtThis.kind = t.kind; } #UnaryExpression(1)
- }
- void PreDecrementExpression() :
- { Token t = null; }
- {
- t="--" PrimaryExpression()
- { 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( PrimaryExpression() ("++"|"--") )
- PrimaryExpression()
- ( 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() )*
- }
- void MethodInvocation() #MethodInvocation : { }
- {
- AmbiguousName() Arguments()
- }
- void PrimaryPrefix() : { }
- {
- Literal()
- |
- "(" Expression() ")"
- |
- AllocationExpression()
- |
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD( MethodInvocation() )
- MethodInvocation()
- |
- LOOKAHEAD( Type() "." "class" )
- Type()
- |
- AmbiguousName()
- /*
- |
- 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()
- */
- }
- 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 ).longValue() );
- }
- else
- try {
- jjtThis.value = new Primitive(
- Integer.decode( literal ).intValue() );
- } catch ( NumberFormatException e ) {
- throw createParseException(
- "Error or number too big for integer type: "+ 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 ).floatValue() );
- }
- else
- {
- if(ch == 'd' || ch == 'D')
- literal = literal.substring(0,literal.length()-1);
- jjtThis.value = new Primitive( new Double( literal ).doubleValue() );
- }
- }
- |
- x = <CHARACTER_LITERAL> {
- try {
- jjtThis.charSetup( x.image.substring(1, x.image.length() - 1) );
- } catch ( Exception e ) {
- throw createParseException("Error parsing character: "+x.image);
- }
- }
- |
- x = <STRING_LITERAL> {
- try {
- jjtThis.stringSetup( x.image.substring(1, x.image.length() - 1) );
- } catch ( Exception e ) {
- throw createParseException("Error parsing string: "+x.image);
- }
- }
- |
- b = BooleanLiteral() {
- jjtThis.value = new Primitive( 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 :
- {}
- {
- // e.g. int [4][3][][];
- LOOKAHEAD(2)
- ( LOOKAHEAD(2) "[" Expression() "]" { jjtThis.addDefinedDimension(); } )+
- ( LOOKAHEAD(2) "[" "]" { jjtThis.addUndefinedDimension(); } )*
- |
- // e.g. int [][] { {1,2}, {3,4} };
- ( "[" "]" { jjtThis.addUndefinedDimension(); } )+ ArrayInitializer()
- }
- /*
- * Statement syntax follows.
- */
- void Statement() : { }
- {
- LOOKAHEAD(2)
- LabeledStatement()
- |
- Block()
- |
- EmptyStatement()
- |
- StatementExpression() ";"
- |
- SwitchStatement()
- |
- IfStatement()
- |
- WhileStatement()
- |
- DoStatement()
- |
- LOOKAHEAD ( { isRegularForStatement() } )
- ForStatement()
- |
- EnhancedForStatement()
- |
- BreakStatement()
- |
- ContinueStatement()
- |
- ReturnStatement()
- |
- SynchronizedStatement()
- |
- ThrowStatement()
- |
- TryStatement()
- }
- void LabeledStatement() :
- {}
- {
- <IDENTIFIER> ":" Statement()
- }
- void Block() #Block :
- {}
- {
- "{" ( BlockStatement() )* "}"
- }
- void BlockStatement() :
- {
- }
- {
- LOOKAHEAD( Modifiers( Modifiers.FIELD, true ) ( "class" | "interface" ) )
- ClassDeclaration()
- |
- LOOKAHEAD ( Modifiers( Modifiers.METHOD, true )
- ReturnType() <IDENTIFIER> "("
- )
- MethodDeclaration()
- |
- LOOKAHEAD ( Modifiers( Modifiers.METHOD, true )
- <IDENTIFIER> FormalParameters() [ "throws" NameList() ] "{"
- )
- MethodDeclaration()
- |
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD( Modifiers( Modifiers.FIELD, true ) Type() <IDENTIFIER> )
- TypedVariableDeclaration() ";"
- |
- Statement()
- |
- // Allow BeanShell imports in any block
- ImportDeclaration()
- |
- // Allow BeanShell package declarations in any block
- PackageDeclaration()
- |
- FormalComment()
- }
- void FormalComment() #FormalComment( retainComments ) :
- {
- Token t;
- }
- {
- t=<FORMAL_COMMENT> {
- jjtThis.text=t.image;
- }
- }
- void EmptyStatement() :
- {}
- {
- ";"
- }
- void StatementExpression() :
- { }
- {
- /*
- This is looser than normal Java to simplify the grammar. This allows
- us to type arbitrary expressions on the command line, e.g. "1+1;"
- We should turn this off in the implementation in strict java mode.
- */
- Expression()
- /*
- // This was the original Java grammar.
- // Original comment:
- // 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 :
- { Token t = null; }
- {
- "for" "(" [ ForInit() { jjtThis.hasForInit=true; } ]
- ";" [ Expression() { jjtThis.hasExpression=true; } ]
- ";" [ ForUpdate() { jjtThis.hasForUpdate=true; } ] ")"
- Statement()
- }
- /*
- The new JDK1.5 enhanced for statement.
- e.g. for( int a : arrayOfInts ) { }
- We also support loose typing of the iterator var for BeanShell
- e.g. for( a : arrayOfInts ) { }
- */
- void EnhancedForStatement() #EnhancedForStatement :
- { Token t = null; }
- {
- LOOKAHEAD( 4 ) // look ahead for the ":" before deciding
- "for" "(" t=<IDENTIFIER> ":" Expression() ")"
- Statement() { jjtThis.varName = t.image; }
- |
- "for" "(" Type() t=<IDENTIFIER> ":" Expression() ")"
- Statement() { jjtThis.varName = t.image; }
- }
- void ForInit() :
- { Token t = null; }
- {
- // SYNTACTIC_LOOKAHEAD
- LOOKAHEAD( Modifiers( Modifiers.FIELD, true ) 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;
- Modifiers mods;
- }
- {
- mods = Modifiers( Modifiers.FIELD, false )
- Type() VariableDeclarator() ( "," VariableDeclarator() )*
- {
- jjtThis.modifiers = mods;
- }
- }
- 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 SynchronizedStatement() #Block :
- {
- }
- {
- "synchronized" "(" Expression() ")" Block() {
- jjtThis.isSynchronized=true;
- }
- }
- void ThrowStatement() #ThrowStatement :
- {}
- {
- "throw" Expression() ";"
- }
- void TryStatement() #TryStatement:
- /*
- Semantic check required here to make sure that at least one
- finally/catch is present. (You can have a try with finally and no catch).
- */
- { boolean closed = false; }
- {
- "try" Block()
- ( "catch" "(" FormalParameter() ")" Block() { closed = true; } )*
- [ "finally" Block() { closed = true; } ]
- {
- if ( !closed ) throw generateParseException();
- }
- }