Mathias Landhäußer 11 лет назад
Родитель
Сommit
3d8c929c68

+ 84 - 0
jplag.frontend.java-1.5/pom.xml

@@ -0,0 +1,84 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+	<modelVersion>4.0.0</modelVersion>
+	<version>0.0.1-SNAPSHOT</version>
+
+	<repositories>
+		<repository>
+			<id>ipdNexus</id>
+			<name>Recaa Repository</name>
+			<url>http://bob.ipd.kit.edu/nexus/content/repositories/public/</url>
+		</repository>
+	</repositories>
+
+	<build>
+		<plugins>
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>build-helper-maven-plugin</artifactId>
+				<version>1.7</version>
+				<configuration>
+					<sources>
+						<source>target/generated-sources/javacc</source>
+					</sources>
+				</configuration>
+				<executions>
+					<execution>
+						<id>add-javacc-source</id>
+						<phase>generate-sources</phase>
+						<goals>
+							<goal>add-source</goal>
+						</goals>
+
+					</execution>
+				</executions>
+			</plugin>
+			<plugin>
+				<groupId>org.codehaus.mojo</groupId>
+				<artifactId>javacc-maven-plugin</artifactId>
+				<version>2.0</version>
+				<configuration>
+					<grammarEncoding>${project.build.sourceEncoding}</grammarEncoding>
+					<debugparser>false</debugparser>
+					<isStatic>false</isStatic>
+					<outputDirectory>src/main/java/jplag/java15/grammar</outputDirectory>
+				</configuration>
+				<executions>
+					<execution>
+						<id>javacc</id>
+						<goals>
+							<goal>javacc</goal>
+						</goals>
+					</execution>
+				</executions>
+			</plugin>
+
+			<plugin>
+				<groupId>org.apache.maven.plugins</groupId>
+				<artifactId>maven-jar-plugin</artifactId>
+				<configuration>
+					<archive>
+						<manifest>
+							<mainClass>jplag.java15.Parser</mainClass>
+							<packageName>jplag.java15</packageName>
+						</manifest>
+					</archive>
+				</configuration>
+			</plugin>
+		</plugins>
+	</build>
+
+	<dependencies>
+		<dependency>
+			<groupId>edu.kit.ipd.jplag</groupId>
+			<artifactId>frontend-utils</artifactId>
+			<version>0.0.3-SNAPSHOT</version>
+		</dependency>
+	</dependencies>
+	<parent>
+		<groupId>edu.kit.ipd.jplag.frontend</groupId>
+		<artifactId>frontend-parent</artifactId>
+		<version>0.3-SNAPSHOT</version>
+	</parent>
+	<artifactId>java-1.5</artifactId>
+</project>

+ 92 - 0
jplag.frontend.java-1.5/src/main/java/jplag/java15/JavaToken.java

@@ -0,0 +1,92 @@
+package jplag.java15;
+
+
+public class JavaToken extends jplag.Token implements JavaTokenConstants {
+	private static final long serialVersionUID = 3743208940428676175L;
+	private int line, column, length;
+
+	public JavaToken(int type, String file, int line, int column, int length) {
+		super(type, file, line, column, length);
+	}
+
+	public int getLine() { return line; }
+	public int getColumn() { return column; }
+	public int getLength() { return length; }
+	public void setLine(int line) { this.line = line; }
+	public void setColumn(int column) { this.column = column; }
+	public void setLength(int length) { this.length = length; }
+
+  public static String type2string(int type) {
+    switch (type) {
+		case JavaTokenConstants.FILE_END:				// @formatter:off
+                            return "********";
+	case JavaTokenConstants.SEPARATOR_TOKEN:
+							return "METHOD_SEPARATOR";
+    case J_PACKAGE:         return "PACKAGE ";
+    case J_IMPORT:          return "IMPORT  ";
+    case J_CLASS_BEGIN:     return "CLASS{  ";
+    case J_CLASS_END:       return "}CLASS  ";
+    case J_METHOD_BEGIN:    return "METHOD{ ";
+    case J_METHOD_END:      return "}METHOD ";
+    case J_VARDEF:          return "VARDEF  ";
+    case J_SYNC_BEGIN:      return "SYNC{   ";
+    case J_SYNC_END:        return "}SYNC   ";
+    case J_DO_BEGIN:        return "DO{     ";
+    case J_DO_END:          return "}DO     ";
+    case J_WHILE_BEGIN:     return "WHILE{  ";
+    case J_WHILE_END:       return "}WHILE  ";
+    case J_FOR_BEGIN:       return "FOR{    ";
+    case J_FOR_END:         return "}FOR    ";
+    case J_SWITCH_BEGIN:    return "SWITCH{ ";
+    case J_SWITCH_END:      return "}SWITCH ";
+    case J_CASE:            return "CASE    ";
+    case J_TRY_BEGIN:       return "TRY{    ";
+    case J_CATCH_BEGIN:     return "CATCH{  ";
+    case J_CATCH_END:       return "}CATCH  ";
+    case J_FINALLY:         return "FINALLY ";
+    case J_IF_BEGIN:        return "IF{     ";
+    case J_ELSE:            return "ELSE    ";
+    case J_IF_END:          return "}IF     ";
+    case J_COND:            return "COND    ";
+    case J_BREAK:           return "BREAK   ";
+    case J_CONTINUE:        return "CONTINUE";
+    case J_RETURN:          return "RETURN  ";
+    case J_THROW:           return "THROW   ";
+    case J_IN_CLASS_BEGIN:  return "INCLASS{";
+    case J_IN_CLASS_END:    return "}INCLASS";
+    case J_APPLY:           return "APPLY   ";
+    case J_NEWCLASS:        return "NEWCLASS";
+    case J_NEWARRAY:        return "NEWARRAY";
+    case J_ASSIGN:          return "ASSIGN  ";
+    case J_INTERFACE_BEGIN: return "INTERF{ ";
+    case J_INTERFACE_END:   return "}INTERF ";
+    case J_CONSTR_BEGIN:    return "CONSTR{ ";
+    case J_CONSTR_END:      return "}CONSTR ";
+    case J_INIT_BEGIN:      return "INIT{   ";
+    case J_INIT_END:        return "}INIT   ";
+    case J_VOID:            return "VOID    ";
+    case J_ARRAY_INIT_BEGIN:return "ARRINIT{";
+    case J_ARRAY_INIT_END:  return "ARRINIT}";
+    case J_ENUM_BEGIN:      return "ENUM{   ";
+    case J_ENUM_CLASS_BEGIN:return "ENUM_CLA";
+    case J_ENUM_END:        return "}ENUM   ";
+    case J_GENERIC:         return "GENERIC ";
+    case J_ASSERT:          return "ASSERT  ";
+    case J_ANNO:            return "ANNO    ";
+    case J_ANNO_MARKER:     return "ANNOMARK";
+    case J_ANNO_M_BEGIN:    return "ANNO_M{ ";
+    case J_ANNO_M_END:      return "}ANNO_M ";
+    case J_ANNO_T_BEGIN:    return "ANNO_T{ ";
+    case J_ANNO_T_END:      return "}ANNO_T ";
+    case J_ANNO_C_BEGIN:    return "ANNO_C{ ";
+    case J_ANNO_C_END:      return "}ANNO_C ";
+
+    default:                return "*UNKNOWN"; // @formatter:on
+    }
+  }
+  
+  public static int numberOfTokens() { 
+    return NUM_DIFF_TOKENS;
+  } 
+}
+

+ 72 - 0
jplag.frontend.java-1.5/src/main/java/jplag/java15/JavaTokenConstants.java

