diff options
Diffstat (limited to 'framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java')
-rw-r--r-- | framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java | 438 |
1 files changed, 438 insertions, 0 deletions
diff --git a/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java new file mode 100644 index 00000000..605b3368 --- /dev/null +++ b/framework/src/ant/apache-ant-1.9.6/src/main/org/apache/tools/ant/taskdefs/optional/ANTLR.java @@ -0,0 +1,438 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.tools.ant.taskdefs.optional; + +import java.io.BufferedReader; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; + +import org.apache.tools.ant.AntClassLoader; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.Project; +import org.apache.tools.ant.Task; +import org.apache.tools.ant.taskdefs.Execute; +import org.apache.tools.ant.taskdefs.LogOutputStream; +import org.apache.tools.ant.taskdefs.PumpStreamHandler; +import org.apache.tools.ant.taskdefs.condition.Os; +import org.apache.tools.ant.types.Commandline; +import org.apache.tools.ant.types.CommandlineJava; +import org.apache.tools.ant.types.Path; +import org.apache.tools.ant.util.FileUtils; +import org.apache.tools.ant.util.JavaEnvUtils; +import org.apache.tools.ant.util.LoaderUtils; +import org.apache.tools.ant.util.TeeOutputStream; + +/** + * Invokes the ANTLR Translator generator on a grammar file. + * + */ +public class ANTLR extends Task { + + private CommandlineJava commandline = new CommandlineJava(); + + /** the file to process */ + private File targetFile; + + /** where to output the result */ + private File outputDirectory; + + /** an optional super grammar file */ + private File superGrammar; + + /** optional flag to enable html output */ + private boolean html; + + /** optional flag to print out a diagnostic file */ + private boolean diagnostic; + + /** optional flag to add trace methods */ + private boolean trace; + + /** optional flag to add trace methods to the parser only */ + private boolean traceParser; + + /** optional flag to add trace methods to the lexer only */ + private boolean traceLexer; + + /** optional flag to add trace methods to the tree walker only */ + private boolean traceTreeWalker; + + /** working directory */ + private File workingdir = null; + + /** captures ANTLR's output */ + private ByteArrayOutputStream bos = new ByteArrayOutputStream(); + + /** The debug attribute */ + private boolean debug; + + + /** Instance of a utility class to use for file operations. */ + private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); + + /** Constructor for ANTLR task. */ + public ANTLR() { + commandline.setVm(JavaEnvUtils.getJreExecutable("java")); + commandline.setClassname("antlr.Tool"); + } + + /** + * The grammar file to process. + * @param target the gramer file + */ + public void setTarget(File target) { + log("Setting target to: " + target.toString(), Project.MSG_VERBOSE); + this.targetFile = target; + } + + /** + * The directory to write the generated files to. + * @param outputDirectory the output directory + */ + public void setOutputdirectory(File outputDirectory) { + log("Setting output directory to: " + outputDirectory.toString(), Project.MSG_VERBOSE); + this.outputDirectory = outputDirectory; + } + + /** + * Sets an optional super grammar file. + * Use setGlib(File superGrammar) instead. + * @param superGrammar the super grammar filename + * @deprecated since ant 1.6 + */ + public void setGlib(String superGrammar) { + String sg = null; + if (Os.isFamily("dos")) { + sg = superGrammar.replace('\\', '/'); + } else { + sg = superGrammar; + } + setGlib(FILE_UTILS.resolveFile(getProject().getBaseDir(), sg)); + } + /** + * Sets an optional super grammar file + * @param superGrammar the super grammar file + * @since ant 1.6 + */ + public void setGlib(File superGrammar) { + this.superGrammar = superGrammar; + } + /** + * Sets a flag to enable ParseView debugging + * @param enable a <code>boolean</code> value + */ + public void setDebug(boolean enable) { + this.debug = enable; + } + + /** + * If true, emit html + * @param enable a <code>boolean</code> value + */ + public void setHtml(boolean enable) { + html = enable; + } + + /** + * Sets a flag to emit diagnostic text + * @param enable a <code>boolean</code> value + */ + public void setDiagnostic(boolean enable) { + diagnostic = enable; + } + + /** + * If true, enables all tracing. + * @param enable a <code>boolean</code> value + */ + public void setTrace(boolean enable) { + trace = enable; + } + + /** + * If true, enables parser tracing. + * @param enable a <code>boolean</code> value + */ + public void setTraceParser(boolean enable) { + traceParser = enable; + } + + /** + * If true, enables lexer tracing. + * @param enable a <code>boolean</code> value + */ + public void setTraceLexer(boolean enable) { + traceLexer = enable; + } + + /** + * Sets a flag to allow the user to enable tree walker tracing + * @param enable a <code>boolean</code> value + */ + public void setTraceTreeWalker(boolean enable) { + traceTreeWalker = enable; + } + + // we are forced to fork ANTLR since there is a call + // to System.exit() and there is nothing we can do + // right now to avoid this. :-( (SBa) + // I'm not removing this method to keep backward compatibility + /** + * @ant.attribute ignore="true" + * @param s a <code>boolean</code> value + */ + public void setFork(boolean s) { + //this.fork = s; + } + + /** + * The working directory of the process + * @param d the working directory + */ + public void setDir(File d) { + this.workingdir = d; + } + + /** + * Adds a classpath to be set + * because a directory might be given for Antlr debug. + * @return a path to be configured + */ + public Path createClasspath() { + return commandline.createClasspath(getProject()).createPath(); + } + + /** + * Adds a new JVM argument. + * @return create a new JVM argument so that any argument can be passed to the JVM. + * @see #setFork(boolean) + */ + public Commandline.Argument createJvmarg() { + return commandline.createVmArgument(); + } + + /** + * Adds the jars or directories containing Antlr + * this should make the forked JVM work without having to + * specify it directly. + * @throws BuildException on error + */ + public void init() throws BuildException { + addClasspathEntry("/antlr/ANTLRGrammarParseBehavior.class"); + } + + /** + * Search for the given resource and add the directory or archive + * that contains it to the classpath. + * + * <p>Doesn't work for archives in JDK 1.1 as the URL returned by + * getResource doesn't contain the name of the archive.</p> + * @param resource the resource name to search for + */ + protected void addClasspathEntry(String resource) { + /* + * pre Ant 1.6 this method used to call getClass().getResource + * while Ant 1.6 will call ClassLoader.getResource(). + * + * The difference is that Class.getResource expects a leading + * slash for "absolute" resources and will strip it before + * delegating to ClassLoader.getResource - so we now have to + * emulate Class's behavior. + */ + if (resource.startsWith("/")) { + resource = resource.substring(1); + } else { + resource = "org/apache/tools/ant/taskdefs/optional/" + + resource; + } + + File f = LoaderUtils.getResourceSource(getClass().getClassLoader(), + resource); + if (f != null) { + log("Found " + f.getAbsolutePath(), Project.MSG_DEBUG); + createClasspath().setLocation(f); + } else { + log("Couldn\'t find " + resource, Project.MSG_VERBOSE); + } + } + + /** + * Execute the task. + * @throws BuildException on error + */ + public void execute() throws BuildException { + validateAttributes(); + + //TODO: use ANTLR to parse the grammar file to do this. + File generatedFile = getGeneratedFile(); + boolean targetIsOutOfDate = + targetFile.lastModified() > generatedFile.lastModified(); + boolean superGrammarIsOutOfDate = superGrammar != null + && (superGrammar.lastModified() > generatedFile.lastModified()); + if (targetIsOutOfDate || superGrammarIsOutOfDate) { + if (targetIsOutOfDate) { + log("Compiling " + targetFile + " as it is newer than " + + generatedFile, Project.MSG_VERBOSE); + } else { + log("Compiling " + targetFile + " as " + superGrammar + + " is newer than " + generatedFile, Project.MSG_VERBOSE); + } + populateAttributes(); + commandline.createArgument().setValue(targetFile.toString()); + + log(commandline.describeCommand(), Project.MSG_VERBOSE); + int err = run(commandline.getCommandline()); + if (err != 0) { + throw new BuildException("ANTLR returned: " + err, getLocation()); + } else { + String output = bos.toString(); + if (output.indexOf("error:") > -1) { + throw new BuildException("ANTLR signaled an error: " + + output, getLocation()); + } + } + } else { + log("Skipped grammar file. Generated file " + generatedFile + + " is newer.", Project.MSG_VERBOSE); + } + } + + /** + * A refactored method for populating all the command line arguments based + * on the user-specified attributes. + */ + private void populateAttributes() { + commandline.createArgument().setValue("-o"); + commandline.createArgument().setValue(outputDirectory.toString()); + if (superGrammar != null) { + commandline.createArgument().setValue("-glib"); + commandline.createArgument().setValue(superGrammar.toString()); + } + if (html) { + commandline.createArgument().setValue("-html"); + } + if (diagnostic) { + commandline.createArgument().setValue("-diagnostic"); + } + if (trace) { + commandline.createArgument().setValue("-trace"); + } + if (traceParser) { + commandline.createArgument().setValue("-traceParser"); + } + if (traceLexer) { + commandline.createArgument().setValue("-traceLexer"); + } + if (traceTreeWalker) { + if (is272()) { + commandline.createArgument().setValue("-traceTreeParser"); + } else { + commandline.createArgument().setValue("-traceTreeWalker"); + } + } + if (debug) { + commandline.createArgument().setValue("-debug"); + } + } + + private void validateAttributes() throws BuildException { + if (targetFile == null || !targetFile.isFile()) { + throw new BuildException("Invalid target: " + targetFile); + } + + // if no output directory is specified, used the target's directory + if (outputDirectory == null) { + setOutputdirectory(new File(targetFile.getParent())); + } + if (!outputDirectory.isDirectory()) { + throw new BuildException("Invalid output directory: " + outputDirectory); + } + } + + private File getGeneratedFile() throws BuildException { + String generatedFileName = null; + try { + BufferedReader in = new BufferedReader(new FileReader(targetFile)); + String line; + while ((line = in.readLine()) != null) { + int extendsIndex = line.indexOf(" extends "); + if (line.startsWith("class ") && extendsIndex > -1) { + generatedFileName = line.substring( + "class ".length(), extendsIndex).trim(); + break; + } + } + in.close(); + } catch (Exception e) { + throw new BuildException("Unable to determine generated class", e); + } + if (generatedFileName == null) { + throw new BuildException("Unable to determine generated class"); + } + return new File(outputDirectory, generatedFileName + + (html ? ".html" : ".java")); + } + + /** execute in a forked VM */ + private int run(String[] command) throws BuildException { + PumpStreamHandler psh = + new PumpStreamHandler(new LogOutputStream(this, Project.MSG_INFO), + new TeeOutputStream( + new LogOutputStream(this, + Project.MSG_WARN), + bos) + ); + Execute exe = new Execute(psh, null); + exe.setAntRun(getProject()); + if (workingdir != null) { + exe.setWorkingDirectory(workingdir); + } + exe.setCommandline(command); + try { + return exe.execute(); + } catch (IOException e) { + throw new BuildException(e, getLocation()); + } finally { + FileUtils.close(bos); + } + } + + /** + * Whether the antlr version is 2.7.2 (or higher). + * + * @return true if the version of Antlr present is 2.7.2 or later. + * @since Ant 1.6 + */ + protected boolean is272() { + AntClassLoader l = null; + try { + l = getProject().createClassLoader(commandline.getClasspath()); + l.loadClass("antlr.Version"); + return true; + } catch (ClassNotFoundException e) { + return false; + } finally { + if (l != null) { + l.cleanup(); + } + } + } +} |