/plugins/JavaSideKick/trunk/src/sidekick/java/parser/Tiger.jj
# · Unknown · 2649 lines · 2441 code · 208 blank · 0 comment · 0 complexity · 104dece9ebe7fbe45d652ab08aab8575 MD5 · raw file
Large files are truncated click here to view the full file
- /*
- Per Sreenivasa Viswanadha (as posted on the javacc user mailing list), the
- original java 1.5 grammar is licensed under the BSD license, so this modified
- grammar is also.
- Copyright (c) 2005, Dale Anson
- All rights reserved.
- Redistribution and use in source and binary forms, with or without modification,
- are permitted provided that the following conditions are met:
- * Redistributions of source code must retain the above copyright notice,
- this list of conditions and the following disclaimer.
- * Redistributions in binary form must reproduce the above copyright notice,
- this list of conditions and the following disclaimer in the documentation
- and/or other materials provided with the distribution.
- * Neither the name of the <ORGANIZATION> nor the names of its contributors
- may be used to endorse or promote products derived from this software without
- specific prior written permission.
- THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
- ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
- ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
- options {
- JAVA_UNICODE_ESCAPE = true;
- //ERROR_REPORTING = true;
- STATIC = false;
- //DEBUG_PARSER = true;
- }
- PARSER_BEGIN(TigerParser)
- package sidekick.java.parser;
- import sidekick.util.*;
- import sidekick.java.node.*;
- import sidekick.java.util.Log;
- import java.io.*;
- import java.util.*;
- /**
- * Based on grammar to parse Java version 1.5 written by Sreenivasa Viswanadha,
- * parses a java file for the JavaSideKick plugin to provide a java code
- * browser that works with java 1.5. I've also updated this file so it will
- * parse javacc files for JavaSideKick too, that makes it a lot easier to edit
- * files such as this.
- * <p>
- * Example usage to parse a java file:<p>
- * <code>
- * TigerParser parser = new TigerParser(filename);<br>
- * CUNode root = parser.getJavaRootNode();<br>
- * </code>
- * or to parse a javacc file:<br>
- * <code>
- * TigerParser parser = new TigerParser(filename);<br>
- * CUNode root = parser.getJavaCCRootNode();<br>
- * </code>
- * Calling either of the above causes the file to be parsed into
- * TigerNodes, of which, CUNode is the top-level. The TigerNodes have a parent/
- * child relastionship, which naturally forms a tree structure.
- * <p>
- * To turn this .jj file into a .java file, run <code>javacc Tiger.jj</code>
- * from the directory that contains this file. Javacc will produce a number of
- * .java files, Be careful -- not all files in the directory are produced by
- * javacc, in particular ModifierSet.java and Token.java are required files and
- * are NOT produced by javacc. So the sequence is:<br>
- * .jj -> javacc -> .java -> javac -> .class
- * <p>
- * References like JLS X.X are section numbers in the Java Language Specification
- * Third Edition.
- */
- public class TigerParser
- {
- // accumulates counts of classes, interfaces, methods and fields.
- private Results results = new Results();
- private InputStream inputStream = null;
- /**
- * Constructor for TigerParser. Note that JavaSideKick does not use this
- * constructor -- since the options for building the parser have both
- * USER_TOKEN_MANAGER and USER_CHAR_STREAM set to false (these are the
- * default values so are not explicitly set), javacc will create a
- * constructor "public TigerParser(InputStream)". It is that constructor
- * that JavaSideKick uses.
- * @param fileName name of the file to parse
- */
- public TigerParser(String filename)
- {
- this(System.in);
- try {
- inputStream = new FileInputStream(new File(filename));
- ReInit(inputStream);
- }
- catch(Exception e) {
- e.printStackTrace();
- }
- }
- TigerParser(JavaCharStream stream) {
- jj_input_stream = stream;
- token_source = new TigerParserTokenManager(jj_input_stream);
- token = new Token();
- jj_ntk = -1;
- }
- /**
- * @return the accumulated counts of classes, interfaces, methods, and fields.
- */
- public Results getResults() {
- return results;
- }
- public Location getLocation(Token t) {
- if (t == null)
- return new Location(0, 0);
- return new Location(t.beginLine, t.beginColumn);
- }
- public Location getEndLocation(Token t) {
- if (t == null)
- return new Location(0, 0);
- return new Location(t.endLine, t.endColumn + 1);
- }
- public Location getLocation(Modifier m) {
- if (m == null)
- return new Location(0, 0);
- if (m.beginLine == -1)
- m.beginLine = 0;
- return new Location(m.beginLine, m.beginColumn);
- }
-
- /**
- * @param pe ParseException, if null, one will be generated.
- * @param kinds One or more token types (see TigerParserConstants for
- * definitions). Skipping will stop at the first token type found in
- * this list.
- * @return the token that was skipped to. This could be null since there is
- * a limit of checking no more than 100 tokens. If a token of the requested
- * kind is not found within the next 100 tokens, null will be returned.
- */
- public Token error_skipto(ParseException pe, int... kinds) {
- if (pe == null) {
- pe = generateParseException(); // generate the exception object.
- }
- addException(pe);
- return error_skipto(kinds);
- }
-
- private Token error_skipto(int... kinds) {
- Token t = null;
- int i = 0;
- do {
- i++;
- if (i > 100) {
- return t;
- }
- t = getNextToken();
- for (int type : kinds) {
- if (t.kind == type) {
- return t;
- }
- }
- } while (t != null);
- return t;
- }
- private List<ErrorNode> exceptions = new ArrayList<ErrorNode>();
- private void addException(ParseException pe) {
- //pe.printStackTrace();
- ErrorNode en = new ErrorNode(pe);
- exceptions.add(en);
- }
- public List<ErrorNode> getErrors() {
- return exceptions;
- }
- public void adjustModifier(Modifier m, Token t) {
- if (m.beginLine < t.beginLine) {
- m.beginLine = t.beginLine;
- }
- if (m.beginLine == t.beginLine && (t.beginColumn < m.beginColumn || m.beginColumn == -1)) {
- m.beginColumn = t.beginColumn;
- }
- if (m.endLine < t.endLine) {
- m.endLine = t.endLine;
- }
- if (m.endLine == t.endLine && m.endColumn < t.endColumn) {
- m.endColumn = t.endColumn;
- }
- }
- public void setTabSize(int size) {
- jj_input_stream.setTabSize(size);
- }
- public int getTabSize() {
- return jj_input_stream.getTabSize(0);
- }
- /*
- * Returns true if the next token is not in the FOLLOW list of "expansion".
- * It is used to decide when the end of an "expansion" has been reached.
- */
- private boolean notTailOfExpansionUnit() {
- Token t;
- t = getToken(1);
- if (t.kind == BIT_OR || t.kind == COMMA || t.kind == RPAREN || t.kind == RBRACE || t.kind == RBRACKET) return false;
- return true;
- }
- /* returns a list as a comma separated string */
- private String toString(List list) {
- if (list != null) {
- StringBuffer sb = new StringBuffer();
- for (Iterator it = list.iterator(); it.hasNext(); ) {
- Object o = it.next();
- if (o == null) {
- o = "null";
- }
- sb.append(o.toString());
- if (it.hasNext()) {
- sb.append(",");
- }
- }
- return sb.toString();
- }
- return "";
- }
- private String toTigerString(List<TigerNode> list) {
- if (list != null) {
- StringBuffer sb = new StringBuffer();
- for (Iterator it = list.iterator(); it.hasNext(); ) {
- TigerNode tn = (TigerNode)it.next();
- sb.append(tn.getName()).append(", ");
- if (tn.getChildCount() > 0) {
- sb.append(toTigerString(tn.getChildren()));
- }
- }
- return sb.toString();
- }
- return "";
- }
- }
- PARSER_END(TigerParser)
- /********************************************
- * THE JAVA TOKEN SPECIFICATION STARTS HERE *
- ********************************************/
- /* WHITE SPACE */
- SKIP :
- {
- " "
- | "\t"
- | "\n"
- | "\r"
- | "\f"
- }
- /* COMMENTS */
- MORE :
- {
- /* danson, added backup(2) for special handling of single line comments at
- the end of a file, see <IN_SINGLE_LINE_COMMENT> special token below */
- "//" { input_stream.backup(2); } : IN_SINGLE_LINE_COMMENT
- |
- <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
- |
- "/*" : IN_MULTI_LINE_COMMENT
- }
- <IN_SINGLE_LINE_COMMENT>
- SPECIAL_TOKEN :
- {
- /* this is the original, I've replaced with the next line to allow a single
- line comment at the end of a java file without a new line following the
- comment. The java language specification says that single line comments
- must be followed by an end-of-line marker (see section 3.4), so this new rule
- relaxes that requirement slightly by allowing the line terminator to be
- optional. This only makes sense when the comment is the last line of the
- source file, all other single line comments will have a line terminator. This
- request was posted as a bug against JBrowse, I don't see any problem with
- allowing it, especially since Sun's compiler doesn't complain. */
- /* <SINGLE_LINE_COMMENT: "\n" | "\r" | "\r\n" > : DEFAULT */
- < SINGLE_LINE_COMMENT: "//"(~["\n","\r"])* ("\n"|"\r"|"\r\n")? > : DEFAULT
- }
- <IN_FORMAL_COMMENT>
- SPECIAL_TOKEN :
- {
- <FORMAL_COMMENT: "*/" > : DEFAULT
- }
- <IN_MULTI_LINE_COMMENT>
- SPECIAL_TOKEN :
- {
- <MULTI_LINE_COMMENT: "*/" > : DEFAULT
- }
- <IN_SINGLE_LINE_COMMENT,IN_FORMAL_COMMENT,IN_MULTI_LINE_COMMENT>
- MORE :
- {
- < ~[] >
- }
- /* RESERVED WORDS AND LITERALS */
- TOKEN :
- {
- < ABSTRACT: "abstract" >
- | < ASSERT: "assert" >
- | < BOOLEAN: "boolean" >
- | < BREAK: "break" >
- | < BYTE: "byte" >
- | < CASE: "case" >
- | < CATCH: "catch" >
- | < CHAR: "char" >
- | < CLASS: "class" >
- | < 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" >
- | < SUPER: "super" >
- | < SWITCH: "switch" >
- | < SYNCHRONIZED: "synchronized" >
- | < THIS: "this" >
- | < THROW: "throw" >
- | < THROWS: "throws" >
- | < TRANSIENT: "transient" >
- | < TRUE: "true" >
- | < TRY: "try" >
- | < VOID: "void" >
- | < VOLATILE: "volatile" >
- | < WHILE: "while" >
- }
- /* JAVACC RESERVED WORDS: These are the only tokens in JavaCC but not in Java */
- /* danson, using these keywords as tokens causes problems when parsing java
- code, so I'm replacing these keyworks with semantic lookahead as described in
- the javacc faq. */
- /*
- TOKEN :
- {
- < _OPTIONS: "options" >
- | < _LOOKAHEAD: "LOOKAHEAD" >
- | < _IGNORE_CASE: "IGNORE_CASE" >
- | < _PARSER_BEGIN: "PARSER_BEGIN" >
- | < _PARSER_END: "PARSER_END" >
- | < _JAVACODE: "JAVACODE" >
- | < _TOKEN: "TOKEN" >
- | < _SPECIAL_TOKEN: "SPECIAL_TOKEN" >
- | < _MORE: "MORE" >
- | < _SKIP: "SKIP" >
- | < _TOKEN_MGR_DECLS: "TOKEN_MGR_DECLS" >
- | < _EOF: "EOF" >
- }
- */
- /* LITERALS */
- // DONE: Java 7 allows a binary literal.
- // DONE: Java 7 allows underscores in numeric literals to improve readability, e.g.
- // long creditCardNumber = 1234_5678_9012_3456L;
- TOKEN :
- {
- < INTEGER_LITERAL:
- <DECIMAL_LITERAL> (["l","L"])?
- | <HEX_LITERAL> (["l","L"])?
- | <BINARY_LITERAL> (["l","L"])?
- | <OCTAL_LITERAL> (["l","L"])?
- >
- |
- < #DECIMAL_LITERAL: ["1"-"9"] ((["_"])*["0"-"9"])* >
- |
- < #HEX_LITERAL: "0" ["x","X"] (["0"-"9","a"-"f","A"-"F"])((["_"])*["0"-"9","a"-"f","A"-"F"])* >
- |
- < #BINARY_LITERAL: "0" ["b","B"] (["0"-"1"])((["_"])*["0"-"1"])* > // new for Java 7
- |
- < #OCTAL_LITERAL: "0" ((["_"])*(["0"-"7"]))* >
- |
- < FLOATING_POINT_LITERAL:
- (["0"-"9"])((["_"])*(["0"-"9"]))* "." ((["0"-"9"])((["_"])*(["0"-"9"]))*)* (<EXPONENT>)? (["f","F","d","D"])?
- | "." (["0"-"9"])((["_"])*(["0"-"9"]))* (<EXPONENT>)? (["f","F","d","D"])?
- | (["0"-"9"])((["_"])*(["0"-"9"]))* <EXPONENT> (["f","F","d","D"])?
- | (["0"-"9"])((["_"])*(["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"]
- )
- )
- )*
- "\""
- >
- }
- /* IDENTIFIERS */
- TOKEN :
- {
- < 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"
- ]
- >
- }
- /* SEPARATORS */
- TOKEN :
- {
- < LPAREN: "(" >
- | < RPAREN: ")" >
- | < LBRACE: "{" >
- | < RBRACE: "}" >
- | < LBRACKET: "[" >
- | < RBRACKET: "]" >
- | < SEMICOLON: ";" >
- | < COMMA: "," >
- | < DOT: "." >
- | < AT: "@" >
- }
- /* OPERATORS */
- TOKEN :
- {
- < ASSIGN: "=" >
- | < LT: "<" >
- | < BANG: "!" >
- | < TILDE: "~" >
- | < HOOK: "?" >
- | < COLON: ":" >
- | < EQ: "==" >
- | < LE: "<=" >
- | < GE: ">=" >
- | < NE: "!=" >
- | < SC_OR: "||" >
- | < SC_AND: "&&" >
- | < INCR: "++" >
- | < DECR: "--" >
- | < PLUS: "+" >
- | < MINUS: "-" >
- | < STAR: "*" >
- | < SLASH: "/" >
- | < BIT_AND: "&" >
- | < BIT_OR: "|" >
- | < XOR: "^" >
- | < REM: "%" >
- | < LSHIFT: "<<" >
- | < PLUSASSIGN: "+=" >
- | < MINUSASSIGN: "-=" >
- | < STARASSIGN: "*=" >
- | < SLASHASSIGN: "/=" >
- | < ANDASSIGN: "&=" >
- | < ORASSIGN: "|=" >
- | < XORASSIGN: "^=" >
- | < REMASSIGN: "%=" >
- | < LSHIFTASSIGN: "<<=" >
- | < RSIGNEDSHIFTASSIGN: ">>=" >
- | < RUNSIGNEDSHIFTASSIGN: ">>>=" >
- | < ELLIPSIS: "..." >
- }
- /* >'s need special attention due to generics syntax. */
- TOKEN :
- {
- < RUNSIGNEDSHIFT: ">>>" >
- {
- matchedToken.kind = GT;
- ((Token.GTToken)matchedToken).realKind = RUNSIGNEDSHIFT;
- input_stream.backup(2);
- }
- | < RSIGNEDSHIFT: ">>" >
- {
- matchedToken.kind = GT;
- ((Token.GTToken)matchedToken).realKind = RSIGNEDSHIFT;
- input_stream.backup(1);
- }
- | < GT: ">" >
- }
- /************************************************
- * THE JAVACC GRAMMAR SPECIFICATION STARTS HERE *
- ************************************************/
- CUNode getJavaCCRootNode(int tab_size) :
- {
- setTabSize(tab_size);
- CUNode n = new CUNode();
- List<TigerNode> children = null;
- }
- {
- children = javacc_input()
- {
- if (children != null ) {
- for (TigerNode child : children) {
- if (child instanceof CUNode) {
- for (ImportNode in : ((CUNode)child).getImportNodes()) {
- n.addImport(in);
- }
- }
- n.addChild(child);
- }
- }
- return n;
- }
- }
- List<TigerNode> javacc_input() :
- {
- List<TigerNode> children = new ArrayList<TigerNode>();
- TigerNode options_node = null;
- Token parser_node_start_t = null;
- Token parser_node_end_t = null;
- Token cunode_start_t = null;
- Token cunode_end_t = null;
- TigerNode production_node = null;
- CUNode cunode = null;
- CUNode parser_node = new CUNode(){public int getOrdinal(){return TigerNode.PARSER;}};
- }
- {
- options_node=javacc_options()
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("PARSER_BEGIN")} )
- parser_node_start_t=<IDENTIFIER> "(" identifier() cunode_start_t=")"
- cunode=CompilationUnit(getTabSize())
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("PARSER_END")} )
- cunode_end_t=<IDENTIFIER> "(" identifier() parser_node_end_t=")"
- ( production_node=production() { children.add(production_node); } )+
- <EOF>
- {
- if (options_node != null) {
- children.add(options_node);
- }
- if (parser_node_start_t != null && parser_node_end_t != null ) {
- parser_node.setName("PARSER");
- parser_node.setStartLocation(getLocation(parser_node_start_t));
- parser_node.setEndLocation(getEndLocation(parser_node_end_t));
- children.add(parser_node);
- if (cunode != null) {
- cunode.setStartLocation(getLocation(cunode_start_t));
- cunode.setEndLocation(getEndLocation(cunode_end_t));
- if (cunode.getChildren() != null ) {
- for (Iterator it = cunode.getChildren().iterator(); it.hasNext(); ) {
- parser_node.addChild((TigerNode)it.next());
- }
- }
- else {
- parser_node.addChild(cunode);
- }
- for (ImportNode in : cunode.getImportNodes()) {
- parser_node.addImport(in);
- }
- }
- }
- return children;
- }
- }
- TigerNode javacc_options() :
- {
- TigerNode tn = new TigerNode() {public int getOrdinal() { return TigerNode.OPTIONS;}};
- Token start_t = null;
- Token end_t = null;
- }
- {
- // special handling for javacc keyword
- [
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("options")} )
- (start_t=<IDENTIFIER> "{" ( option_binding() )+ end_t="}" )
- ]
- //[ start_t=<_OPTIONS> "{" ( option_binding() )+ end_t="}" ]
- {
- tn.setName("options");
- tn.setStartLocation(getLocation(start_t));
- tn.setEndLocation(getEndLocation(end_t));
- return tn;
- }
- }
- void option_binding() :
- {}
- {
- (
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("LOOKAHEAD")} )
- identifier()
- |
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("IGNORE_CASE")} )
- identifier()
- |
- <IDENTIFIER>
- |
- "static" )
- "="
- ( IntegerLiteral() | BooleanLiteral() | StringLiteral() )
- ";"
- }
- TigerNode production() :
- {
- TigerNode tn = null;
- }
- {
- (
- LOOKAHEAD(1)
- /*
- * Since JAVACODE is both a JavaCC reserved word and a Java identifier,
- * we need to give preference to "javacode_production" over
- * "bnf_production".
- */
- tn=javacode_production()
- |
- LOOKAHEAD(1)
- /*
- * Since SKIP, TOKEN, etc. are both JavaCC reserved words and Java
- * identifiers, we need to give preference to "regular_expression_production"
- * over "bnf_production".
- */
- tn=regular_expr_production()
- |
- LOOKAHEAD(1)
- /*
- * Since TOKEN_MGR_DECLS is both a JavaCC reserved word and a Java identifier,
- * we need to give preference to "token_manager_decls" over
- * "bnf_production".
- */
- tn=token_manager_decls()
- |
- tn=bnf_production()
- )
- {
- return tn;
- }
- }
- TigerNode javacode_production() :
- {
- JavaCodeProductionNode mn = new JavaCodeProductionNode();
- List<TigerNode> params = null;
- Token start_t = null;
- Type resultType = null;
- String identifier = "";
- BlockNode bn = null;
- }
- {
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("JAVACODE")} )
- start_t=<IDENTIFIER>
- resultType=ResultType() identifier=identifier() params=FormalParameters()
- [ LOOKAHEAD(2) "throws" Name() ( "," Name() )* ]
- [ LOOKAHEAD(2) node_descriptor() ]
- bn=Block()
- {
- if (start_t != null){
- mn.setStartLocation(getLocation(start_t));
- }
- if (resultType != null) {
- mn.setReturnType(resultType);
- }
- mn.setName(identifier);
- if (params != null) {
- mn.setFormalParams(params);
- }
- if (bn != null) {
- mn.setEndLocation(bn.getEndLocation());
- mn.addChild(bn);
- }
- return mn;
- }
- }
- TigerNode bnf_production() :
- {
- BNFProductionNode mn = new BNFProductionNode();
- List<TigerNode> params = null;
- Type resultType = null;
- String identifier = "";
- Token end_t = null;
- BlockNode java_block = null;
- }
- {
- resultType=ResultType() identifier=identifier() params=FormalParameters()
- [ "throws" Name() ( "," Name() )* ]
- [ node_descriptor() ]
- ":"
- java_block = Block()
- "{" expansion_choices() end_t="}"
- {
- if (resultType != null) {
- mn.setStartLocation(resultType.getStartLocation());
- mn.setReturnType(resultType);
- }
- mn.setName(identifier);
- if (params != null) {
- mn.setFormalParams(params);
- }
- if (end_t != null ) {
- mn.setEndLocation(getEndLocation(end_t));
- }
- if (java_block != null) {
- mn.addChild(java_block);
- }
- return mn;
- }
- }
- TigerNode regular_expr_production() :
- {
- Token start_t = null;
- Token end_t = null;
- Token t = null;
- TigerNode tn = new RegexProductionNode();
- Token kind = null;
- StringBuffer lexical_state_list = new StringBuffer();
- }
- {
- [
- LOOKAHEAD(2) start_t="<" "*" ">" {lexical_state_list.append("<*>"); }
- |
- start_t="<" t=<IDENTIFIER> {lexical_state_list.append("<").append(t.image);} ( "," t=<IDENTIFIER> {lexical_state_list.append(",").append(t.image);} )* ">" {lexical_state_list.append(">");}
- ]
- kind=regexpr_kind() [ "["
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("IGNORE_CASE")} )
- <IDENTIFIER>
- "]"
- ] ":"
- "{" regexpr_spec() ( "|" regexpr_spec() )* end_t="}"
- {
- if (lexical_state_list.length() > 0) {
- tn.setName(lexical_state_list.toString());
- }
- else if (kind != null) {
- tn.setName(kind.image);
- }
- tn.setStartLocation(getLocation(start_t == null ? kind : start_t));
- tn.setEndLocation(getEndLocation(end_t));
- return tn;
- }
- }
- TigerNode token_manager_decls() :
- {
- Token start_t = null;
- BlockNode bn = null;
- }
- {
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("TOKEN_MGR_DECLS")} )
- start_t=<IDENTIFIER> ":" bn=TokenMgrDeclBlock()
- {
- TigerNode tn = new TokenMgrDeclProductionNode();
- tn.setName(start_t.image);
- tn.setStartLocation(getLocation(start_t));
- if (bn != null) {
- tn.setEndLocation(bn.getEndLocation());
- tn.addChildren(bn.getChildren());
- }
- return tn;
- }
- }
- Token regexpr_kind() :
- {
- Token t = null;
- }
- {
- (
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("TOKEN")} )
- t=<IDENTIFIER>
- |
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("SPECIAL_TOKEN")} )
- t=<IDENTIFIER>
- |
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("SKIP")} )
- t=<IDENTIFIER>
- |
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("MORE")} )
- t=<IDENTIFIER>
- )
- {
- return t;
- }
- }
- void regexpr_spec() :
- {}
- {
- regular_expression() [ Block() ] [ ":" <IDENTIFIER> ]
- }
- void expansion_choices() :
- {}
- {
- expansion() ( "|" expansion() )*
- }
- void expansion() :
- {}
- {
- ( LOOKAHEAD(1)
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("LOOKAHEAD")} )
- <IDENTIFIER> "(" local_lookahead() ")"
- )?
- ( LOOKAHEAD(0, { notTailOfExpansionUnit() } )
- expansion_unit()
- [ node_descriptor() ]
- )+
- }
- void local_lookahead() :
- {
- boolean commaAtEnd = false, emptyLA = true;
- }
- {
- [
- /*
- * The lookahead of 1 is to turn off the warning message that lets
- * us know that an expansion choice can also start with an integer
- * literal because a primary expression can do the same. But we
- * know that this is what we want.
- */
- LOOKAHEAD(1)
- IntegerLiteral()
- {
- emptyLA = false;
- }
- ]
- [ LOOKAHEAD(0, { !emptyLA && (getToken(1).kind != RPAREN) } )
- ","
- {
- commaAtEnd = true;
- }
- ]
- [ LOOKAHEAD(0, { getToken(1).kind != RPAREN && getToken(1).kind != LBRACE } )
- expansion_choices()
- {
- emptyLA = false; commaAtEnd = false;
- }
- ]
- [ LOOKAHEAD(0, { !emptyLA && !commaAtEnd && (getToken(1).kind != RPAREN) } )
- ","
- {
- commaAtEnd = true;
- }
- ]
- [ LOOKAHEAD(0, { emptyLA || commaAtEnd } )
- "{" Expression() "}"
- ]
- }
- void expansion_unit() :
- {}
- {
- LOOKAHEAD(1)
- /*
- * We give this priority over primary expressions which use LOOKAHEAD as the
- * name of its identifier.
- */
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("LOOKAHEAD")} )
- <IDENTIFIER> "(" local_lookahead() ")"
- |
- Block()
- |
- "[" expansion_choices() "]"
- |
- "try" "{" expansion_choices() "}"
- ( "catch" "(" Name() <IDENTIFIER> ")" Block() )*
- [ "finally" Block() ]
- |
- LOOKAHEAD( identifier() | StringLiteral() | "<" | PrimaryExpression() "=" )
- [
- LOOKAHEAD(PrimaryExpression() "=")
- PrimaryExpression() "="
- ]
- ( regular_expression() | identifier() Arguments() )
- |
- "(" expansion_choices() ")" ( "+" | "*" | "?" )?
- }
- void regular_expression() :
- {}
- {
- StringLiteral()
- |
- LOOKAHEAD(3)
- "<" [ [ "#" ] identifier() ":" ] complex_regular_expression_choices() ">"
- |
- LOOKAHEAD(2)
- "<" identifier() ">"
- |
- "<"
- // special handling for javacc keyword
- LOOKAHEAD( {getToken(1).kind == IDENTIFIER && getToken(1).image.equals("EOF")} )
- <IDENTIFIER>
- ">"
- }
- void complex_regular_expression_choices() :
- {}
- {
- complex_regular_expression() ( "|" complex_regular_expression() )*
- }
- void complex_regular_expression() :
- {}
- {
- ( complex_regular_expression_unit() )+
- }
- void complex_regular_expression_unit() :
- {}
- {
- StringLiteral()
- |
- "<" identifier() ">"
- |
- character_list()
- |
- "(" complex_regular_expression_choices() ")" ( "+" | "*" | "?" )?
- }
- void character_list() :
- {}
- {
- [ "~" ] "[" [ character_descriptor() ( "," character_descriptor() )* ] "]"
- }
- void character_descriptor() :
- {}
- {
- StringLiteral() [ "-" StringLiteral() ]
- }
- String identifier() :
- {
- Token t = null;
- }
- {
- t=<IDENTIFIER>
- {
- return t.image;
- }
- }
- /**********************************************
- * THE JJTREE PRODUCTIONS START HERE *
- **********************************************/
- void node_descriptor() :
- {}
- {
- "#" ( <IDENTIFIER> | <VOID> )
- [
- LOOKAHEAD(1)
- "(" [ ">" ] node_descriptor_expression() ")"
- ]
- }
- JAVACODE
- void node_descriptor_expression()
- {
- Token tok;
- int nesting = 1;
- while (true) {
- tok = getToken(1);
- if (tok.kind == 0) {
- throw new ParseException();
- }
- if (tok.kind == LPAREN) nesting++;
- if (tok.kind == RPAREN) {
- nesting--;
- if (nesting == 0) break;
- }
- tok = getNextToken();
- }
- }
- /* javacc productions */
- void IntegerLiteral() :
- {}
- {
- <INTEGER_LITERAL>
- }
- void StringLiteral() :
- {}
- {
- <STRING_LITERAL>
- }
- /*****************************************
- * THE JAVA LANGUAGE GRAMMAR STARTS HERE *
- *****************************************/
- /*
- * Program structuring syntax follows.
- */
- CUNode getJavaRootNode(int tab_size) :
- {
- CUNode n = null;
- }
- {
- n = JavaCompilationUnit(tab_size)
- {
- return n;
- }
- }
- /**
- * Main entry point for parsing the PARSER section in javacc files. Use
- * JavaCompilationUnit as main entry point for parsing java files.
- * @return a CUNode, which is parent or root node of all other nodes.
- */
- CUNode CompilationUnit(int tab_size):
- {
- setTabSize(tab_size);
- CUNode n = new CUNode();
- TigerNode a;
- String packageName = "";
- ImportNode in = null;
- }
- {
- try {
- (
- [ packageName=PackageDeclaration() ]
- ( in=ImportDeclaration() { n.addImport(in); } )*
- // TypeDeclaration, this will be one or more classes or
- // interfaces, add these as child nodes of the root node
- (
- a=TypeDeclaration()
- { n.addChild(a); }
- )*
- )
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, RBRACE, PUBLIC, PRIVATE, PROTECTED, CLASS, INTERFACE, ENUM);
- }
- {
- n.setPackageName(packageName);
- return n;
- }
- }
- /**
- * Main entry point for parsing java files.
- * @return a CUNode, which is parent or root node of all other nodes.
- */
- CUNode JavaCompilationUnit(int tab_size):
- {
- CUNode n = null;
- Token end_t = null;
- }
- {
- try {
- (
- n = CompilationUnit(tab_size)
- // read the whole file
- end_t=<EOF>
- )
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, RBRACE);
- }
- {
- if (end_t != null) {
- n.setEndLocation(getEndLocation(end_t));
- }
- return n;
- }
- }
- String PackageDeclaration():
- {
- NameNode name = null;
- }
- {
- try {
- "package" name=Name() ";" ////
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, IMPORT, CLASS, INTERFACE, ENUM, PUBLIC, PRIVATE, PROTECTED);
- }
- {
- if (name == null) {
- return "";
- }
- return name.getFullyQualifiedTypeName();
- }
- }
- /**
- * @return just the package name, without the 'import' or 'static' or '.*', e.g.
- * "import java.util.*;" will return "java.util". A fully qualified import will
- * return the full classname, e.g. "import java.util.List;" will return
- * "java.util.List", this is also the case with static imports, e.g.
- * "import static java.lang.Math.PI;" will return "java.lang.Math.PI".
- */
- ImportNode ImportDeclaration():
- {
- NameNode name = null;
- Token st = null;
- Token et = null;
- }
- {
- try {
- st="import" [ "static" ] name=Name() [ "." "*" ] et=";" ////
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, IMPORT, CLASS, INTERFACE, ENUM, PUBLIC, PRIVATE, PROTECTED);
- }
- {
- if (name == null) {
- return null;
- }
- ImportNode in = new ImportNode(name.getFullyQualifiedTypeName());
- in.setStartLocation(getLocation(st));
- in.setEndLocation(getEndLocation(et));
- return in;
- }
- }
- /*
- * Modifiers. We match all modifiers in a single rule to reduce the chances of
- * syntax errors for simple modifier mistakes. It will also enable us to give
- * better error messages.
- */
- Modifier Modifiers():
- {
- int modifiers = 0;
- Token t = null;
- Modifier m = new Modifier();
- }
- {
- (
- LOOKAHEAD(2)
- (
- t="public" { modifiers |= ModifierSet.PUBLIC; adjustModifier(m, t);}
- |
- t="static" { modifiers |= ModifierSet.STATIC; adjustModifier(m, t);}
- |
- t="protected" { modifiers |= ModifierSet.PROTECTED; adjustModifier(m, t);}
- |
- t="private" { modifiers |= ModifierSet.PRIVATE; adjustModifier(m, t);}
- |
- t="final" { modifiers |= ModifierSet.FINAL; adjustModifier(m, t);}
- |
- t="abstract" { modifiers |= ModifierSet.ABSTRACT; adjustModifier(m, t);}
- |
- t="synchronized" { modifiers |= ModifierSet.SYNCHRONIZED; adjustModifier(m, t);}
- |
- t="native" { modifiers |= ModifierSet.NATIVE; adjustModifier(m, t);}
- |
- t="transient" { modifiers |= ModifierSet.TRANSIENT; adjustModifier(m, t);}
- |
- t="volatile" { modifiers |= ModifierSet.VOLATILE; adjustModifier(m, t);}
- |
- t="strictfp" { modifiers |= ModifierSet.STRICTFP; adjustModifier(m, t);}
- |
- // TODO: Annotation doesn't work as a modifier, at least, not the way the
- // Modifer and ModifierSet classes are set up. Need to figure out how to
- // represent Annotation as a modifier.
- Annotation()
- )
- )*
- {
- m.modifiers = modifiers;
- return m;
- }
- }
- /*
- * Declaration syntax follows.
- */
- // Handle classes, interfaces, enums, and annotations.
- TigerNode TypeDeclaration():
- {
- Modifier modifier;
- TigerNode tn = null;
- }
- {
- try {
- ";" /// is this the semi-colon that I need to handle at the end of a class??
- |
- modifier = Modifiers()
- (
- tn=ClassOrInterfaceDeclaration(modifier)
- |
- tn=EnumDeclaration(modifier)
- |
- tn=AnnotationTypeDeclaration(modifier) { tn = null; }
- )
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, RBRACE, PUBLIC, PRIVATE, PROTECTED); // TODO: rethrow?
- }
- {
- return tn;
- }
- }
- /**
- * @return a ClassNode or an InterfaceNode
- */
- TigerNode ClassOrInterfaceDeclaration(Modifier m):
- {
- boolean isInterface = false;
- Token t = null;
- TigerNode kids = null; // only need the children of this node
- String type_params = "";
- List<TigerNode> extends_list = null;
- List<TigerNode> implements_list = null;
- Token type = null;
- }
- {
- try {
- ( type="class" | type="interface" { isInterface = true; } )
- t=<IDENTIFIER>
- [ type_params = TypeParameters() ]
- [ extends_list=ExtendsList(isInterface) ]
- [ implements_list=ImplementsList(isInterface) ]
- kids=ClassOrInterfaceBody(isInterface)
- /* danson, added this check for trailing semi-colon. Apparently, this has been
- legal since the beginning of Java, some sort of a C hold-over. Sun's latest
- Java 1.5 compiler doesn't mind it, but this parser whined if the class has a
- semi-colon after the last }. The original Java1.5.jj file that this parser
- is based on does NOT whine, so I've done something to change the base behaviour.
- See below, I probably broke this in ClassOrInterfaceBody. */
- [ LOOKAHEAD(2) <SEMICOLON> ]
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, CLASS, INTERFACE, ENUM, PUBLIC, PRIVATE, PROTECTED);
- }
- {
- ClassNode node = isInterface ? new InterfaceNode(t.image, m.modifiers) : new ClassNode(t.image, m.modifiers);
- if (isInterface) {
- results.incInterfaceCount();
- }
- else {
- results.incClassCount();
- }
- if (m.beginColumn > -1) {
- node.setStartLocation(getLocation(m) );
- }
- else {
- node.setStartLocation(getLocation(type));
- }
- if (kids != null)
- node.setEndLocation(kids.getEndLocation());
- // add the child nodes, don't need the 'kids' node itself, it's just a holder
- // for the nodes I want (although I do want the end location).
- if (kids != null && kids.getChildren() != null)
- node.addChildren(kids.getChildren());
- node.setTypeParams(type_params);
- node.setExtendsList(extends_list);
- node.setImplementsList(implements_list);
- return node;
- }
- }
- /**
- * @return a list of sidekick.java.node.Types representing items in an 'extends'
- * list, e.g. the "Bar" in "public class Foo extends Bar"
- */
- List<TigerNode> ExtendsList(boolean isInterface):
- {
- boolean extendsMoreThanOne = false;
- List<TigerNode> list = new ArrayList<TigerNode>(); // a list of Types
- Type type_s = null;
- Type type_a = null;
- }
- {
- try {
- "extends" type_s=ClassOrInterfaceType() { list.add(type_s); }
- ( "," type_a=ClassOrInterfaceType() { extendsMoreThanOne = true; list.add(type_a); } )*
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, RBRACE);
- }
- {
- if (extendsMoreThanOne && !isInterface)
- throw new ParseException("A class cannot extend more than one other class");
- return list;
- }
- }
- /**
- * @return a list of sidekick.java.node.Types representing items in an 'implements'
- * list, e.g. the "Bar" and "Serializable" in "public class Foo implements Bar, Serializable"
- */
- List<TigerNode> ImplementsList(boolean isInterface):
- {
- List<TigerNode> list = new ArrayList<TigerNode>();
- Type type_s = null;
- Type type_a = null;
- }
- {
- try {
- "implements" type_s=ClassOrInterfaceType() { list.add(type_s); }
- ( "," type_a=ClassOrInterfaceType() { list.add(type_a); } )*
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, RBRACE);
- }
- {
- if (isInterface)
- throw new ParseException("An interface cannot implement other interfaces");
- return list;
- }
- }
- /**
- * @return an EnumNode
- */
- TigerNode EnumDeclaration(Modifier m):
- {
- Token t = null;
- Token start_t = null;
- TigerNode body = null;
- }
- {
- try {
- start_t="enum" t=<IDENTIFIER>
- [ ImplementsList(false) ]
- body=EnumBody()
- }
- catch(ParseException pe) {
- if (t == null) {
- // handle the case where old code used 'enum' as a variable name
- ParseException e = new ParseException("Parse error at line " + start_t.beginLine + ", column " + start_t.beginColumn + ". Encountered: 'enum' as an identifier, 'enum' is a keyword.");
- addException(e);
- return null;
- }
- else
- error_skipto(pe, SEMICOLON, RBRACE);
- }
- {
- if (t == null) {
- // handle the case where old code used 'enum' as a variable name
- ParseException e = new ParseException("Parse error at line " + start_t.beginLine + ", column " + start_t.beginColumn + ". Encountered: 'enum' as an identifier, 'enum' is a keyword.");
- addException(e);
- return null;
- }
- EnumNode node = new EnumNode(t.image, m.modifiers);
- if (start_t != null) {
- if (m.beginColumn == -1)
- node.setStartLocation(getLocation(start_t));
- else
- node.setStartLocation(getLocation(m));
- }
- node.setEndLocation(body.getEndLocation());
- node.addChildren(body.getChildren());
- return node;
- }
- }
- // returns the end location of the enum body
- TigerNode EnumBody():
- {
- Token start_t = null;
- Token end_t = null;
- List<TigerNode> constants = new ArrayList<TigerNode>();
- TigerNode constant;
- }
- {
- try {
- start_t="{"
- constant = EnumConstant(){constants.add(constant);} ( "," constant=EnumConstant(){if (constant != null) constants.add(constant);} )*
- [ ";" ( ClassOrInterfaceBodyDeclaration(false) )* ]
- end_t="}"
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, RBRACE);
- end_t = start_t;
- }
- {
- TigerNode node = new TigerNode();
- node.setStartLocation(getLocation(start_t));
- node.setEndLocation(getEndLocation(end_t));
- node.addChildren(constants);
- return node;
- }
- }
- /**
- * @return an enum constant value
- */
- TigerNode EnumConstant():
- {
- Token t = null;
- TigerNode node = null;
- }
- {
- try {
- t=<IDENTIFIER> [ Arguments() ] [ ClassOrInterfaceBody(false) ]
- }
- catch(ParseException pe) {
- // This grammar expects commas to be followed by EnumConstants, but
- // neither javac nor the language spec says it has to, so something like
- // public enum {ACE, BASE, CASE, } is allowed.
- // TODO: rethrow the exception? This is poor coding practice. Or maybe
- // let PMD find it?
- return null;
- }
- {
- if (t != null) {
- node = new TigerNode();
- node.setName(t.image);
- node.setStartLocation(getLocation(t));
- node.setEndLocation(getEndLocation(t));
- }
- return node;
- }
- }
- /**
- * @return a string representing a generics type, e.g. the "<String>" in
- * "List<String> list = new List();", the string will contain the angle brackets.
- */
- String TypeParameters():
- {
- String s = "<";
- String a = "";
- }
- {
- try {
- (
- "<"
- (
- a=TypeParameter()
- { s += a; }
- )?
- (
- ","
- { s += ","; }
- a=TypeParameter()
- { s += a; }
- )*
- ">"
- )
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, GT);
- }
- {
- return s + ">";
- }
- }
- String TypeParameter():
- {
- String s = "";
- Token t = null;
- }
- {
- try {
- (
- t=<IDENTIFIER> [ s=TypeBound() ]
- )
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON);
- }
- {
- StringBuffer sb = new StringBuffer();
- if (t.image != null)
- sb.append(t.image);
- if (s.length() > 0)
- sb.append(" ").append(s);
- return sb.toString();
- }
- }
- String TypeBound():
- {
- String s = "extends";
- Type type_s = null;
- Type type_a = null;
- }
- {
- try {
- (
- "extends"
- type_a=ClassOrInterfaceType()
- { s += " " + type_a.toString(); }
- (
- "&"
- { s += " & "; }
- type_a=ClassOrInterfaceType()
- { s += type_a.toString(); }
- )*
- )
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON); // TODO: rethrow?
- }
- {
- return s;
- }
- }
- /**
- * @return a node representing the contents of a Class or Interface body. The
- * returned node is simply a holder for the contents, it is the children of this
- * node that are useful as they are the methods and fields of the class or
- * interface.
- */
- TigerNode ClassOrInterfaceBody(boolean isInterface):
- {
- TigerNode parent = new TigerNode("", -1);
- TigerNode child = null;
- Token start_t = null;
- Token end_t = null;
- }
- {
- try {
- (
- start_t="{"
- (
- child=ClassOrInterfaceBodyDeclaration(isInterface)
- { if (child != null) parent.addChild(child); }
- )*
- end_t="}"
- )
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, RBRACE, PUBLIC, PRIVATE, PROTECTED);
- }
- {
- if (start_t != null) {
- parent.setStartLocation(getLocation(start_t));
- }
- if (end_t != null) {
- parent.setEndLocation(getEndLocation(end_t));
- }
- else if (child != null) {
- parent.setEndLocation(child.getEndLocation());
- }
- return parent.getChildren() != null ? parent : null;
- }
- }
- /**
- * @return one of several different nodes, could be a ClassNode, EnumNode,
- * ConstructorNode, FieldNode, MethodNode, or an InterfaceNode.
- */
- TigerNode ClassOrInterfaceBodyDeclaration(boolean isInterface):
- {
- // see note above (~ line 510), I think my changes here have broken the test for a
- // trailing ; after a class body.
- boolean isNestedInterface = false;
- Modifier m;
- TigerNode a = null;
- TigerNode initializer = null;
- String type_params = null;
- }
- {
- try {
- (
- LOOKAHEAD(2)
- initializer=Initializer()
- {
- if (isInterface)
- throw new ParseException("An interface cannot have initializers");
- if (initializer != null)
- return initializer;
- }
- |
- m = Modifiers() // Just get all the modifiers out of the way. If you want to do
- // more checks, pass the modifiers down to the member
- (
- a=ClassOrInterfaceDeclaration(m)
- |
- a=EnumDeclaration(m)
- |
- LOOKAHEAD( [ TypeParameters() ] <IDENTIFIER> "(" )
- a=ConstructorDeclaration(m)
- |
- LOOKAHEAD( Type() <IDENTIFIER> ( "[" "]" )* ( "," | "=" | ";" ) )
- a=FieldDeclaration(m)
- |
- a=MethodDeclaration(m)
- |
- a=AnnotationTypeDeclaration(m)
- )
- |
- ";" /// is this the trailing semi-colon??
- )
- }
- catch(ParseException pe) {
- //error_skipto(pe, SEMICOLON, PUBLIC, PRIVATE, PROTECTED); // TODO: rethrow?
- throw pe;
- }
- {
- return a;
- }
- }
- /**
- * @return a FieldNode
- */
- FieldNode FieldDeclaration(Modifier m):
- {
- Type type = null;
- FieldNode fn = null;
- VariableDeclarator name = null;
- VariableDeclarator a;
- Token et = null;
- }
- {
- try {
- (
- // Modifiers are already matched in the caller
- /// might need to change this, I'm collecting multiple declarations into a single
- /// field, which seems to be okay, e.g. I'm putting "int x = 0, y = 6" into a
- /// field with Type "int" and name "x, y". It might be better to create individual
- /// nodes for each, so for this example, this method could return 2 fields, one
- /// for "int x" and one for "int y".
- type=Type() name=VariableDeclarator()
- {
- fn = new FieldNode(name.getName(), m.modifiers, type);
- fn.addChild(name);
- if (fn.isPrimitive())
- results.incPrimitiveFieldCount();
- else
- results.incReferenceFieldCount();
- }
- (
- "," a=VariableDeclarator()
- {
- fn.setName(fn.getName() + ", " + a.getName());
- fn.addChild(a);
- }
- )*
- et=";"
- )
- }
- catch(ParseException pe) {
- //error_skipto(pe, SEMICOLON);
- throw pe;
- }
- {
- if (m.beginColumn == -1)
- fn.setStartLocation(type.getStartLocation());
- else
- fn.setStartLocation(getLocation(m)); //type.getStartLocation());
- fn.setEndLocation(getEndLocation(et));
- return fn;
- }
- }
- /*
- Represents a variable declaration. The returned node represents the LHS,
- the children of the node represent the RHS.
- */
- VariableDeclarator VariableDeclarator():
- {
- VariableDeclarator s = null;
- List<TigerNode> list = null;
- }
- {
- try {
- (
- s=VariableDeclaratorId() [ "=" list=VariableInitializer() ]
- )
- }
- catch(ParseException pe) {
- //error_skipto(pe, SEMICOLON);
- throw pe;
- }
- {
- if (list != null) {
- s.addChildren(list);
- }
- return s;
- }
- }
- VariableDeclarator VariableDeclaratorId():
- {
- Token t = null;
- }
- {
- try {
- t=<IDENTIFIER> ( "[" "]" )*
- }
- catch(ParseException pe) {
- //error_skipto(pe, SEMICOLON);
- throw pe;
- }
- {
- if ( t == null)
- return null;
- VariableDeclarator tn = new VariableDeclarator(t.image);
- tn.setStartLocation(new Location(t.beginLine, t.beginColumn));
- tn.setEndLocation(new Location(t.beginLine, t.beginColumn + t.image.length()));
- return tn;
- }
- }
- List<TigerNode> VariableInitializer():
- {
- List<TigerNode> list = new ArrayList<TigerNode>();
- List<TigerNode> a = null;
- }
- {
- try {
- a=ArrayInitializer()
- |
- a=Expression()
- }
- catch(ParseException pe) {
- //error_skipto(pe, SEMICOLON);
- throw pe;
- }
- {
- if (a != null)
- list.addAll(a);
- return list;
- }
- }
- List<TigerNode> ArrayInitializer():
- {
- List<TigerNode> list = new ArrayList<TigerNode>();
- List<TigerNode> a = null;
- List<TigerNode> b = null;
- }
- {
- try {
- "{" [ a=VariableInitializer() { if (a != null) list.addAll(a); } ( LOOKAHEAD(2) "," a=VariableInitializer() { if (b != null) list.addAll(b); } )* ] [ "," ] "}"
- }
- catch(ParseException pe) {
- //error_skipto(pe, SEMICOLON);
- throw pe;
- }
- {
- return list;
- }
- }
- /**
- * @return a MethodNode
- */
- TigerNode MethodDeclaration(Modifier m):
- {
- String type_params = "";
- Type return_type = null;
- MethodNode m_node = null;
- List<TigerNode> name_list = null;
- int line_number = -1;
- BlockNode block = null;
- Location endLoc = null;
- Token t = null;
- }
- {
- try {
- (
- // Modifiers already matched in the caller!
- [ type_params = TypeParameters() ]
- return_type = ResultType()
- m_node = MethodDeclarator() [ "throws" name_list=NameList() ]
- ( block = Block() | t=";" )
- )
- }
- catch(ParseException pe) {
- error_skipto(pe, SEMICOLON, RBRACE, PUBLIC, PRIVATE, PROTECTED);
- }
- {
- if (m_node == null)
- return null;
- MethodNode node = new MethodNode();
- node.setName(m_node.getName());
- if (m.beginColumn == -1)
- node.setStartLocation(new Location(m_node.getStartLocation().line, 0));
- else
- node.setStartLocation(getLocation(m));
- node.setModifiers(m.modif…