@@ -0,0 +1,72 @@
+package jplag.java15;
+
+public interface JavaTokenConstants extends jplag.TokenConstants {
+  final static int FILE_END = 0;
+  
+  // Used to optionally separate methods from each other
+  // with an always marked token
+  final static int SEPARATOR_TOKEN = 1;
+
+  final static int J_PACKAGE = 2;               //
+  final static int J_IMPORT = 3;                //
+  final static int J_CLASS_BEGIN = 4;           //
+  final static int J_CLASS_END = 5;             //
+  final static int J_METHOD_BEGIN = 6;          //
+  final static int J_METHOD_END = 7;            //
+  final static int J_VARDEF = 8;                //
+  final static int J_SYNC_BEGIN = 9;            //
+  final static int J_SYNC_END = 10;              //
+  final static int J_DO_BEGIN = 11;             //
+  final static int J_DO_END = 12;               //
+  final static int J_WHILE_BEGIN = 13;          //
+  final static int J_WHILE_END = 14;            //
+  final static int J_FOR_BEGIN = 15;            //
+  final static int J_FOR_END = 16;              //
+  final static int J_SWITCH_BEGIN = 17;         //
+  final static int J_SWITCH_END = 18;           //
+  final static int J_CASE = 19;                 //
+  final static int J_TRY_BEGIN = 20;            //
+  final static int J_CATCH_BEGIN = 21;          //
+  final static int J_CATCH_END = 22;            //
+  final static int J_FINALLY = 23;              //
+  final static int J_IF_BEGIN = 24;             //
+  final static int J_ELSE = 25;                 //
+  final static int J_IF_END = 26;               //
+  final static int J_COND = 27;                 //
+  final static int J_BREAK = 28;                //
+  final static int J_CONTINUE = 29;             //
+  final static int J_RETURN = 30;               //
+  final static int J_THROW = 31;                //
+  final static int J_IN_CLASS_BEGIN=32;         //
+  final static int J_IN_CLASS_END = 33;         //
+  final static int J_APPLY = 34;                //
+  final static int J_NEWCLASS = 35;             //
+  final static int J_NEWARRAY = 36;             //
+  final static int J_ASSIGN = 37;               //
+  final static int J_INTERFACE_BEGIN=38;        //
+  final static int J_INTERFACE_END = 39;        //
+  final static int J_CONSTR_BEGIN = 40;         //
+  final static int J_CONSTR_END = 41;           //
+  final static int J_INIT_BEGIN = 42;           //
+  final static int J_INIT_END = 43;             //
+  final static int J_VOID = 44;                 //
+  final static int J_ARRAY_INIT_BEGIN = 45;     //
+  final static int J_ARRAY_INIT_END = 46;       //
+  // new in 1.5:
+  final static int J_ENUM_BEGIN = 47;           //
+  final static int J_ENUM_CLASS_BEGIN = 48;     //
+  final static int J_ENUM_END = 49;             //
+  final static int J_GENERIC = 50;              //
+  final static int J_ASSERT = 51;               //
+
+  final static int J_ANNO = 52;                 //
+  final static int J_ANNO_MARKER = 53;          //
+  final static int J_ANNO_M_BEGIN = 54;         //
+  final static int J_ANNO_M_END = 55;           //
+  final static int J_ANNO_T_BEGIN = 56;         //
+  final static int J_ANNO_T_END = 57;           //
+  final static int J_ANNO_C_BEGIN = 58;         //
+  final static int J_ANNO_C_END = 59;           //
+  
+  final static int NUM_DIFF_TOKENS = 60;
+}

+ 63 - 0
jplag.frontend.java-1.5/src/main/java/jplag/java15/Language.java

@@ -0,0 +1,63 @@
+package jplag.java15;
+
+import java.io.File;
+
+import jplag.ProgramI;
+
+public class Language implements jplag.Language {
+	private Parser parser;
+
+	public Language(ProgramI program) {
+		this.parser = new Parser(false);
+		this.parser.setProgram(program);
+	}
+
+	public int errorsCount() {
+		return this.parser.errorsCount();
+	}
+
+	public String[] suffixes() {
+		String[] res = { ".java", ".jav", ".JAVA", ".JAV" };
+		return res;
+	}
+
+	public String name() {
+		return "Java1.5 Parser";
+	}
+
+	public String getShortName() {
+		return "java15";
+	}
+
+	public int min_token_match() {
+		return 8;
+	}
+
+	public jplag.Structure parse(File dir, String[] files) {
+		return this.parser.parse(dir, files);
+	}
+
+	public boolean errors() {
+		return this.parser.getErrors();
+	}
+
+	public boolean supportsColumns() {
+		return true;
+	}
+
+	public boolean isPreformated() {
+		return true;
+	}
+
+	public boolean usesIndex() {
+		return false;
+	}
+
+	public int noOfTokens() {
+		return jplag.java15.JavaToken.numberOfTokens();
+	}
+
+	public String type2string(int type) {
+		return jplag.java15.JavaToken.type2string(type);
+	}
+}

+ 68 - 0
jplag.frontend.java-1.5/src/main/java/jplag/java15/LanguageWithDelimitedMethods.java

@@ -0,0 +1,68 @@
+package jplag.java15;
+
+import java.io.File;
+
+import jplag.ProgramI;
+
+/**
+ * Java 1.5 parser with method separators; if you know why these separators
+ * exist, PLEASE tell us or document at
+ * https://svn.ipd.kit.edu/trac/jplag/wiki/Server/Frontends/Java-1.5)
+ */
+public class LanguageWithDelimitedMethods implements jplag.Language {
+	private Parser parser;
+
+	public LanguageWithDelimitedMethods(ProgramI program) {
+		this.parser = new Parser(true);
+		this.parser.setProgram(program);
+	}
+
+	public int errorsCount() {
+		return this.parser.errorsCount();
+	}
+
+	public String[] suffixes() {
+		String[] res = { ".java", ".jav", ".JAVA", ".JAV" };
+		return res;
+	}
+
+	public String name() {
+		return "Java1.5 Parser with delimited methods";
+	}
+
+	public String getShortName() {
+		return "java15dm";
+	}
+
+	public int min_token_match() {
+		return 8;
+	}
+
+	public jplag.Structure parse(File dir, String[] files) {
+		return this.parser.parse(dir, files);
+	}
+
+	public boolean errors() {
+		return this.parser.getErrors();
+	}
+
+	public boolean supportsColumns() {
+		return true;
+	}
+
+	public boolean isPreformated() {
+		return true;
+	}
+
+	public boolean usesIndex() {
+		return false;
+	}
+
+	public int noOfTokens() {
+		return jplag.java15.JavaToken.numberOfTokens();
+	}
+
+	public String type2string(int type) {
+		return jplag.java15.JavaToken.type2string(type);
+	}
+}

+ 90 - 0
jplag.frontend.java-1.5/src/main/java/jplag/java15/Parser.java

@@ -0,0 +1,90 @@
+package jplag.java15;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileReader;
+import java.io.IOException;
+
+import jplag.java15.grammar.JavaParser;
+import jplag.java15.grammar.Token;
+
+public class Parser extends jplag.Parser implements JavaTokenConstants {
+	private String actFile;
+	private boolean useMethodSeparators;
+
+	private jplag.Structure struct;
+
+	public Parser(boolean useMethodSeparators) {
+		this.useMethodSeparators = useMethodSeparators;
+	}
+
+	public static void main(String args[]) {
+		if (args.length != 1) {
+			System.out.println("Only one parameter allowed.");
+			System.exit(-1);
+		}
+		Parser parser = new Parser(true);
+		parser.setProgram(new jplag.StrippedProgram());
+		jplag.Structure struct = parser.parse(null, args);
+		try {
+			BufferedReader reader = new BufferedReader(new FileReader(new File(args[0])));
+			int lineNr = 1;
+			int token = 0;
+			String line;
+			while ((line = reader.readLine()) != null) {
+				if (token < struct.size()) {
+					boolean first = true;
+					while (struct.tokens[token] != null && struct.tokens[token].getLine() == lineNr) {
+						if (!first) {
+							System.out.println();
+						}
+						JavaToken tok = (JavaToken) struct.tokens[token];
+						System.out.print(JavaToken.type2string(tok.type) + " (" + tok.getLine() + "," + tok.getColumn() + ","
+								+ tok.getLength() + ")\t");
+						first = false;
+						token++;
+					}
+					if (first)
+						System.out.print("                \t");
+				}
+				System.out.println(line);
+				lineNr++;
+			}
+			reader.close();
+		} catch (IOException e) {
+			e.printStackTrace();
+		}
+	}
+
+	public jplag.Structure parse(File dir, String files[]) {
+		struct = new jplag.Structure();
+		errors = 0;
+
+		JavaParser parser = null; // This will be (re)initialised in parseFile()
+
+		for (int i = 0; i < files.length; i++) {
+			actFile = files[i];
+			getProgram().print(null, "Parsing file " + files[i] + "\n");
+			if (!JavaParser.parseFile(dir, files[i], parser, this))
+				errors++;
+
+			struct.addToken(new JavaToken(FILE_END, actFile, -1, -1, -1));
+		}
+
+		this.parseEnd();
+		return struct;
+	}
+
+	public void add(int type, Token token) {
+		if (type == SEPARATOR_TOKEN && !useMethodSeparators)
+			return;
+
+		JavaToken tok = new JavaToken(type, actFile, token.beginLine, token.beginColumn, token.image.length());
+		struct.addToken(tok);
+
+		/*
+		 * getProgram().print(null,token.beginLine+"\t"+
+		 * JavaToken.type2string(type)+"\t"+ token.image);
+		 */
+	}
+}

