/*******************************************************************************
* Copyright © 2011, 2013 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*
*******************************************************************************/
package org.eclipse.edt.compiler.core.ast;
import java.io.BufferedReader;
import java.io.FileReader;
import java.util.StringTokenizer;
/**
* Scans the contents of file ${PARSER_NAME}.java (assumed to be in working directory)
* and prints each line to standard out. Everything but the method CUP$Parser$do_action()
* is printed verbatim. The contents of that method (one large switch statement) are
* split between two methods.
*
* This technique is a workaround for the 65535-byte limit for methods in Java.
*
* @author Dave Murray
*/
public class ActionMethodSplitter {
public static final String PARSER_NAME = "Parser";
public static final String NL = System.getProperty( "line.separator" );
public static final String DO_ACTION_SIG_BEGIN1 = " public final java_cup.runtime.Symbol CUP$";
public static final String DO_ACTION_SIG_BEGIN2 = "$do_action(";
public static final String ACTION_TABLE_BEGIN = " protected static final short[][] _action_table = ";
public static void main( String[] args ) {
BufferedReader reader = null;
StringBuffer activeBuffer = new StringBuffer();
String doActionSig = null;
int numCases = -1;
String parserName = args.length == 1 ? args[0] : PARSER_NAME;
String doActionSigBegin = DO_ACTION_SIG_BEGIN1 + parserName + DO_ACTION_SIG_BEGIN2;
try {
reader = new BufferedReader( new FileReader( parserName + ".java" ) );
String line = reader.readLine();
while( line != null ) {
if( line.equals( doActionSigBegin ) ) {
System.out.println( activeBuffer );
activeBuffer = new StringBuffer();
while(!line.equals( " {" ) ) {
activeBuffer.append( line + NL );
line = reader.readLine();
}
activeBuffer.append( line + NL );
doActionSig = activeBuffer.toString();
doActionSig = doActionSig.replaceAll( "do_action", "do_action2" );
line = reader.readLine();
// Now line is " /*. . . . . . . . . . . . . . . . . . . .*/"
activeBuffer.append( line + NL );
line = reader.readLine();
// Now line is " case ###: // whenClause_plus ::= whenClause_plus whenClause"
StringTokenizer st = new StringTokenizer( line );
st.nextToken();
numCases = Integer.parseInt( st.nextToken().replaceAll(":", "") );
}
if( numCases != -1 && line.trim().startsWith( "case " + Integer.toString(numCases/2))) {
activeBuffer.append( " default:" + NL );
activeBuffer.append( " return( CUP$" + parserName + "$do_action2(CUP$" + parserName + "$act_num,CUP$" + parserName + "$parser,CUP$" + parserName + "$stack,CUP$" + parserName + "$top) ); " + NL );
activeBuffer.append( " }" + NL );
activeBuffer.append( " }" + NL );
System.out.println( activeBuffer );
System.out.println();
System.out.println( doActionSig );
numCases = -1;
activeBuffer = new StringBuffer();
}
// The _action_table field is ridiculously large so it needs to be split up too.
if (line.equals(ACTION_TABLE_BEGIN)) {
System.out.println( activeBuffer );
activeBuffer = new StringBuffer();
activeBuffer.append( line + " unpackFromStrings(join(ActionTableHelper1.strings, ActionTableHelper2.strings));" + NL + NL );
activeBuffer.append( " static String[] join(String[] s1, String[] s2) {" + NL );
activeBuffer.append( " String[] temp = new String[s1.length + s2.length];" + NL );
activeBuffer.append( " System.arraycopy(s1, 0, temp, 0, s1.length);" + NL );
activeBuffer.append( " System.arraycopy(s2, 0, temp, s1.length, s2.length);" + NL );
activeBuffer.append( " return temp;" + NL );
activeBuffer.append( " }" + NL + NL );
// Next line is 'unpackFromStrings(new String[] {' which we don't need.
line = reader.readLine();
// First 'chunk' - 10000 lines
boolean done = false;
int count = 0;
activeBuffer.append( " private static class ActionTableHelper1 {" + NL );
activeBuffer.append( " private static String[] strings = new String[] {" + NL );
while (!done && count < 10000) {
line = reader.readLine();
if (line.endsWith("});")) {
// last line.
line = line.substring(0, line.indexOf("});"));
done = true;
}
activeBuffer.append(line + NL);
count++;
}
activeBuffer.append(" };" + NL);
activeBuffer.append( " }" + NL + NL );
// Second chunk. If this parser ever shrinks to fit all in the first part, this is an empty array.
activeBuffer.append( " private static class ActionTableHelper2 {" + NL );
activeBuffer.append( " static String[] strings = new String[] {" + NL );
while (!done) {
line = reader.readLine();
if (line.endsWith("});")) {
// last line.
line = line.substring(0, line.indexOf("});"));
done = true;
}
activeBuffer.append(line + NL);
}
activeBuffer.append(" };" + NL);
activeBuffer.append( " }" + NL + NL );
line = reader.readLine();
}
activeBuffer.append( line + NL );
line = reader.readLine();
}
System.out.println( activeBuffer );
}
catch( Exception e ) {
e.printStackTrace();
}
finally {
try {
if( reader != null ) reader.close();
}
catch( Exception e ) {}
}
//public final java_cup.runtime.Symbol CUP$Parser$do_action(
}
}