001: package fri.patterns.interpreter.parsergenerator.builder;
002:
003: import java.io.File;
004: import java.lang.reflect.*;
005: import fri.patterns.interpreter.parsergenerator.parsertables.*;
006: import fri.patterns.interpreter.parsergenerator.syntax.Syntax;
007:
008: /**
009: This class is deprecated in favor of serialization.
010: <p>
011: CompiledTables buffers parser tables by generating source and compiling
012: that source. This lasts very long at first time, but is faster than
013: serialization for every subsequent call. The class will be posted in
014: current directory (has no package). The source gets removed after successful
015: compilation. The Sun compiler must be in package path, which is normally in
016: <i>$JAVA_HOME/lib/tools.jar</i>.
017: <p>
018: Building compiled Java ParserTables takes 1600, building from scratch takes 6000 millis.
019: CompiledTables seem to be slower than SerializedParser!
020: <p>
021: An alternative to compiled tables is generating the parser tables source
022: with <i>SourceGenerator</i> and integrating that source into project sources.
023: This avoids the dynamically created class in working directory and the neccessity
024: to have javac in CLASSPATH at runtime.
025: <pre>
026: ParserTables tables = new CompiledTables().get(syntaxInput, "MyParserTables");
027: </pre>
028:
029: @deprecated in favor of serialization
030: */
031:
032: public class CompiledTables {
033: /** The suffix for compiled ParserTables files. */
034: public static final String CLASSFILE_SUFFIX = "ParserTables";
035: private boolean DEVELOPMENT = false; // setting this to true in constructor will prevent the tables from being compiled
036:
037: /** Creates a parser tables factory that uses compiled tables as buffer. */
038: public CompiledTables() {
039: this (false);
040: }
041:
042: /** Creates a parser tables factory that uses compiled tables as buffer. @param development when true tables will NOT be compiled. */
043: public CompiledTables(boolean development) {
044: this .DEVELOPMENT = development;
045: }
046:
047: /**
048: Builds the ParserTables from scratch if not found as class in CLASSPATH, else loads that class.
049: LALRParserTables.class wil be the type of created parser tables.
050: @param syntaxInput the Parser syntax as File, InputStream, List of Lists, String [][] or Syntax.
051: @return ParserTables object, or object built from scratch that gets compiled into current directory.
052: */
053: public AbstractParserTables get(Object syntaxInput)
054: throws Exception {
055: return get(syntaxInput, null);
056: }
057:
058: /**
059: Builds the ParserTables from scratch if not found as class in CLASSPATH, else loads that class.
060: LALRParserTables.class wil be the type of created parser tables.
061: @param syntaxInput the Parser syntax as File, InputStream, List of Lists, String [][] or Syntax.
062: @param className name of target class of ParserTables, without package path, without .java extension.
063: @return ParserTables object, or object built from scratch that gets compiled into current directory.
064: */
065: public AbstractParserTables get(Object syntaxInput, String className)
066: throws Exception {
067: return get(LALRParserTables.class, syntaxInput, className);
068: }
069:
070: /**
071: Builds the ParserTables from scratch if not found as class in CLASSPATH, else loads that class.
072: LALRParserTables.class wil be the type of created parser tables.
073: @param syntaxInput the Parser syntax as File, InputStream, List of Lists, String [][] or Syntax.
074: @param className name of target class of ParserTables, without package path, without .java extension.
075: @param parserType class of ParserTables to create, e.g. LALRParserTables.class
076: @return ParserTables object, or object built from scratch that gets compiled into current directory.
077: */
078: public AbstractParserTables get(Class parserType,
079: Object syntaxInput, String className) throws Exception {
080: if (className == null)
081: className = SerializedObject
082: .baseNameFromSyntax(syntaxInput);
083:
084: className = className + CLASSFILE_SUFFIX;
085:
086: AbstractParserTables parserTables = null;
087:
088: if (DEVELOPMENT == false) {
089: try {
090: Class cls = Class.forName(className);
091: parserTables = AbstractParserTables
092: .construct(cls, null);
093: } catch (Exception e) { // class is not present
094: System.err
095: .println("Could not find compiled parser tables for classname "
096: + className
097: + " in "
098: + System.getProperty("java.class.path")
099: + " - trying scratch build: "
100: + e.toString());
101: }
102: }
103:
104: if (parserTables == null) {
105: fri.util.TimeStopper ts = new fri.util.TimeStopper();
106:
107: Syntax grammar = SerializedObject.toSyntax(syntaxInput);
108: parserTables = AbstractParserTables.construct(parserType,
109: grammar);
110: if (DEVELOPMENT == false) {
111: String javaFile = parserTables.toSourceFile(className);
112: int ret = compile(javaFile);
113: new File(javaFile).delete(); // source file no more needed
114: System.err
115: .println("ParserTables scratch compilation took "
116: + ts.getTimeMillis()
117: + " millis, return was " + ret);
118: }
119: }
120:
121: return parserTables;
122: }
123:
124: /**
125: Aufruf des Sun-Compilers. Dazu muss tools.jar im CLASSPATH sein!
126: @return return-code von "new com.sun.tools.javac.Main().compile(javaFile)".
127: */
128: protected int compile(String javaFile) {
129: try {
130: String javaCompiler = "com.sun.tools.javac.Main";
131: System.err.println("compiling source: " + javaCompiler
132: + " " + javaFile);
133:
134: Class cls = Class.forName(javaCompiler);
135: Object compiler = cls.newInstance();
136: Method method = cls.getMethod("compile",
137: new Class[] { String[].class });
138: String[] args = new String[] {
139: "-classpath",
140: "." + System.getProperty("path.separator")
141: + System.getProperty("java.class.path"),
142: javaFile };
143: Object o = method.invoke(compiler, new Object[] { args });
144: int ret = ((Integer) o).intValue();
145:
146: System.err.println("javac returns " + ret);
147: return ret;
148: } catch (Exception e) {
149: e.printStackTrace();
150: System.err
151: .println("com.sun.tools.javac.Main() not present. Please put $JAVA_HOME/lib/tools.jar into CLASSPATH for quick loading next time.");
152: }
153: return -1;
154: }
155:
156: /** Test main. Building compiled ParserTables takes 1600, building from scratch takes 6000 millis. */
157: public static void main(String[] args) {
158: try {
159: File syntaxFile = new File(
160: "fri/patterns/interpreter/parsergenerator/syntax/builder/examples/SyntaxBuilder.syntax");
161: Syntax syntax = new fri.patterns.interpreter.parsergenerator.syntax.builder.SyntaxBuilder(
162: syntaxFile).getParserSyntax();
163: fri.util.TimeStopper ts = new fri.util.TimeStopper();
164: AbstractParserTables parserTables = new CompiledTables()
165: .get(syntax, "SyntaxBuilderParserTables");
166: System.err.println("ParserTables were built in "
167: + ts.getTimeMillis() + " millis");
168: } catch (Exception e) {
169: e.printStackTrace();
170: }
171: }
172:
173: }
|