+ 545 - 0
jplag.frontend.java-1.5/src/main/java/jplag/java15/grammar/JavaTabModCharStream.java

@@ -0,0 +1,545 @@
+/* Generated By:JavaCC: Do not edit this line. JavaCharStream.java Version 3.0 */
+package jplag.java15.grammar;
+
+/**
+ * An implementation of interface CharStream, where the stream is assumed to
+ * contain only ASCII characters (with java-like unicode escape processing).
+ * 
+ * Modification: Tabs are kept as single characters in column calculation
+ */
+
+public class JavaTabModCharStream implements CharStream
+{
+  public static final boolean staticFlag = false;
+  static final int hexval(char c) throws java.io.IOException {
+    switch(c)
+    {
+       case '0' :
+          return 0;
+       case '1' :
+          return 1;
+       case '2' :
+          return 2;
+       case '3' :
+          return 3;
+       case '4' :
+          return 4;
+       case '5' :
+          return 5;
+       case '6' :
+          return 6;
+       case '7' :
+          return 7;
+       case '8' :
+          return 8;
+       case '9' :
+          return 9;
+
+       case 'a' :
+       case 'A' :
+          return 10;
+       case 'b' :
+       case 'B' :
+          return 11;
+       case 'c' :
+       case 'C' :
+          return 12;
+       case 'd' :
+       case 'D' :
+          return 13;
+       case 'e' :
+       case 'E' :
+          return 14;
+       case 'f' :
+       case 'F' :
+          return 15;
+    }
+
+    throw new java.io.IOException(); // Should never come here
+  }
+
+  public int bufpos = -1;
+  int bufsize;
+  int available;
+  int tokenBegin;
+  protected int bufline[];
+  protected int bufcolumn[];
+
+  protected int column = 0;
+  protected int line = 1;
+
+  protected boolean prevCharIsCR = false;
+  protected boolean prevCharIsLF = false;
+
+  protected java.io.Reader inputStream;
+
+  protected char[] nextCharBuf;
+  protected char[] buffer;
+  protected int maxNextCharInd = 0;
+  protected int nextCharInd = -1;
+  protected int inBuf = 0;
+
+  protected void ExpandBuff(boolean wrapAround)
+  {
+     char[] newbuffer = new char[bufsize + 2048];
+     int newbufline[] = new int[bufsize + 2048];
+     int newbufcolumn[] = new int[bufsize + 2048];
+
+     try
+     {
+        if (wrapAround)
+        {
+           System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+           System.arraycopy(buffer, 0, newbuffer,
+                                             bufsize - tokenBegin, bufpos);
+           buffer = newbuffer;
+
+           System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+           System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
+           bufline = newbufline;
+
+           System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+           System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
+           bufcolumn = newbufcolumn;
+
+           bufpos += (bufsize - tokenBegin);
+        }
+        else
+        {
+           System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
+           buffer = newbuffer;
+
+           System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
+           bufline = newbufline;
+
+           System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
+           bufcolumn = newbufcolumn;
+
+           bufpos -= tokenBegin;
+        }
+     }
+     catch (Throwable t)
+     {
+        throw new Error(t.getMessage());
+     }
+
+     available = (bufsize += 2048);
+     tokenBegin = 0;
+  }
+
+  protected void FillBuff() throws java.io.IOException
+  {
+     int i;
+     if (maxNextCharInd == 4096)
+        maxNextCharInd = nextCharInd = 0;
+
+     try {
+        if ((i = inputStream.read(nextCharBuf, maxNextCharInd,
+                                            4096 - maxNextCharInd)) == -1)
+        {
+           inputStream.close();
+           throw new java.io.IOException();
+        }
+        else
+           maxNextCharInd += i;
+        return;
+     }
+     catch(java.io.IOException e) {
+        if (bufpos != 0)
+        {
+           --bufpos;
+           backup(0);
+        }
+        else
+        {
+           bufline[bufpos] = line;
+           bufcolumn[bufpos] = column;
+        }
+        throw e;
+     }
+  }
+
+  protected char ReadByte() throws java.io.IOException
+  {
+     if (++nextCharInd >= maxNextCharInd)
+        FillBuff();
+
+     return nextCharBuf[nextCharInd];
+  }
+
+  public char BeginToken() throws java.io.IOException
+  {     
+     if (inBuf > 0)
+     {
+        --inBuf;
+
+        if (++bufpos == bufsize)
+           bufpos = 0;
+
+        tokenBegin = bufpos;
+        return buffer[bufpos];
+     }
+
+     tokenBegin = 0;
+     bufpos = -1;
+
+     return readChar();
+  }     
+
+  protected void AdjustBuffSize()
+  {
+     if (available == bufsize)
+     {
+        if (tokenBegin > 2048)
+        {
+           bufpos = 0;
+           available = tokenBegin;
+        }
+        else
+           ExpandBuff(false);
+     }
+     else if (available > tokenBegin)
+        available = bufsize;
+     else if ((tokenBegin - available) < 2048)
+        ExpandBuff(true);
+     else
+        available = tokenBegin;
+  }
+
+  protected void UpdateLineColumn(char c)
+  {
+     column++;
+
+     if (prevCharIsLF)
+     {
+        prevCharIsLF = false;
+        line += (column = 1);
+     }
+     else if (prevCharIsCR)
+     {
+        prevCharIsCR = false;
+        if (c == '\n')
+        {
+           prevCharIsLF = true;
+        }
+        else
+           line += (column = 1);
+     }
+
+     switch (c)
+     {
+        case '\r' :
+           prevCharIsCR = true;
+           break;
+        case '\n' :
+           prevCharIsLF = true;
+           break;
+        default :
+           break;
+     }
+
+     bufline[bufpos] = line;
+     bufcolumn[bufpos] = column;
+  }
+
+  public char readChar() throws java.io.IOException
+  {
+     if (inBuf > 0)
+     {
+        --inBuf;
+
+        if (++bufpos == bufsize)
+           bufpos = 0;
+
+        return buffer[bufpos];
+     }
+
+     char c;
+
+     if (++bufpos == available)
+        AdjustBuffSize();
+
+     if ((buffer[bufpos] = c = ReadByte()) == '\\')
+     {
+        UpdateLineColumn(c);
+
+        int backSlashCnt = 1;
+
+        for (;;) // Read all the backslashes
+        {
+           if (++bufpos == available)
+              AdjustBuffSize();
+
+           try
+           {
+              if ((buffer[bufpos] = c = ReadByte()) != '\\')
+              {
+                 UpdateLineColumn(c);
+                 // found a non-backslash char.
+                 if ((c == 'u') && ((backSlashCnt & 1) == 1))
+                 {
+                    if (--bufpos < 0)
+                       bufpos = bufsize - 1;
+
+                    break;
+                 }
+
+                 backup(backSlashCnt);
+                 return '\\';
+              }
+           }
+           catch(java.io.IOException e)
+           {
+              if (backSlashCnt > 1)
+                 backup(backSlashCnt);
+
+              return '\\';
+           }
+
+           UpdateLineColumn(c);
+           backSlashCnt++;
+        }
+
+        // Here, we have seen an odd number of backslash's followed by a 'u'
+        try
+        {
+           while ((c = ReadByte()) == 'u')
+              ++column;
+
+           buffer[bufpos] = c = (char)(hexval(c) << 12 |
+                                       hexval(ReadByte()) << 8 |
+                                       hexval(ReadByte()) << 4 |
+                                       hexval(ReadByte()));
+
+           column += 4;
+        }
+        catch(java.io.IOException e)
+        {
+           throw new Error("Invalid escape character at line " + line +
+                                         " column " + column + ".");
+        }
+
+        if (backSlashCnt == 1)
+           return c;
+        else
+        {
+           backup(backSlashCnt - 1);
+           return '\\';
+        }
+     }
+     else
+     {
+        UpdateLineColumn(c);
+        return (c);
+     }
+  }
+
+  /**
+   * @deprecated 
+   * @see #getEndColumn
+   */
+
+  public int getColumn() {
+     return bufcolumn[bufpos];
+  }
+
+  /**
+   * @deprecated 
+   * @see #getEndLine
+   */
+
+  public int getLine() {
+     return bufline[bufpos];
+  }
+
+  public int getEndColumn() {
+     return bufcolumn[bufpos];
+  }
+
+  public int getEndLine() {
+     return bufline[bufpos];
+  }
+
+  public int getBeginColumn() {
+     return bufcolumn[tokenBegin];
+  }
+
+  public int getBeginLine() {
+     return bufline[tokenBegin];
+  }
+
+  public void backup(int amount) {
+
+    inBuf += amount;
+    if ((bufpos -= amount) < 0)
+       bufpos += bufsize;
+  }
+
+  public JavaTabModCharStream(java.io.Reader dstream,
+                 int startline, int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    available = bufsize = buffersize;
+    buffer = new char[buffersize];
+    bufline = new int[buffersize];
+    bufcolumn = new int[buffersize];
+    nextCharBuf = new char[4096];
+  }
+
+  public JavaTabModCharStream(java.io.Reader dstream,
+                                        int startline, int startcolumn)
+  {
+     this(dstream, startline, startcolumn, 4096);
+  }
+
+  public JavaTabModCharStream(java.io.Reader dstream)
+  {
+     this(dstream, 1, 1, 4096);
+  }
+  public void ReInit(java.io.Reader dstream,
+                 int startline, int startcolumn, int buffersize)
+  {
+    inputStream = dstream;
+    line = startline;
+    column = startcolumn - 1;
+
+    if (buffer == null || buffersize != buffer.length)
+    {
+      available = bufsize = buffersize;
+      buffer = new char[buffersize];
+      bufline = new int[buffersize];
+      bufcolumn = new int[buffersize];
+      nextCharBuf = new char[4096];
+    }
+    prevCharIsLF = prevCharIsCR = false;
+    tokenBegin = inBuf = maxNextCharInd = 0;
+    nextCharInd = bufpos = -1;
+  }
+
+  public void ReInit(java.io.Reader dstream,
+                                        int startline, int startcolumn)
+  {
+     ReInit(dstream, startline, startcolumn, 4096);
+  }
+
+  public void ReInit(java.io.Reader dstream)
+  {
+     ReInit(dstream, 1, 1, 4096);
+  }
+  public JavaTabModCharStream(java.io.InputStream dstream, int startline,
+		  int startcolumn, int buffersize)
+  {
+     this(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
+  }
+
+  public JavaTabModCharStream(java.io.InputStream dstream, int startline,
+                                                           int startcolumn)
+  {
+     this(dstream, startline, startcolumn, 4096);
+  }
+
+  public JavaTabModCharStream(java.io.InputStream dstream)
+  {
+     this(dstream, 1, 1, 4096);
+  }
+
+  public void ReInit(java.io.InputStream dstream, int startline,
+		  int startcolumn, int buffersize)
+  {
+     ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, 4096);
+  }
+  public void ReInit(java.io.InputStream dstream, int startline,
+                                                           int startcolumn)
+  {
+     ReInit(dstream, startline, startcolumn, 4096);
+  }
+  public void ReInit(java.io.InputStream dstream)
+  {
+     ReInit(dstream, 1, 1, 4096);
+  }
+
+  public String GetImage()
+  {
+     if (bufpos >= tokenBegin)
+        return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
+     else
+        return new String(buffer, tokenBegin, bufsize - tokenBegin) +
+                              new String(buffer, 0, bufpos + 1);
+  }
+
+  public char[] GetSuffix(int len)
+  {
+     char[] ret = new char[len];
+
+     if ((bufpos + 1) >= len)
+        System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
+     else
+     {
+        System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
+                                                          len - bufpos - 1);
+        System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
+     }
+
+     return ret;
+  }
+
+  public void Done()
+  {
+     nextCharBuf = null;
+     buffer = null;
+     bufline = null;
+     bufcolumn = null;
+  }
+
+  /**
+   * Method to adjust line and column numbers for the start of a token.
+   */
+  public void adjustBeginLineColumn(int newLine, int newCol)
+  {
+     int start = tokenBegin;
+     int len;
+
+     if (bufpos >= tokenBegin)
+     {
+        len = bufpos - tokenBegin + inBuf + 1;
+     }
+     else
+     {
+        len = bufsize - tokenBegin + bufpos + 1 + inBuf;
+     }
+
+     int i = 0, j = 0, k = 0;
+     int nextColDiff = 0, columnDiff = 0;
+
+     while (i < len &&
+            bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
+     {
+        bufline[j] = newLine;
+        nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
+        bufcolumn[j] = newCol + columnDiff;
+        columnDiff = nextColDiff;
+        i++;
+     } 
+
+     if (i < len)
+     {
+        bufline[j] = newLine++;
+        bufcolumn[j] = newCol + columnDiff;
+
+        while (i++ < len)
+        {
+           if (bufline[j = start % bufsize] != bufline[++start % bufsize])
+              bufline[j] = newLine++;
+           else
+              bufline[j] = newLine;
+        }
+     }
+
+     line = bufline[j];
+     column = bufcolumn[j];
+  }
+
+}

