diff options
Diffstat (limited to 'antlr-3.4/antlr3-maven-plugin/src/main/java/org/antlr/mojo/antlr3/Antlr3Mojo.java')
-rw-r--r-- | antlr-3.4/antlr3-maven-plugin/src/main/java/org/antlr/mojo/antlr3/Antlr3Mojo.java | 493 |
1 files changed, 493 insertions, 0 deletions
diff --git a/antlr-3.4/antlr3-maven-plugin/src/main/java/org/antlr/mojo/antlr3/Antlr3Mojo.java b/antlr-3.4/antlr3-maven-plugin/src/main/java/org/antlr/mojo/antlr3/Antlr3Mojo.java new file mode 100644 index 0000000..e7225d3 --- /dev/null +++ b/antlr-3.4/antlr3-maven-plugin/src/main/java/org/antlr/mojo/antlr3/Antlr3Mojo.java @@ -0,0 +1,493 @@ +/** +[The "BSD licence"] + +ANTLR - Copyright (c) 2005-2008 Terence Parr +Maven Plugin - Copyright (c) 2009 Jim Idle + +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright +notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote products +derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/* ======================================================================== + * This is the definitive ANTLR3 Mojo set. All other sets are belong to us. + */ +package org.antlr.mojo.antlr3; + +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.project.MavenProject; + +import java.io.File; +import java.io.IOException; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; +import org.antlr.Tool; +import org.antlr.runtime.RecognitionException; +import org.apache.maven.plugin.logging.Log; +import org.codehaus.plexus.compiler.util.scan.InclusionScanException; +import org.codehaus.plexus.compiler.util.scan.SimpleSourceInclusionScanner; +import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner; +import org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping; +import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping; + +/** + * Goal that picks up all the ANTLR grammars in a project and moves those that + * are required for generation of the compilable sources into the location + * that we use to compile them, such as target/generated-sources/antlr3 ... + * + * @goal antlr + * + * @phase process-sources + * @requiresDependencyResolution compile + * @requiresProject true + * + * @author <a href="mailto:jimi@temporal-wave.com">Jim Idle</a> + */ +public class Antlr3Mojo + extends AbstractMojo { + + // First, let's deal with the options that the ANTLR tool itself + // can be configured by. + // + /** + * If set to true, then after the tool has processed an input grammar file + * it will report various statistics about the parser, such as information + * on cyclic DFAs, which rules may use backtracking, and so on. + * + * @parameter default-value="false" + */ + protected boolean report; + /** + * If set to true, then the ANTLR tool will print a version of the input + * grammar which is devoid of any actions that may be present in the input file. + * + * @parameter default-value="false" + */ + protected boolean printGrammar; + /** + * If set to true, then the code generated by the ANTLR code generator will + * be set to debug mode. This means that when run, the code will 'hang' and + * wait for a debug connection on a TCP port (49100 by default). + * + * @parameter default-value="false" + */ + protected boolean debug; + /** + * If set to true, then then the generated parser will compute and report on + * profile information at runtime. + * + * @parameter default-value="false" + */ + protected boolean profile; + /** + * If set to true then the ANTLR tool will generate a description of the nfa + * for each rule in <a href="http://www.graphviz.org">Dot format</a> + * + * @parameter default-value="false" + */ + protected boolean nfa; + /** + * If set to true then the ANTLR tool will generate a description of the DFA + * for each decision in the grammar in <a href="http://www.graphviz.org">Dot format</a> + * + * @parameter default-value="false" + */ + protected boolean dfa; + /** + * If set to true, the generated parser code will log rule entry and exit points + * to stdout as an aid to debugging. + * + * @parameter default-value="false" + */ + protected boolean trace; + /** + * If this parameter is set, it indicates that any warning or error messages returned + * by ANLTR, should be formatted in the specified way. Currently, ANTLR supports the + * built-in formats of antlr, gnu and vs2005. + * + * @parameter default-value="antlr" + */ + protected String messageFormat; + /** + * If this parameter is set to true, then ANTLR will report all sorts of things + * about what it is doing such as the names of files and the version of ANTLR and so on. + * + * @parameter default-value="true" + */ + protected boolean verbose; + + /** + * The number of alts, beyond which ANTLR will not generate a switch statement + * for the DFA. + * + * @parameter default-value="300" + */ + private int maxSwitchCaseLabels; + + /** + * The number of alts, below which ANTLR will not choose to generate a switch + * statement over an if statement. + */ + private int minSwitchAlts; + + /* -------------------------------------------------------------------- + * The following are Maven specific parameters, rather than specificlly + * options that the ANTLR tool can use. + */ + /** + * Provides an explicit list of all the grammars that should + * be included in the generate phase of the plugin. Note that the plugin + * is smart enough to realize that imported grammars should be included but + * not acted upon directly by the ANTLR Tool. + * + * Unless otherwise specified, the include list scans for and includes all + * files that end in ".g" in any directory beneath src/main/antlr3. Note that + * this version of the plugin looks for the directory antlr3 and not the directory + * antlr, so as to avoid clashes and confusion for projects that use both v2 and v3 grammars + * such as ANTLR itself. + * + * @parameter + */ + protected Set includes = new HashSet(); + /** + * Provides an explicit list of any grammars that should be excluded from + * the generate phase of the plugin. Files listed here will not be sent for + * processing by the ANTLR tool. + * + * @parameter + */ + protected Set excludes = new HashSet(); + /** + * @parameter expression="${project}" + * @required + * @readonly + */ + protected MavenProject project; + /** + * Specifies the Antlr directory containing grammar files. For + * antlr version 3.x we default this to a directory in the tree + * called antlr3 because the antlr directory is occupied by version + * 2.x grammars. + * + * @parameter default-value="${basedir}/src/main/antlr3" + * @required + */ + private File sourceDirectory; + /** + * Location for generated Java files. For antlr version 3.x we default + * this to a directory in the tree called antlr3 because the antlr + * directory is occupied by version 2.x grammars. + * + * @parameter default-value="${project.build.directory}/generated-sources/antlr3" + * @required + */ + private File outputDirectory; + /** + * Location for imported token files, e.g. <code>.tokens</code> and imported grammars. + * Note that ANTLR will not try to process grammars that it finds to be imported + * into other grammars (in the same processing session). + * + * @parameter default-value="${basedir}/src/main/antlr3/imports" + */ + private File libDirectory; + + public File getSourceDirectory() { + return sourceDirectory; + } + + public File getOutputDirectory() { + return outputDirectory; + } + + public File getLibDirectory() { + return libDirectory; + } + + void addSourceRoot(File outputDir) { + project.addCompileSourceRoot(outputDir.getPath()); + } + /** + * An instance of the ANTLR tool build + */ + protected Tool tool; + + /** + * The main entry point for this Mojo, it is responsible for converting + * ANTLR 3.x grammars into the target language specified by the grammar. + * + * @throws org.apache.maven.plugin.MojoExecutionException When something is discovered such as a missing source + * @throws org.apache.maven.plugin.MojoFailureException When something really bad happens such as not being able to create the ANTLR Tool + */ + public void execute() + throws MojoExecutionException, MojoFailureException { + + Log log = getLog(); + + // Check to see if the user asked for debug information, then dump all the + // parameters we have picked up if they did. + // + if (log.isDebugEnabled()) { + + // Excludes + // + for (String e : (Set<String>) excludes) { + + log.debug("ANTLR: Exclude: " + e); + } + + // Includes + // + for (String e : (Set<String>) includes) { + + log.debug("ANTLR: Include: " + e); + } + + // Output location + // + log.debug("ANTLR: Output: " + outputDirectory); + + // Library directory + // + log.debug("ANTLR: Library: " + libDirectory); + + // Flags + // + log.debug("ANTLR: report : " + report); + log.debug("ANTLR: printGrammar : " + printGrammar); + log.debug("ANTLR: debug : " + debug); + log.debug("ANTLR: profile : " + profile); + log.debug("ANTLR: nfa : " + nfa); + log.debug("ANTLR: dfa : " + dfa); + log.debug("ANTLR: trace : " + trace); + log.debug("ANTLR: messageFormat : " + messageFormat); + log.debug("ANTLR: maxSwitchCaseLabels : " + maxSwitchCaseLabels); + log.debug("ANTLR: minSwitchAlts : " + minSwitchAlts); + log.debug("ANTLR: verbose : " + verbose); + } + + // Ensure that the output directory path is all in tact so that + // ANTLR can just write into it. + // + File outputDir = getOutputDirectory(); + + if (!outputDir.exists()) { + outputDir.mkdirs(); + } + + // First thing we need is an instance of the ANTLR 3.1 build tool + // + try { + // ANTLR Tool buld interface + // + tool = new Tool(); + } catch (Exception e) { + log.error("The attempt to create the ANTLR build tool failed, see exception report for details"); + + throw new MojoFailureException("Jim failed you!"); + } + + // Next we need to set the options given to us in the pom into the + // tool instance we have created. + // + tool.setDebug(debug); + tool.setGenerate_DFA_dot(dfa); + tool.setGenerate_NFA_dot(nfa); + tool.setProfile(profile); + tool.setReport(report); + tool.setPrintGrammar(printGrammar); + tool.setTrace(trace); + tool.setVerbose(verbose); + tool.setMessageFormat(messageFormat); + tool.setMaxSwitchCaseLabels(maxSwitchCaseLabels); + tool.setMinSwitchAlts(minSwitchAlts); + + // Where do we want ANTLR to produce its output? (Base directory) + // + if (log.isDebugEnabled()) + { + log.debug("Output directory base will be " + outputDirectory.getAbsolutePath()); + } + tool.setOutputDirectory(outputDirectory.getAbsolutePath()); + + // Tell ANTLR that we always want the output files to be produced in the output directory + // using the same relative path as the input file was to the input directory. + // + tool.setForceRelativeOutput(true); + + // Where do we want ANTLR to look for .tokens and import grammars? + // + tool.setLibDirectory(libDirectory.getAbsolutePath()); + + if (!sourceDirectory.exists()) { + if (log.isInfoEnabled()) { + log.info("No ANTLR grammars to compile in " + sourceDirectory.getAbsolutePath()); + } + return; + } else { + if (log.isInfoEnabled()) { + log.info("ANTLR: Processing source directory " + sourceDirectory.getAbsolutePath()); + } + } + + // Set working directory for ANTLR to be the base source directory + // + tool.setInputDirectory(sourceDirectory.getAbsolutePath()); + + try { + + // Now pick up all the files and process them with the Tool + // + processGrammarFiles(sourceDirectory, outputDirectory); + + } catch (InclusionScanException ie) { + + log.error(ie); + throw new MojoExecutionException("Fatal error occured while evaluating the names of the grammar files to analyze"); + + } catch (Exception e) { + + getLog().error(e); + throw new MojoExecutionException(e.getMessage()); + } + + + + tool.process(); + + // If any of the grammar files caused errors but did nto throw exceptions + // then we should have accumulated errors in the counts + // + if (tool.getNumErrors() > 0) { + throw new MojoExecutionException("ANTLR caught " + tool.getNumErrors() + " build errors."); + } + + // All looks good, so we need to tel Maven about the sources that + // we just created. + // + if (project != null) { + // Tell Maven that there are some new source files underneath + // the output directory. + // + addSourceRoot(this.getOutputDirectory()); + } + + } + + + /** + * + * @param sourceDirectory + * @param outputDirectory + * @throws antlr.TokenStreamException + * @throws antlr.RecognitionException + * @throws java.io.IOException + * @throws org.codehaus.plexus.compiler.util.scan.InclusionScanException + */ + private void processGrammarFiles(File sourceDirectory, File outputDirectory) + throws RecognitionException, IOException, InclusionScanException { + // Which files under the source set should we be looking for as grammar files + // + SourceMapping mapping = new SuffixMapping("g", Collections.EMPTY_SET); + + // What are the sets of includes (defaulted or otherwise). + // + Set includes = getIncludesPatterns(); + + // Now, to the excludes, we need to add the imports directory + // as this is autoscanned for importd grammars and so is auto-excluded from the + // set of gramamr fiels we shuold be analyzing. + // + excludes.add("imports/**"); + + SourceInclusionScanner scan = new SimpleSourceInclusionScanner(includes, excludes); + + scan.addSourceMapping(mapping); + Set grammarFiles = scan.getIncludedSources(sourceDirectory, null); + + if (grammarFiles.isEmpty()) { + if (getLog().isInfoEnabled()) { + getLog().info("No grammars to process"); + } + } else { + + // Tell the ANTLR tool that we want sorted build mode + // + tool.setMake(true); + + // Iterate each grammar file we were given and add it into the tool's list of + // grammars to process. + // + for (File grammar : (Set<File>) grammarFiles) { + + if (getLog().isDebugEnabled()) { + getLog().debug("Grammar file '" + grammar.getPath() + "' detected."); + } + + + String relPath = findSourceSubdir(sourceDirectory, grammar.getPath()) + grammar.getName(); + + if (getLog().isDebugEnabled()) { + getLog().debug(" ... relative path is: " + relPath); + } + tool.addGrammarFile(relPath); + + } + + } + + + } + + public Set getIncludesPatterns() { + if (includes == null || includes.isEmpty()) { + return Collections.singleton("**/*.g"); + } + return includes; + } + + /** + * Given the source directory File object and the full PATH to a + * grammar, produce the path to the named grammar file in relative + * terms to the sourceDirectory. This will then allow ANTLR to + * produce output relative to the base of the output directory and + * reflect the input organization of the grammar files. + * + * @param sourceDirectory The source directory File object + * @param grammarFileName The full path to the input grammar file + * @return The path to the grammar file relative to the source directory + */ + private String findSourceSubdir(File sourceDirectory, String grammarFileName) { + String srcPath = sourceDirectory.getPath() + File.separator; + + if (!grammarFileName.startsWith(srcPath)) { + throw new IllegalArgumentException("expected " + grammarFileName + " to be prefixed with " + sourceDirectory); + } + + File unprefixedGrammarFileName = new File(grammarFileName.substring(srcPath.length())); + + return unprefixedGrammarFileName.getParent() + File.separator; + } +} |