Author: pawelz Date: Tue Oct 13 10:29:03 2009 GMT Module: packages Tag: HEAD ---- Log message: - ant task for antlrr3 - from http://antlr.org/share/1169924912745/antlr3-task.zip
---- Files affected: packages/antlr3: ANTLR3.java (NONE -> 1.1) (NEW) ---- Diffs: ================================================================ Index: packages/antlr3/ANTLR3.java diff -u /dev/null packages/antlr3/ANTLR3.java:1.1 --- /dev/null Tue Oct 13 12:29:03 2009 +++ packages/antlr3/ANTLR3.java Tue Oct 13 12:28:58 2009 @@ -0,0 +1,776 @@ +/* + * Copyright 2000-2004 The Apache Software Foundation + * + * Licensed 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. + * + * 2006-12-29: Modified to work for antlr3 by J�rgen Pfundt + * 2007-01-04: Some minor correction after checking code with findBugs tool + * 2007-02-10: Adapted the grammar type recognition to the changed naming + * conventions for Tree Parser + * 2007-10-17: Options "trace", "traceLexer", "traceParser" and "glib" emit + * warnings when being used. + * Added recognition of "parser grammar T". + * Added options "nocollapse", "noprune". + * ANTLR option "depend" is being used to resolve build dependencies. + * 2007-11-15: Embedded Classpath statement had not been observed + * with option depend="true" (Reported by Mats Behre) + * 2008-03-31: Support the option conversiontimeout. (Jim Idle) + * 2007-12-31: With option "depend=true" proceed even if first pass failed so + * that ANTLR can spit out its errors + * 2008-08-09: Inspecting environment variable ANTLR_HOME to detect and add + * antlr- and stringtemplate libraries to the classpath + * 2008-08-09: Removed routine checkGenerateFile. It got feeble with the + * introduction of composed grammars, e.g. "import T.g" and after + * a short struggle it started it's journey to /dev/null. + * From now one it is always antlr itself via the depend option + * which decides about dependecies + * 2008-08-19: Dependency check for composed grammars added. + * Might need some further improvements. + */ +package org.apache.tools.ant.antlr; + +import java.util.regex.*; +import java.io.*; +import java.util.Map; +import org.apache.tools.ant.BuildException; +import org.apache.tools.ant.DirectoryScanner; +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.Redirector; +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.JavaEnvUtils; +import org.apache.tools.ant.util.LoaderUtils; +import org.apache.tools.ant.util.TeeOutputStream; +import org.apache.tools.ant.util.FileUtils; + +/** + * Invokes the ANTLR3 Translator generator on a grammar file. + * + */ +public class ANTLR3 extends Task { + + private CommandlineJava commandline = new CommandlineJava(); + /** the file to process */ + private File target = null; + /** where to output the result */ + private File outputDirectory = null; + /** location of token files */ + private File libDirectory = null; + /** an optional super grammar file */ + private File superGrammar; + /** depend */ + private boolean depend = false; + /** fork */ + private boolean fork; + /** name of output style for messages */ + private String messageFormatName; + /** optional flag to print out a diagnostic file */ + private boolean diagnostic; + /** optional flag to add 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; + /** working directory */ + private File workingdir = null; + /** captures ANTLR's output */ + private ByteArrayOutputStream bos = new ByteArrayOutputStream(); + /** The debug attribute */ + private boolean debug; + /** The report attribute */ + private boolean report; + /** The print attribute */ + private boolean print; + /** The profile attribute */ + private boolean profile; + /** The nfa attribute */ + private boolean nfa; + /** The dfa attribute */ + private boolean dfa; + /** multi threaded analysis */ + private boolean multiThreaded; + /** collapse incident edges into DFA states */ + private boolean nocollapse; + /** test lookahead against EBNF block exit branches */ + private boolean noprune; + /** put tags at start/stop of all templates in output */ + private boolean dbgST; + /** print AST */ + private boolean grammarTree; + /** Instance of a utility class to use for file operations. */ + private FileUtils fileUtils; + /** + * Whether to override the default conversion timeout with -Xconversiontimeout nnnn + */ + private String conversiontimeout; + + public ANTLR3() { + commandline.setVm(JavaEnvUtils.getJreExecutable("java")); + commandline.setClassname("org.antlr.Tool"); + fileUtils = FileUtils.getFileUtils(); + } + + /** + * The grammar file to process. + */ + public void setTarget(File targetFile) { + log("Setting target to: " + targetFile.toString(), Project.MSG_VERBOSE); + this.target = targetFile; + } + + /** + * The directory to write the generated files to. + */ + public void setOutputdirectory(File outputDirectoryFile) { + log("Setting output directory to: " + outputDirectoryFile.toString(), Project.MSG_VERBOSE); + this.outputDirectory = outputDirectoryFile; + } + + /** + * The directory to write the generated files to. + */ + public File getOutputdirectory() { + return outputDirectory; + } + + /** + * The token files output directory. + */ + public void setLibdirectory(File libDirectoryFile) { + log("Setting lib directory to: " + libDirectoryFile.toString(), Project.MSG_VERBOSE); + this.libDirectory = libDirectoryFile; + } + + /** + * The output style for messages. + */ + public void setMessageformat(String name) { + log("Setting message-format to: " + name, Project.MSG_VERBOSE); + this.messageFormatName = name; + } + + /** + * Sets an optional super grammar file + * @deprecated + */ + public void setGlib(File superGrammarFile) { + this.superGrammar = superGrammarFile; + } + + /** + * Sets a flag to enable ParseView debugging + */ + public void setDebug(boolean enable) { + this.debug = enable; + } + + /** + * Sets a flag to enable report statistics + */ + public void setReport(boolean enable) { + this.report = enable; + } + + /** + * Sets a flag to print out the grammar without actions + */ + public void setPrint(boolean enable) { + this.print = enable; + } + + /** + * Sets a flag to enable profiling + */ + public void setProfile(boolean enable) { + this.profile = enable; + } + + /** + * Sets a flag to enable nfa generation + */ + public void setNfa(boolean enable) { + this.nfa = enable; + } + + /** + * Sets a flag to enable nfa generation + */ + public void setDfa(boolean enable) { + this.dfa = enable; + } + + /** + * Run the analysis multithreaded + * @param enable + */ + public void setMultithreaded(boolean enable) { + multiThreaded = enable; + } + + /** + * collapse incident edges into DFA states + * @param enable + */ + public void setNocollapse(boolean enable) { + nocollapse = enable; + } + + /** + * test lookahead against EBNF block exit branches + * @param enable + */ + public void setNoprune(boolean enable) { + noprune = enable; + } + + /** + * test lookahead against EBNF block exit branches + * @param enable + */ + public void setDbgST(boolean enable) { + dbgST = enable; + } + + /** + * override the default conversion timeout with -Xconversiontimeout nnnn + * @param conversiontimeoutString + */ + public void setConversiontimeout(String conversiontimeoutString) { + log("Setting conversiontimeout to: " + conversiontimeoutString, Project.MSG_VERBOSE); + try { + int timeout = Integer.valueOf(conversiontimeoutString); + this.conversiontimeout = conversiontimeoutString; + } catch (NumberFormatException e) { + log("Option ConversionTimeOut ignored due to illegal value: '" + conversiontimeoutString + "'", Project.MSG_ERR); + } + } + + /** + * Set a flag to enable printing of the grammar tree + */ + public void setGrammartree(boolean enable) { + grammarTree = enable; + } + + /** + * Set a flag to enable dependency checking by ANTLR itself + * The depend option is always used implicitely inside the antlr3 task + * @deprecated + */ + public void setDepend(boolean s) { + this.depend = s; + } + + /** + * Sets a flag to emit diagnostic text + */ + public void setDiagnostic(boolean enable) { + diagnostic = enable; + } + + /** + * If true, enables all tracing. + * @deprecated + */ + public void setTrace(boolean enable) { + trace = enable; + } + + /** + * If true, enables parser tracing. + * @deprecated + */ + public void setTraceParser(boolean enable) { + traceParser = enable; + } + + /** + * If true, enables lexer tracing. + * @deprecated + */ + public void setTraceLexer(boolean enable) { + traceLexer = 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" + */ + public void setFork(boolean s) { + this.fork = s; + } + + /** + * The working directory of the process + */ + public void setDir(File d) { + this.workingdir = d; + } + + /** + * Adds a classpath to be set + * because a directory might be given for Antlr debug. + */ + 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 and associates. + * This should make the forked JVM work without having to + * specify it directly. + */ + @Override + public void init() throws BuildException { + /* Inquire environment variables */ + Map<String, String> variables = System.getenv(); + /* Get value for key "ANTLR_HOME" which should hopefully point to + * the directory where the current version of antlr3 is installed */ + String antlrHome = variables.get("ANTLR_HOME"); + if (antlrHome != null) { + /* Environment variable ANTLR_HOME has been defined. + * Now add all antlr and stringtemplate libraries to the + * classpath */ + addAntlrJarsToClasspath(antlrHome + "/lib"); + } + addClasspathEntry("/antlr/ANTLRGrammarParseBehavior.class", "AntLR2"); + addClasspathEntry("/org/antlr/tool/ANTLRParser.class", "AntLR3"); + addClasspathEntry("/org/antlr/stringtemplate/StringTemplate.class", "Stringtemplate"); + + + } + + /** + * 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> + */ + protected void addClasspathEntry(String resource, String msg) { + /* + * 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 via classpath: " + f.getAbsolutePath(), Project.MSG_VERBOSE); + createClasspath().setLocation(f); + } else { + log("Couldn\'t find resource " + resource + " for library " + msg + " in external classpath", Project.MSG_VERBOSE); + } + } + + /** + * If the environment variable ANTLR_HOME is defined and points + * to the installation directory of antlr3 then look for all antlr-*.jar and + * stringtemplate-*.jar files in the lib directory and add them + * to the classpath. + * This feature should make working with eclipse or netbeans projects a + * little bit easier. As wildcards are being used for the version part + * of the jar-archives it makes the task independent of + * new releases. Just let ANTLR_HOME point to the new installation + * directory. + */ + private void addAntlrJarsToClasspath(String antlrLibDir) { + String[] includes = {"antlr-*.jar", "stringtemplate-*.jar"}; + + DirectoryScanner ds = new DirectoryScanner(); + ds.setIncludes(includes); + ds.setBasedir(new File(antlrLibDir)); + ds.setCaseSensitive(true); + ds.scan(); + + String separator = System.getProperty("file.separator"); + String[] files = ds.getIncludedFiles(); + for (String file : files) { + File f = new File(antlrLibDir + separator + file); + log("Found via ANTLR_HOME: " + f.getAbsolutePath(), Project.MSG_VERBOSE); + createClasspath().setLocation(f); + } + } + + @Override + public void execute() throws BuildException { + + validateAttributes(); + + // Use ANTLR itself to resolve dependencies and decide whether + // to invoke ANTLR for compilation + if (dependencyCheck()) { + populateAttributes(); + commandline.createArgument().setValue(target.toString()); + + log(commandline.describeCommand(), Project.MSG_VERBOSE); + int err = 0; + try { + err = run(commandline.getCommandline(), new LogOutputStream(this, Project.MSG_INFO), new LogOutputStream(this, Project.MSG_WARN)); + } catch (IOException e) { + throw new BuildException(e, getLocation()); + } finally { + try { + bos.close(); + } catch (IOException e) { + // ignore + } + } + + if (err != 0) { + throw new BuildException("ANTLR returned: " + err, getLocation()); + } else { + Pattern p = Pattern.compile("error\\([0-9]+\\):"); + Matcher m = p.matcher(bos.toString()); + if (m.find()) { + throw new BuildException("ANTLR signaled an error.", getLocation()); + } + } + } else { + try { + log("All dependencies of grammar file \'" + target.getCanonicalPath() + "\' are up to date.", Project.MSG_VERBOSE); + } catch (IOException ex) { + log("All dependencies of grammar file \'" + target.toString() + "\' are up to date.", 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()); + + commandline.createArgument().setValue("-lib"); + commandline.createArgument().setValue(libDirectory.toString()); + + if (superGrammar != null) { + log("Option 'glib' is not supported by ANTLR v3. Option ignored!", Project.MSG_WARN); + } + + if (diagnostic) { + commandline.createArgument().setValue("-diagnostic"); + } + if (depend) { + log("Option 'depend' is implicitely always used by ANTLR v3. Option can safely be omitted!", Project.MSG_WARN); + } + if (trace) { + log("Option 'trace' is not supported by ANTLR v3. Option ignored!", Project.MSG_WARN); + } + if (traceParser) { + log("Option 'traceParser' is not supported by ANTLR v3. Option ignored!", Project.MSG_WARN); + } + if (traceLexer) { + log("Option 'traceLexer' is not supported by ANTLR v3. Option ignored!", Project.MSG_WARN); + } + if (debug) { + commandline.createArgument().setValue("-debug"); + } + if (report) { + commandline.createArgument().setValue("-report"); + } + if (print) { + commandline.createArgument().setValue("-print"); + } + if (profile) { + commandline.createArgument().setValue("-profile"); + } + if (messageFormatName != null) { + commandline.createArgument().setValue("-message-format"); + commandline.createArgument().setValue(messageFormatName); + } + if (nfa) { + commandline.createArgument().setValue("-nfa"); + } + if (dfa) { + commandline.createArgument().setValue("-dfa"); + } + if (multiThreaded) { + commandline.createArgument().setValue("-Xmultithreaded"); + } + if (nocollapse) { + commandline.createArgument().setValue("-Xnocollapse"); + } + if (noprune) { + commandline.createArgument().setValue("-Xnoprune"); + } + if (dbgST) { + commandline.createArgument().setValue("-XdbgST"); + } + if (conversiontimeout != null) { + commandline.createArgument().setValue("-Xconversiontimeout"); + commandline.createArgument().setValue(conversiontimeout); + } + if (grammarTree) { + commandline.createArgument().setValue("-Xgrtree"); + } + } + + private void validateAttributes() throws BuildException { + + if (target == null) { + throw new BuildException("No target grammar, lexer grammar or tree parser specified!"); + } else if (!target.isFile()) { + throw new BuildException("Target: " + target + " is not a file!"); + } + + // if no output directory is specified, use the target's directory + if (outputDirectory == null) { + setOutputdirectory(new File(target.getParent())); + } + + if (!outputDirectory.isDirectory()) { + throw new BuildException("Invalid output directory: " + outputDirectory); + } + + if (workingdir != null && !workingdir.isDirectory()) { + throw new BuildException("Invalid working directory: " + workingdir); + } + + // if no libDirectory is specified, use the target's directory + if (libDirectory == null) { + setLibdirectory(new File(target.getParent())); + } + + if (!libDirectory.isDirectory()) { + throw new BuildException("Invalid lib directory: " + libDirectory); + } + } + + private boolean dependencyCheck() throws BuildException { + // using "antlr -o <OutputDirectory> -lib <LibDirectory> -depend <T>" + // to get the list of dependencies + CommandlineJava cmdline; + try { + cmdline = (CommandlineJava) commandline.clone(); + } catch (java.lang.CloneNotSupportedException e) { + throw new BuildException("Clone of commandline failed: " + e); + } + + cmdline.createArgument().setValue("-depend"); + cmdline.createArgument().setValue("-o"); <<Diff was trimmed, longer than 597 lines>>
_______________________________________________ pld-cvs-commit mailing list [email protected] http://lists.pld-linux.org/mailman/listinfo/pld-cvs-commit