+ 90 - 0
jplag.frontend.java-1.5/src/main/java/jplag/java15/grammar/Token.java

@@ -0,0 +1,90 @@
+/* Generated By:JavaCC: Do not edit this line. Token.java Version 3.0 */
+package jplag.java15.grammar;
+
+/**
+ * Describes the input token stream.
+ */
+
+public class Token {
+
+  /**
+   * An integer that describes the kind of this token.  This numbering
+   * system is determined by JavaCCParser, and a table of these numbers is
+   * stored in the file ...Constants.java.
+   */
+  public int kind;
+
+  /**
+   * beginLine and beginColumn describe the position of the first character
+   * of this token; endLine and endColumn describe the position of the
+   * last character of this token.
+   */
+  public int beginLine, beginColumn, endLine, endColumn;
+
+  /**
+   * The string image of the token.
+   */
+  public String image;
+
+  /**
+   * A reference to the next regular (non-special) token from the input
+   * stream.  If this is the last token from the input stream, or if the
+   * token manager has not read tokens beyond this one, this field is
+   * set to null.  This is true only if this token is also a regular
+   * token.  Otherwise, see below for a description of the contents of
+   * this field.
+   */
+  public Token next;
+
+  /**
+   * This field is used to access special tokens that occur prior to this
+   * token, but after the immediately preceding regular (non-special) token.
+   * If there are no such special tokens, this field is set to null.
+   * When there are more than one such special token, this field refers
+   * to the last of these special tokens, which in turn refers to the next
+   * previous special token through its specialToken field, and so on
+   * until the first special token (whose specialToken field is null).
+   * The next fields of special tokens refer to other special tokens that
+   * immediately follow it (without an intervening regular token).  If there
+   * is no such token, this field is null.
+   */
+  public Token specialToken;
+
+  /**
+   * Returns the image.
+   */
+  public String toString()
+  {
+     return image;
+  }
+
+  /**
+   * Returns a new Token object, by default. However, if you want, you
+   * can create and return subclass objects based on the value of ofKind.
+   * Simply add the cases to the switch for all those special cases.
+   * For example, if you have a subclass of Token called IDToken that
+   * you want to create if ofKind is ID, simlpy add something like :
+   *
+   *    case MyParserConstants.ID : return new IDToken();
+   *
+   * to the following switch statement. Then you can cast matchedToken
+   * variable to the appropriate type and use it in your lexical actions.
+   */
+  public static final Token newToken(int ofKind)
+  {
+     switch(ofKind)
+     {
+		case JavaParserConstants.RUNSIGNEDSHIFT:
+		case JavaParserConstants.RSIGNEDSHIFT:
+		case JavaParserConstants.GT:
+			return new GTToken();
+
+		default:
+			return new Token();
+     }
+  }
+
+	public static class GTToken extends Token {
+		int realKind = JavaParserConstants.GT;
+	}
+}

+ 1556 - 0
jplag.frontend.java-1.5/src/main/javacc/Java1.5.jj

@@ -0,0 +1,1556 @@
+/* Hey Emacs, this is -*- mode: java; page-delimiter: "^%%$"; -*- */
+
+/*
+ * Copyright © 2002 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * California 95054, U.S.A. All rights reserved.  Sun Microsystems, Inc. has
+ * intellectual property rights relating to technology embodied in the product
+ * that is described in this document. In particular, and without limitation,
+ * these intellectual property rights may include one or more of the U.S.
+ * patents listed at http://www.sun.com/patents and one or more additional
+ * patents or pending patent applications in the U.S. and in other countries.
+ * U.S. Government Rights - Commercial software. Government users are subject
+ * to the Sun Microsystems, Inc. standard license agreement and applicable
+ * provisions of the FAR and its supplements.  Use is subject to license terms.
+ * Sun,  Sun Microsystems,  the Sun logo and  Java are trademarks or registered
+ * trademarks of Sun Microsystems, Inc. in the U.S. and other countries.  This
+ * product is covered and controlled by U.S. Export Control laws and may be
+ * subject to the export or import laws in other countries.  Nuclear, missile,
+ * chemical biological weapons or nuclear maritime end uses or end users,
+ * whether direct or indirect, are strictly prohibited.  Export or reexport
+ * to countries subject to U.S. embargo or to entities identified on U.S.
+ * export exclusion lists, including, but not limited to, the denied persons
+ * and specially designated nationals lists is strictly prohibited.
+ */
+
+options {
+  JAVA_UNICODE_ESCAPE = true;
+  ERROR_REPORTING = false;
+  STATIC = false;
+  USER_CHAR_STREAM = true;
+}
+
+PARSER_BEGIN(JavaParser)
+package jplag.java15.grammar;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+
+import jplag.UnicodeReader;
+import jplag.java15.JavaTokenConstants;
+
+/**
+ * Grammar to parse Java version 1.5
+ * @author Sreenivasa Viswanadha - Simplified and enhanced for 1.5
+ */
+public class JavaParser implements JavaTokenConstants
+{
+    /**
+     * Class to hold modifiers.
+     */
+  
+    private jplag.java15.Parser parser2;
+    static public final class ModifierSet
+    {
+        /* Definitions of the bits in the modifiers field.  */
+        public static final int PUBLIC = 0x0001;
+        public static final int PROTECTED = 0x0002;
+        public static final int PRIVATE = 0x0004;
+        public static final int ABSTRACT = 0x0008;
+        public static final int STATIC = 0x0010;
+        public static final int FINAL = 0x0020;
+        public static final int SYNCHRONIZED = 0x0040;
+        public static final int NATIVE = 0x0080;
+        public static final int TRANSIENT = 0x0100;
+        public static final int VOLATILE = 0x0200;
+        public static final int STRICTFP = 0x1000;
+
+        /** A set of accessors that indicate whether the specified modifier is in the set. */
+
+        public boolean isPublic(int modifiers)
+        {
+            return (modifiers & PUBLIC) != 0;
+        }
+
+        public boolean isProtected(int modifiers)
+        {
+            return (modifiers & PROTECTED) != 0;
+        }
+
+        public boolean isPrivate(int modifiers)
+        {
+            return (modifiers & PRIVATE) != 0;
+        }
+
+        public boolean isStatic(int modifiers)
+        {
+            return (modifiers & STATIC) != 0;
+        }
+
+        public boolean isAbstract(int modifiers)
+        {
+            return (modifiers & ABSTRACT) != 0;
+        }
+
+        public boolean isFinal(int modifiers)
+        {
+            return (modifiers & FINAL) != 0;
+        }
+
+        public boolean isNative(int modifiers)
+        {
+            return (modifiers & NATIVE) != 0;
+        }
+
+        public boolean isStrictfp(int modifiers)
+        {
+            return (modifiers & STRICTFP) != 0;
+        }
+
+        public boolean isSynchronized(int modifiers)
+        {
+            return (modifiers & SYNCHRONIZED) != 0;
+        }
+
+        public boolean isTransient(int modifiers)
+        {
+            return (modifiers & TRANSIENT) != 0;
+        }
+
+        public boolean isVolatile(int modifiers)
+        {
+            return (modifiers & VOLATILE) != 0;
+        }
+
+        /**
+          * Removes the given modifier.
+          */
+        static int removeModifier(int modifiers, int mod) {
+            return modifiers & ~mod;
+        }
+    }
+
+    //JavaParser parser = null;
+    JavaTabModCharStream charStream = null;
+
+    public static boolean parseFile(File dir, String fileName, JavaParser parser, jplag.java15.Parser parserX)
+    {
+        try {
+            FileInputStream in = new FileInputStream(new File(dir,fileName));
+            if (parser == null) {
+                JavaTabModCharStream charStream = new JavaTabModCharStream(new UnicodeReader(in, "ISO-8859-1"));
+                parser = new JavaParser(charStream);
+                parser.charStream = charStream;
+            } else {
+                parser.charStream.ReInit(new UnicodeReader(in, "ISO-8859-1"));
+                parser.ReInit(parser.charStream);
+            }
+            parser.parser2 = parserX;
+        } catch (FileNotFoundException e) {
+            System.out.println("Java Parser: File " + fileName + " not found.");
+            return false;
+        }
+        try {
+            parser.CompilationUnit();
+        } catch (ParseException e) {
+            parserX.getProgram().addError("  Parsing Error in '" + fileName + "':\n  " + e.getMessage() + "\n");
+            return false;
+        } catch (TokenMgrError e) {
+            parserX.getProgram().addError("  Scanning Error in '" + fileName + "':\n  " + e.getMessage() + "\n");
+            return false;
+        } catch (Exception e) {
+            parserX.getProgram().addError("  General error in '" + fileName + "':\n  " + e.getMessage() + "\n");
+            e.printStackTrace();
+            return false;
+        }
+        return true;
+    }
+}
+
+PARSER_END(JavaParser)
+
+/* WHITE SPACE */
+
+SKIP :
+{
+  " "
+| "\t"
+| "\n"
+| "\r"
+| "\f"
+}
+
+/* COMMENTS */
+
+SPECIAL_TOKEN :
+{
+  <SINGLE_LINE_COMMENT: "//" (~["\n", "\r"])* ("\n" | "\r" | "\r\n")? >
+}
+
+MORE :
+{
+  <"/**" ~["/"]> { input_stream.backup(1); } : IN_FORMAL_COMMENT
+|
+  "/*" : IN_MULTI_LINE_COMMENT
+}
+
+<IN_FORMAL_COMMENT>
+SPECIAL_TOKEN :
+{
+  <FORMAL_COMMENT: "*/" > : DEFAULT
+}
+
+<IN_MULTI_LINE_COMMENT>
+SPECIAL_TOKEN :
+{
+  <MULTI_LINE_COMMENT: "*/" > : DEFAULT
+}
+
+<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" >
+}
+
+/* LITERALS */
+
+TOKEN :
+{
+  < 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"]
+            )
+          )
+      )*
+      "\""
+  >
+}
+
+/* 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 JAVA LANGUAGE GRAMMAR STARTS HERE *
+ *****************************************/
+
+/*
+ * Program structuring syntax follows.
+ */
+
+void CompilationUnit():
+{}
+{
+  [ PackageDeclaration() ]
+  ( ImportDeclaration() )*
+  ( TypeDeclaration() )*
+  <EOF>
+}
+
+void PackageDeclaration():
+{}
+{
+  "package" { parser2.add(J_PACKAGE, token); }
+  Name() ";"
+    
+}
+
+void ImportDeclaration():
+{}
+{
+  "import" { parser2.add(J_IMPORT, token); }
+  [ "static" ] Name() [ "." "*" ] ";"
+}
+
+/*
+ * 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.
+ */
+
+int Modifiers():
+{
+   int modifiers = 0;
+}
+{
+ (
+  LOOKAHEAD(2)
+  (
+   "public" { modifiers |= ModifierSet.PUBLIC; }
+  |
+   "static" { modifiers |= ModifierSet.STATIC; }
+  |
+   "protected" { modifiers |= ModifierSet.PROTECTED; }
+  |
+   "private" { modifiers |= ModifierSet.PRIVATE; }
+  |
+   "final" { modifiers |= ModifierSet.FINAL; }
+  |
+   "abstract" { modifiers |= ModifierSet.ABSTRACT; }
+  |
+   "synchronized" { modifiers |= ModifierSet.SYNCHRONIZED; }
+  |
+   "native" { modifiers |= ModifierSet.NATIVE; }
+  |
+   "transient" { modifiers |= ModifierSet.TRANSIENT; }
+  |
+   "volatile" { modifiers |= ModifierSet.VOLATILE; }
+  |
+   "strictfp" { modifiers |= ModifierSet.STRICTFP; }
+  |
+   Annotation()
+  )
+ )*
+
+ {
+    return modifiers;
+ }
+}
+
+/*
+ * Declaration syntax follows.
+ */
+void TypeDeclaration():
+{
+   int modifiers;
+}
+{
+  ";"
+|
+  modifiers = Modifiers()
+  (
+     ClassOrInterfaceDeclaration(modifiers)
+   |
+     EnumDeclaration(modifiers)
+   |
+     AnnotationTypeDeclaration(modifiers)
+  )
+}
+
+
+void ClassOrInterfaceDeclaration(int modifiers):
+{
+   boolean isInterface = false;
+}
+{
+  ( "class" | "interface" { isInterface = true; } )
+        { parser2.add((isInterface ? J_INTERFACE_BEGIN : J_CLASS_BEGIN), token); }
+  <IDENTIFIER>
+  [ TypeParameters() ]
+  [ ExtendsList(isInterface) ]
+  [ ImplementsList(isInterface) ]
+  ClassOrInterfaceBody(isInterface)
+      { parser2.add((isInterface ? J_INTERFACE_END : J_CLASS_END), token); }
+}
+
+void ExtendsList(boolean isInterface):
+{
+   boolean extendsMoreThanOne = false;
+}
+{
+   "extends" ClassOrInterfaceType()
+   ( "," ClassOrInterfaceType() { extendsMoreThanOne = true; } )*
+   {
+      if (extendsMoreThanOne && !isInterface)
+         throw new ParseException("A class cannot extend more than one other class");
+   }
+}
+
+void ImplementsList(boolean isInterface):
+{}
+{
+   "implements" ClassOrInterfaceType()
+   ( "," ClassOrInterfaceType() )*
+   {
+      if (isInterface)
+         throw new ParseException("An interface cannot implement other interfaces");
+   }
+}
+
+void EnumDeclaration(int modifiers):
+{}
+{
+  "enum"							  { parser2.add(J_ENUM_BEGIN, token); }
+  <IDENTIFIER>
+  [ ImplementsList(false) ]
+  EnumBody()                          { parser2.add(J_ENUM_END, token); }
+}
+
+void EnumBody():
+{}
+{
+   "{"
+   EnumConstant() ( "," EnumConstant() )*
+   [ ";"                             { parser2.add(J_ENUM_CLASS_BEGIN, token); }
+     ( ClassOrInterfaceBodyDeclaration(false) )* ]
+   "}"
+}
+
+void EnumConstant():
+{}
+{
+  <IDENTIFIER> [ Arguments() ] [ ClassOrInterfaceBody(false) ]
+}
+
+void TypeParameters():
+{}
+{
+   "<" TypeParameter() ( "," TypeParameter() )* ">"
+}
+
+void TypeParameter():
+{}
+{
+   <IDENTIFIER> [ TypeBound() ]
+}
+
+void TypeBound():
+{}
+{
+   "extends" ClassOrInterfaceType() ( "&" ClassOrInterfaceType() )*
+}
+
+void ClassOrInterfaceBody(boolean isInterface):
+{}
+{
+  "{" ( ClassOrInterfaceBodyDeclaration(isInterface) )* "}"
+}
+
+void ClassOrInterfaceBodyDeclaration(boolean isInterface):
+{
+   boolean isNestedInterface = false;
+   int modifiers;
+}
+{
+  LOOKAHEAD(2)
+  Initializer()
+  {
+     if (isInterface)
+        throw new ParseException("An interface cannot have initializers");
+  }
+|
+  modifiers = Modifiers() // Just get all the modifiers out of the way. If you want to do
+              // more checks, pass the modifiers down to the member
+  (
+      ClassOrInterfaceDeclaration(modifiers)
+    |
+      EnumDeclaration(modifiers)
+    |
+      LOOKAHEAD( [ TypeParameters() ] <IDENTIFIER> "(" )
+      ConstructorDeclaration()
+    |
+      LOOKAHEAD( Type() <IDENTIFIER> ( "[" "]" )* ( "," | "=" | ";" ) )
+      FieldDeclaration(modifiers)
+    |
+      MethodDeclaration(modifiers)
+  )
+|
+  ";"
+}
+
+void FieldDeclaration(int modifiers):
+{}
+{
+  // Modifiers are already matched in the caller
+  Type() VariableDeclarator() ( "," VariableDeclarator() )* ";"
+}
+
+void VariableDeclarator():
+{}
+{
+  <IDENTIFIER>                  		  { parser2.add(J_VARDEF, token); }
+  ( "[" "]" )*
+  [ "="                                   { parser2.add(J_ASSIGN, token); }
+  VariableInitializer() ]
+}
+
+void VariableDeclaratorId():
+{}
+{
+  <IDENTIFIER> ( "[" "]" )*
+}
+
+void VariableInitializer():
+{}
+{
+  ArrayInitializer()
+|
+  Expression()
+}
+
+void ArrayInitializer():
+{}
+{
+  "{"								{ parser2.add(J_ARRAY_INIT_BEGIN, token); }
+  [ VariableInitializer() ( LOOKAHEAD(2) "," VariableInitializer() )* ] [ "," ]
+  "}"								{ parser2.add(J_ARRAY_INIT_END, token); }
+}
+
+void MethodDeclaration(int modifiers):
+{}
+{
+  // Modifiers already matched in the caller!
+  [ TypeParameters() ]
+  ResultType()
+  MethodDeclarator() [ "throws" NameList() ]
+      ( Block() | ";" )                 { parser2.add(J_METHOD_END, token); parser2.add(SEPARATOR_TOKEN, token); }
+}
+
+void MethodDeclarator():
+{}
+{
+  <IDENTIFIER>                          { parser2.add(SEPARATOR_TOKEN, token); parser2.add(J_METHOD_BEGIN, token); }
+  FormalParameters() ( "[" "]" )*
+}
+
+void FormalParameters():
+{}
+{
+  "(" [ FormalParameter() ( "," FormalParameter() )* ] ")"
+}
+
+void FormalParameter():
+{}
+{
+  ("final" | Annotation())* Type() [ "..." ] VariableDeclaratorId()
+}
+
+void ConstructorDeclaration():
+{}
+{
+  [ TypeParameters() ]
+  // Modifiers matched in the caller
+  <IDENTIFIER>                         { parser2.add(SEPARATOR_TOKEN, token); parser2.add(J_CONSTR_BEGIN, token); }
+  FormalParameters() [ "throws" NameList() ]
+  "{"
+    [ LOOKAHEAD(ExplicitConstructorInvocation()) ExplicitConstructorInvocation() ]
+    ( BlockStatement() )*
+  "}"                                  { parser2.add(J_CONSTR_END, token); parser2.add(SEPARATOR_TOKEN, token); }
+}
+
+void ExplicitConstructorInvocation():
+{}
+{
+  LOOKAHEAD("this" Arguments() ";")
+  "this"                               { parser2.add(J_APPLY, token); }
+  Arguments() ";"
+|
+  [ LOOKAHEAD(2) PrimaryExpression() "." ]
+  "super"                              { parser2.add(J_APPLY, token); }
+  Arguments() ";"
+}
+
+void Initializer():
+{}
+{
+  InitializerBegin()
+  ( BlockStatement() )* "}"            { parser2.add(J_INIT_END, token); }
+}
+
+void InitializerBegin():
+{}
+{
+  "static"							   { parser2.add(J_INIT_BEGIN, token); }
+  "{"
+|
+  "{"								   { parser2.add(J_INIT_BEGIN, token); }
+}
+
+/*
+ * Type, name and expression syntax follows.
+ */
+
+void Type():
+{}
+{
+   LOOKAHEAD(2) ReferenceType()
+ |
+   PrimitiveType()
+}
+
+void ReferenceType():
+{}
+{
+   PrimitiveType() ( LOOKAHEAD(2) "[" "]" )+
+  |
+   ( ClassOrInterfaceType() ) ( LOOKAHEAD(2) "[" "]" )*
+}
+
+void ClassOrInterfaceType():
+{}
+{
+  <IDENTIFIER> [ LOOKAHEAD(2) TypeArguments() ]
+  ( LOOKAHEAD(2) "." <IDENTIFIER> [ LOOKAHEAD(2) TypeArguments() ] )*
+}
+
+void TypeArguments():
+{}
+{
+   "<" TypeArgument()                  { parser2.add(J_GENERIC, token); }
+   ( "," TypeArgument()                { parser2.add(J_GENERIC, token); }
+   )* ">"
+}
+
+void TypeArgument():
+{}
+{
+   ReferenceType()
+ |
+   "?" [ WildcardBounds() ]
+}
+
+void WildcardBounds():
+{}
+{
+   "extends" ReferenceType()
+ |
+   "super" ReferenceType()
+}
+
+
+void PrimitiveType():
+{}
+{
+  "boolean"
+|
+  "char"
+|
+  "byte"
+|
+  "short"
+|
+  "int"
+|
+  "long"
+|
+  "float"
+|
+  "double"
+}
+
+void ResultType():
+{}
+{
+  "void"                               { parser2.add(J_VOID, token); }
+|
+  Type()
+}
+
+void Name():
+/*
+ * A lookahead of 2 is required below since "Name" can be followed
+ * by a ".*" when used in the context of an "ImportDeclaration".
+ */
+{}
+{
+  <IDENTIFIER>
+  ( LOOKAHEAD(2) "." <IDENTIFIER>
+  )*
+}
+
+void NameList():
+{}
+{
+  Name() ( "," Name() )*
+}
+
+
+/*
+ * Expression syntax follows.
+ */
+
+void Expression():
+/*
+ * This expansion has been written this way instead of:
+ *   Assignment() | ConditionalExpression()
+ * for performance reasons.
+ * However, it is a weakening of the grammar for it allows the LHS of
+ * assignments to be any conditional expression whereas it can only be
+ * a primary expression.  Consider adding a semantic predicate to work
+ * around this.
+ */
+{}
+{
+  ConditionalExpression()
+  [
+    LOOKAHEAD(2)
+    AssignmentOperator() Expression()
+  ]
+}
+
+void AssignmentOperator():
+{}
+{
+    ("=" | "*=" | "/=" | "%=" | "+=" | "-=" | "<<=" | ">>=" | ">>>=" | "&=" | "^=" | "|=")                                  { parser2.add(J_ASSIGN, token); }
+}
+
+void ConditionalExpression():
+{}
+{
+  ConditionalOrExpression()
+  [ "?"                                     { parser2.add(J_COND, token); }
+    Expression() ":" Expression() ]
+}
+
+void ConditionalOrExpression():
+{}
+{
+  ConditionalAndExpression() ( "||" ConditionalAndExpression() )*
+}
+
+void ConditionalAndExpression():
+{}
+{
+  InclusiveOrExpression() ( "&&" InclusiveOrExpression() )*
+}
+
+void InclusiveOrExpression():
+{}
+{
+  ExclusiveOrExpression() ( "|" ExclusiveOrExpression() )*
+}
+
+void ExclusiveOrExpression():
+{}
+{
+  AndExpression() ( "^" AndExpression() )*
+}
+
+void AndExpression():
+{}
+{
+  EqualityExpression() ( "&" EqualityExpression() )*
+}
+
+void EqualityExpression():
+{}
+{
+  InstanceOfExpression() ( ( "==" | "!=" ) InstanceOfExpression() )*
+}
+
+void InstanceOfExpression():
+{}
+{
+  RelationalExpression() [ "instanceof" Type() ]
+}
+
+void RelationalExpression():
+{}
+{
+  ShiftExpression() ( ( "<" | ">" | "<=" | ">=" ) ShiftExpression() )*
+}
+
+void ShiftExpression():
+{}
+{
+  AdditiveExpression() ( ( "<<" | RSIGNEDSHIFT() | RUNSIGNEDSHIFT() ) AdditiveExpression() )*
+}
+
+void AdditiveExpression():
+{}
+{
+  MultiplicativeExpression() ( ( "+" | "-" ) MultiplicativeExpression() )*
+}
+
+void MultiplicativeExpression():
+{}
+{
+  UnaryExpression() ( ( "*" | "/" | "%" ) UnaryExpression() )*
+}
+
+void UnaryExpression():
+{}
+{
+  ( "+" | "-" ) UnaryExpression()
+|
+  PreIncrementExpression()
+|
+  PreDecrementExpression()
+|
+  UnaryExpressionNotPlusMinus()
+}
+
+void PreIncrementExpression():
+{}
+{
+  "++"                                    { parser2.add(J_ASSIGN, token); }
+  PrimaryExpression()
+}
+
+void PreDecrementExpression():
+{}
+{
+  "--"                                    { parser2.add(J_ASSIGN, token); }
+  PrimaryExpression()
+}
+
+void UnaryExpressionNotPlusMinus():
+{}
+{
+  ( "~" | "!" ) UnaryExpression()
+|
+  LOOKAHEAD( CastLookahead() )
+  CastExpression()
+|
+  PostfixExpression()
+}
+
+// This production is to determine lookahead only.  The LOOKAHEAD specifications
+// below are not used, but they are there just to indicate that we know about
+// this.
+void CastLookahead():
+{}
+{
+  LOOKAHEAD(2)
+  "(" PrimitiveType()
+|
+  LOOKAHEAD("(" Type() "[")
+  "(" Type() "[" "]"
+|
+  "(" Type() ")" ( "~" | "!" | "(" | <IDENTIFIER> | "this" | "super" | "new" | Literal() )
+}
+
+void PostfixExpression():
+{}
+{
+  PrimaryExpression()
+  [ ( "++" | "--" )                       { parser2.add(J_ASSIGN, token); }
+  ]
+}
+
+void CastExpression():
+{}
+{
+  LOOKAHEAD("(" PrimitiveType())
+  "(" Type() ")" UnaryExpression()
+|
+  "(" Type() ")" UnaryExpressionNotPlusMinus()
+}
+
+void PrimaryExpression():
+{}
+{
+  PrimaryPrefix() ( LOOKAHEAD(2) PrimarySuffix() )*
+}
+
+void MemberSelector():
+{}
+{
+  "." TypeArguments() <IDENTIFIER>
+}
+
+void PrimaryPrefix():
+{}
+{
+  Literal()
+|
+  "this"
+|
+  "super" "." <IDENTIFIER>
+|
+  "(" Expression() ")"
+|
+  AllocationExpression()
+|
+  LOOKAHEAD( ResultType() "." "class" )
+  ResultType() "." "class"
+|
+  Name()
+}
+
+void PrimarySuffix():
+{}
+{
+(
+  LOOKAHEAD(2)
+  "." "this"
+|
+  LOOKAHEAD(2)
+  "." "super" "." <IDENTIFIER>
+|
+  LOOKAHEAD(2)
+  "." AllocationExpression()
+|
+  LOOKAHEAD(3)
+  MemberSelector()
+|
+  "[" Expression() "]"
+|
+  "." <IDENTIFIER>
+|
+  	{ parser2.add(J_APPLY, token); }
+  Arguments()
+)
+}
+
+void Literal():
+{}
+{
+  <INTEGER_LITERAL>
+|
+  <FLOATING_POINT_LITERAL>
+|
+  <CHARACTER_LITERAL>
+|
+  <STRING_LITERAL>
+|
+  BooleanLiteral()
+|
+  NullLiteral()
+}
+
+void BooleanLiteral():
+{}
+{
+  "true"
+|
+  "false"
+}
+
+void NullLiteral():
+{}
+{
+  "null"
+}
+
+void Arguments():
+{}
+{
+  "(" [ ArgumentList() ] ")"
+}
+
+void ArgumentList():
+{}
+{
+  Expression() ( "," Expression() )*
+}
+
+void AllocationExpression():
+{
+  Token x;
+}
+{
+  LOOKAHEAD(2)
+  "new"                                     { parser2.add(J_NEWARRAY, token); }
+  PrimitiveType() ArrayDimsAndInits()
+|
+  x="new"
+  ClassOrInterfaceType() [ TypeArguments() ]
+    (                                       { parser2.add(J_NEWARRAY, x); }
+      ArrayDimsAndInits()
+    |										{ parser2.add(J_NEWCLASS, x); }
+      Arguments()
+      [
+        "{"                           { parser2.add(J_IN_CLASS_BEGIN, token); }
+        ( ClassOrInterfaceBodyDeclaration(false) )* "}"
+        							  { parser2.add(J_IN_CLASS_END, token); }
+      ]
+    )
+}
+
+/*
+ * The third LOOKAHEAD specification below is to parse to PrimarySuffix
+ * if there is an expression between the "[...]".
+ */
+void ArrayDimsAndInits():
+{}
+{
+  LOOKAHEAD(2)
+  ( LOOKAHEAD(2) "[" Expression() "]" )+ ( LOOKAHEAD(2) "[" "]" )*
+|
+  ( "[" "]" )+ ArrayInitializer()
+}
+
+
+/*
+ * Statement syntax follows.
+ */
+
+void Statement():
+{}
+{
+  LOOKAHEAD(2)
+  LabeledStatement()
+|
+  AssertStatement()
+|
+  Block()
+|
+  EmptyStatement()
+|
+  StatementExpression() ";"
+|
+  SwitchStatement()
+|
+  IfStatement()
+|
+  WhileStatement()
+|
+  DoStatement()
+|
+  ForStatement()
+|
+  BreakStatement()
+|
+  ContinueStatement()
+|
+  ReturnStatement()
+|
+  ThrowStatement()
+|
+  SynchronizedStatement()
+|
+  TryStatement()
+}
+
+void AssertStatement():
+{}
+{
+  "assert"                                  { parser2.add(J_ASSERT, token); }
+  Expression() [ ":" Expression() ] ";"
+}
+
+void LabeledStatement():
+{}
+{
+  <IDENTIFIER> ":" Statement()
+}
+
+void Block():
+{}
+{
+  "{" ( BlockStatement() )* "}"
+}
+
+void BlockStatement():
+{}
+{
+  LOOKAHEAD(("final" | Annotation())* Type() <IDENTIFIER>)
+  LocalVariableDeclaration() ";"
+|
+  Statement()
+|
+  ClassOrInterfaceDeclaration(0)
+}
+
+void LocalVariableDeclaration():
+{}
+{
+  ("final" | Annotation())* Type() VariableDeclarator() ( "," VariableDeclarator() )*
+}
+
+void EmptyStatement():
+{}
+{
+  ";"
+}
+
+void StatementExpression():
+/*
+ * The last expansion of this production accepts more than the legal
+ * Java expansions for StatementExpression.  This expansion does not
+ * use PostfixExpression for performance reasons.
+ */
+{}
+{
+  PreIncrementExpression()
+|
+  PreDecrementExpression()
+|
+  PrimaryExpression()
+  [
+    "++"                               { parser2.add(J_ASSIGN, token); }
+  |
+    "--"                               { parser2.add(J_ASSIGN, token); }
+  |
+    AssignmentOperator() Expression()
+  ]
+}
+
+void SwitchStatement():
+{}
+{
+  "switch"                             { parser2.add(J_SWITCH_BEGIN, token); }
+  "(" Expression() ")" "{"
+    ( SwitchLabel()
+      ( BlockStatement() )*
+    )*
+  "}"                                  { parser2.add(J_SWITCH_END, token); }
+}
+
+void SwitchLabel():
+{}
+{
+  "case"							   { parser2.add(J_CASE, token); }
+  Expression() ":"
+|
+  "default"							   { parser2.add(J_CASE, token); }
+  ":"
+}
+
+void 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"                                 { parser2.add(J_IF_BEGIN, token); }
+  "(" Expression() ")" Statement()
+  [ LOOKAHEAD(1) "else"                { parser2.add(J_ELSE, token); }
+    Statement() ]
+                                       { parser2.add(J_IF_END, token); }
+}
+
+void WhileStatement():
+{}
+{
+  "while"                              { parser2.add(J_WHILE_BEGIN, token); }
+  "(" Expression() ")" Statement()     { parser2.add(J_WHILE_END, token); }
+}
+
+void DoStatement():
+{}
+{
+  "do"                                 { parser2.add(J_DO_BEGIN, token); }
+  Statement() "while" "(" Expression() ")" ";"
+                                       { parser2.add(J_DO_END, token); }
+}
+
+void ForStatement():
+{}
+{
+  "for"                                { parser2.add(J_FOR_BEGIN, token); }
+  "("
+  (
+      LOOKAHEAD(("final" | Annotation())* Type() <IDENTIFIER> ":")
+      ("final" | Annotation())* Type() <IDENTIFIER>
+      ":" Expression() 
+    |
+     [ ForInit() ] ";" [ Expression() ] ";" [ ForUpdate() ]
+  )
+
+  ")" Statement()
+                                       { parser2.add(J_FOR_END, token); }
+}
+
+void ForInit():
+{}
+{
+  LOOKAHEAD( [ "final" ] Type() <IDENTIFIER> )
+  LocalVariableDeclaration()
+|
+  StatementExpressionList()
+}
+
+void StatementExpressionList():
+{}
+{
+  StatementExpression() ( "," StatementExpression() )*
+}
+
+void ForUpdate():
+{}
+{
+  StatementExpressionList()
+}
+
+void BreakStatement():
+{}
+{
+  "break"                              { parser2.add(J_BREAK, token); }
+  [ <IDENTIFIER> ] ";"
+}
+
+void ContinueStatement():
+{}
+{
+  "continue"                           { parser2.add(J_CONTINUE, token); }
+  [ <IDENTIFIER> ] ";"
+}
+
+void ReturnStatement():
+{}
+{
+  "return"							   { parser2.add(J_RETURN, token); }
+  [ Expression() ] ";"
+}
+
+void ThrowStatement():
+{}
+{
+  "throw"                              { parser2.add(J_THROW, token); }
+  Expression() ";"
+}
+
+void SynchronizedStatement():
+{}
+{
+  "synchronized"                       { parser2.add(J_SYNC_BEGIN, token); }
+  "(" Expression() ")" Block()         { parser2.add(J_SYNC_END, token); }
+}
+
+void TryStatement():
+/*
+ * Semantic check required here to make sure that at least one
+ * finally/catch is present.
+ */
+{}
+{
+  "try"                                { parser2.add(J_TRY_BEGIN, token); }
+  Block()
+  ( "catch"                            { parser2.add(J_CATCH_BEGIN, token); }
+    "(" FormalParameter() ")" Block() )*
+  [ "finally"                          { parser2.add(J_FINALLY, token); }
+    Block() ]                          { parser2.add(J_CATCH_END, token); }
+}
+
+/* We use productions to match >>>, >> and > so that we can keep the
+ * type declaration syntax with generics clean
+ */
+
+void RUNSIGNEDSHIFT():
+{}
+{
+  ( LOOKAHEAD({ getToken(1).kind == GT &&
+                ((Token.GTToken)getToken(1)).realKind == RUNSIGNEDSHIFT} )
+   ">" ">" ">"
+  )
+}
+
+void RSIGNEDSHIFT():
+{}
+{
+  ( LOOKAHEAD({ getToken(1).kind == GT &&
+                ((Token.GTToken)getToken(1)).realKind == RSIGNEDSHIFT} )
+  ">" ">"
+  )
+}
+
+/* Annotation syntax follows. */
+
+void Annotation():
+{}
+{
+   LOOKAHEAD( "@" Name() "(" ( <IDENTIFIER> "=" | ")" ))
+   NormalAnnotation()
+ |
+   LOOKAHEAD( "@" Name() "(" )
+   SingleMemberAnnotation()
+ |
+   MarkerAnnotation()
+}
+
+void NormalAnnotation():
+{}
+{
+   "@"                                  { parser2.add(J_ANNO, token); }
+   Name()
+   "(" [ MemberValuePairs() ] ")"
+}
+
+void MarkerAnnotation():
+{}
+{
+  "@"                                   { parser2.add(J_ANNO_MARKER, token); }
+  Name()
+}
+
+void SingleMemberAnnotation():
+{}
+{
+  "@"                                   { parser2.add(J_ANNO, token); }
+  Name() "(" MemberValue() ")"
+}
+
+void MemberValuePairs():
+{}
+{
+   MemberValuePair() ( "," MemberValuePair() )*
+}
+
+void MemberValuePair():
+{}
+{
+    <IDENTIFIER> "=" MemberValue()
+}
+
+void MemberValue():
+{}
+{
+   Annotation()
+ |
+   MemberValueArrayInitializer()
+ |
+   ConditionalExpression()
+}
+
+void  MemberValueArrayInitializer():
+{}
+{
+  "{"                                   { parser2.add(J_ANNO_M_BEGIN, token); }
+  MemberValue() ( LOOKAHEAD(2) "," MemberValue() )* [ "," ]
+  "}"                                   { parser2.add(J_ANNO_M_END, token); }
+}
+
+
+/* Annotation Types. */
+
+void AnnotationTypeDeclaration(int modifiers):
+{}
+{
+  "@"                                   { parser2.add(J_ANNO_T_BEGIN, token); }
+  "interface" <IDENTIFIER> AnnotationTypeBody()
+                                        { parser2.add(J_ANNO_T_END, token); }
+}
+
+void AnnotationTypeBody():
+{}
+{
+  "{" ( AnnotationTypeMemberDeclaration() )* "}"
+}
+
+void AnnotationTypeMemberDeclaration():
+{
+   int modifiers;
+}
+{
+ modifiers = Modifiers()
+ (
+   LOOKAHEAD(Type() <IDENTIFIER> "(")
+   Type() <IDENTIFIER>
+   "(" ")" [ DefaultValue() ] ";"
+  |
+                                        { parser2.add(J_ANNO_C_BEGIN, token); }
+   ClassOrInterfaceDeclaration(modifiers)
+                                        { parser2.add(J_ANNO_C_END, token); }
+  |
+   EnumDeclaration(modifiers)
+  |
+   AnnotationTypeDeclaration(modifiers)
+  |
+   FieldDeclaration(modifiers)
+ )
+ |
+   ( ";" )
+}
+
+void DefaultValue():
+{}
+{
+  "default" MemberValue()
+}