diff --git a/.gitignore b/.gitignore index d18dd136b..be3e7544c 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,5 @@ /tool/target/ /runtime/Java/target/ /gunit/target/ -*.hprof \ No newline at end of file +*.hprof +/antlr4-maven-plugin/target/ \ No newline at end of file diff --git a/antlr4-maven-plugin/.classpath b/antlr4-maven-plugin/.classpath new file mode 100644 index 000000000..595a5bf4f --- /dev/null +++ b/antlr4-maven-plugin/.classpath @@ -0,0 +1,7 @@ + + + + + + + diff --git a/antlr4-maven-plugin/.project b/antlr4-maven-plugin/.project new file mode 100644 index 000000000..1aedcc067 --- /dev/null +++ b/antlr4-maven-plugin/.project @@ -0,0 +1,23 @@ + + + antlr4-maven-plugin + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/antlr4-maven-plugin/.settings/org.eclipse.core.resources.prefs b/antlr4-maven-plugin/.settings/org.eclipse.core.resources.prefs new file mode 100644 index 000000000..99f26c020 --- /dev/null +++ b/antlr4-maven-plugin/.settings/org.eclipse.core.resources.prefs @@ -0,0 +1,2 @@ +eclipse.preferences.version=1 +encoding/=UTF-8 diff --git a/antlr4-maven-plugin/.settings/org.eclipse.jdt.core.prefs b/antlr4-maven-plugin/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 000000000..60105c1b9 --- /dev/null +++ b/antlr4-maven-plugin/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.6 +org.eclipse.jdt.core.compiler.compliance=1.6 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.6 diff --git a/antlr4-maven-plugin/.settings/org.eclipse.m2e.core.prefs b/antlr4-maven-plugin/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 000000000..f897a7f1c --- /dev/null +++ b/antlr4-maven-plugin/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/antlr4-maven-plugin/pom.xml b/antlr4-maven-plugin/pom.xml new file mode 100644 index 000000000..16bcf122b --- /dev/null +++ b/antlr4-maven-plugin/pom.xml @@ -0,0 +1,361 @@ + + + + + + + + 4.0.0 + + + org.antlr + + + + antlr4-maven-plugin + maven-plugin + + + 4.0-SNAPSHOT + Maven plugin for ANTLR V4 + + 3.0 + + + + http://antlr.org + + + UTF-8 + + + + +This is the brand new, re-written from scratch plugin for ANTLR v4. + +Previous valiant efforts all suffered from being unable to modify the ANTLR Tool +itself to provide support not just for Maven oriented things but any other tool +that might wish to invoke ANTLR without resorting to the command line interface. + +Rather than try to shoe-horn new code into the existing Mojo (in fact I think that +by incorporating a patch supplied by someone I ended up with tow versions of the +Mojo, I elected to rewrite everything from scratch, including the documentation, so +that we might end up with a perfect Mojo that can do everything that ANTLR v4 supports +such as imported grammar processing, proper support for library directories and +locating token files from generated sources, and so on. + +In the end I decided to also change the the ANTLR Tool.java code so that it +would be the provider of all the things that a build tool needs, rather than +delegating things to 5 different tools. So, things like dependencies, dependency +sorting, option tracking, generating sources and so on are all folded back +in to ANTLR's Tool.java code, where they belong, and they now provide a +public interface to anyone that might want to interface with them. + +One other goal of this rewrite was to completely document the whole thing +to death. Hence even this pom has more comments than funcitonal elements, +in case I get run over by a bus or fall off a cliff while skiing. + +Jim Idle - March 2009 + + + + + + + Jim Idle + http://www.temporal-wave.com + + Originator, version 4.0 + + + + + Terence Parr + http://antlr.org/wiki/display/~admin/Home + + Project lead - ANTLR + + + + + David Holroyd + http://david.holroyd.me.uk/ + + Originator - prior version + + + + + Kenny MacDermid + mailto:kenny "at" kmdconsulting.ca + + Contributor - prior versions + + + + + + + + JIRA + http://antlr.org/jira/browse/ANTLR + + + + + + repo + The BSD License + http://www.antlr.org/LICENSE.txt + + + + + + + antlr-repo + ANTLR Testing repository + scpexe://antlr.org/home/mavensync/antlr-repo + + + + antlr-snapshot + ANTLR Testing Snapshot Repository + scpexe://antlr.org/home/mavensync/antlr-snapshot + + + + antlr-repo + ANTLR Maven Plugin Web Site + scpexe://antlr.org/home/mavensync/antlr-maven-webs/antlr4-maven-plugin + + + + + + + + + antlr-snapshot + ANTLR Testing Snapshot Repository + http://antlr.org/antlr-snapshot + + true + always + + + + false + + + + + + + + 2009 + + + + http://antlr.markmail.org/ + + http://www.antlr.org/pipermail/antlr-interest/ + + ANTLR Users + http://www.antlr.org/mailman/listinfo/antlr-interest/ + http://www.antlr.org/mailman/options/antlr-interest/ + antlr-interest@antlr.org + + + + + ANTLR.org + http://www.antlr.org + + + + + + + + + org.apache.maven + maven-plugin-api + 2.0 + compile + + + + org.apache.maven + maven-project + 2.0 + + + + org.codehaus.plexus + plexus-compiler-api + 1.8.6 + + + + + org.antlr + antlr4 + 4.0-SNAPSHOT + + + + + + junit + junit + 4.10 + test + + + + + org.apache.maven.shared + maven-plugin-testing-harness + 1.1 + test + + + + + + + install + + + + org.apache.maven.wagon + wagon-ssh-external + 2.2 + + + + + + + maven-compiler-plugin + 2.3.2 + + 1.6 + 1.6 + true + true + + + + + + + + org.apache.maven.plugins + maven-site-plugin + 3.0 + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.4 + + false + + + + + org.apache.maven.plugins + maven-source-plugin + 2.1.2 + + + attach-sources + + jar + + + + + + + + + + diff --git a/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4ErrorLog.java b/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4ErrorLog.java new file mode 100644 index 000000000..1172ac798 --- /dev/null +++ b/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4ErrorLog.java @@ -0,0 +1,84 @@ +/** + [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. +*/ +package org.antlr.mojo.antlr4; + +import org.antlr.v4.tool.ANTLRMessage; +import org.antlr.v4.tool.ANTLRToolListener; +import org.apache.maven.plugin.logging.Log; + +/** + * The Maven plexus container gives us a Log logging provider + * which we can use to install an error listener for the ANTLR + * tool to report errors by. + */ +public class Antlr4ErrorLog implements ANTLRToolListener { + + private Log log; + + /** + * Instantiate an ANTLR ErrorListner that communicates any messages + * it receives to the Maven error sink. + * + * @param log The Maven Error Log + */ + public Antlr4ErrorLog(Log log) { + this.log = log; + } + + /** + * Sends an informational message to the Maven log sink. + * @param s The message to send to Maven + */ + @Override + public void info(String message) { + log.info(message); + } + + /** + * Sends an error message from ANTLR analysis to the Maven Log sink. + * + * @param message The message to send to Maven. + */ + @Override + public void error(ANTLRMessage message) { + log.error(message.toString()); + } + + /** + * Sends a warning message to the Maven log sink. + * + * @param message + */ + @Override + public void warning(ANTLRMessage message) { + log.warn(message.toString()); + } +} diff --git a/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4Mojo.java b/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4Mojo.java new file mode 100644 index 000000000..c079d4210 --- /dev/null +++ b/antlr4-maven-plugin/src/main/java/org/antlr/mojo/antlr4/Antlr4Mojo.java @@ -0,0 +1,566 @@ +/** +[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 ANTLR4 Mojo set. All other sets are belong to us. + */ +package org.antlr.mojo.antlr4; + +import antlr.RecognitionException; +import antlr.TokenStreamException; +import org.antlr.v4.Tool; +import org.antlr.v4.codegen.CodeGenerator; +import org.antlr.v4.tool.Grammar; +import org.apache.maven.plugin.AbstractMojo; +import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.MojoFailureException; +import org.apache.maven.plugin.logging.Log; +import org.apache.maven.project.MavenProject; +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; + +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileWriter; +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URI; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +/** + * 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/antlr4 ... + * + * @goal antlr + * + * @phase process-sources + * @requiresDependencyResolution compile + * @requiresProject true + * + * @author Jim Idle + */ +public class Antlr4Mojo + 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 variaous 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 atn + * for each rule in Dot format + * + * @parameter default-value="false" + */ + protected boolean atn; + /** + * 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, shoould be formatted in the specified way. Currently, ANTLR suports 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; + + protected boolean verbose_dfa; + + protected boolean force_atn; + + protected boolean abstract_recognizer; + + /** + * 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/antlr4. Note that + * this version of the plugin looks for the directory antlr4 and not the directory + * antlr, so as to avoid clashes and confusion for projects that use both v3 and v4 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 4.x we default this to a directory in the tree + * called antlr4 because the antlr3 directory is occupied by version + * 3.x grammars. + * + * @parameter default-value="${basedir}/src/main/antlr4" + * @required + */ + private File sourceDirectory; + /** + * Location for generated Java files. For antlr version 4.x we default + * this to a directory in the tree called antlr4 because the antlr + * directory is occupied by version 2.x grammars. + * + * @parameter default-value="${project.build.directory}/generated-sources/antlr4" + * @required + */ + private File outputDirectory; + /** + * Location for imported token files, e.g. .tokens 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/antlr4/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 4.x grammars into the target language specified by the grammar. + * + * @throws org.apache.maven.plugin.MojoExecutionException When something is disvocered such as a missing source + * @throws org.apache.maven.plugin.MojoFailureException When something really bad happesn such as not being able to create the ANTLR Tool + */ + @Override + 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 : excludes) { + log.debug("ANTLR: Exclude: " + e); + } + + // Includes + // + for (String e : 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: atn : " + atn); + 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(); + } + + List args = new ArrayList(); + + if (getOutputDirectory() != null) { + args.add("-o"); + args.add(outputDir.getAbsolutePath()); + } + + // Where do we want ANTLR to look for .tokens and import grammars? + // + if (getLibDirectory() != null && getLibDirectory().exists()) { + args.add("-lib"); + args.add(libDirectory.getAbsolutePath()); + } + + // Next we need to set the options given to us in the pom into the + // tool instance we have created. + // + if (debug) { + args.add("-debug"); + } + if (atn) { + args.add("-atn"); + } + if (profile) { + args.add("-profile"); + } + if (report) { + args.add("-report"); + } + if (printGrammar) { + args.add("-print"); + } + if (verbose_dfa) { + args.add("-Xverbose-dfa"); + } + if (messageFormat != null && !"".equals(messageFormat)) { + args.add("-message-format"); + args.add(messageFormat); + } + if (force_atn) { + args.add("-Xforce-atn"); + } + if (abstract_recognizer) { + args.add("-abstract"); + } + + try { + + // Now pick up all the files and process them with the Tool + // + processGrammarFiles(args, 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()); + } + + // Create an instance of the ANTLR 4 build tool + // + try { + tool = new Tool(args.toArray(new String[args.size()])) { + + @Override + public void process(Grammar g, boolean gencode) { + getLog().info("Processing grammar: " + g.fileName); + super.process(g, gencode); + } + + @Override + public Writer getOutputFileWriter(Grammar g, String fileName) throws IOException { + if (outputDirectory == null) { + return new StringWriter(); + } + // output directory is a function of where the grammar file lives + // for subdir/T.g4, you get subdir here. Well, depends on -o etc... + // But, if this is a .tokens file, then we force the output to + // be the base output directory (or current directory if there is not a -o) + // + File outputDir; + if ( fileName.endsWith(CodeGenerator.VOCAB_FILE_EXTENSION) ) { + outputDir = new File(outputDirectory); + } + else { + outputDir = getOutputDirectory(g.fileName); + } + + File outputFile = new File(outputDir, fileName); + if (!outputDir.exists()) { + outputDir.mkdirs(); + } + + URI relativePath = project.getBasedir().toURI().relativize(outputFile.toURI()); + getLog().info(" Writing file: " + relativePath); + FileWriter fw = new FileWriter(outputFile); + return new BufferedWriter(fw); + } + + }; + tool.addListener(new Antlr4ErrorLog(log)); + + // we set some options directly + tool.trace = trace; + + // Where do we want ANTLR to produce its output? (Base directory) + // + if (log.isDebugEnabled()) + { + log.debug("Output directory base will be " + 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); + + // Set working directory for ANTLR to be the base source directory + // + tool.inputDirectory = sourceDirectory; + + if (!sourceDirectory.exists()) { + if (log.isInfoEnabled()) { + log.info("No ANTLR 4 grammars to compile in " + sourceDirectory.getAbsolutePath()); + } + return; + } else { + if (log.isInfoEnabled()) { + log.info("ANTLR 4: Processing source directory " + sourceDirectory.getAbsolutePath()); + } + } + + } catch (Exception e) { + log.error("The attempt to create the ANTLR 4 build tool failed, see exception report for details", e); + + throw new MojoFailureException("Jim failed you!"); + } + + tool.processGrammarsOnCommandLine(); + + // 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 4 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(List args, File sourceDirectory, File outputDirectory) + throws TokenStreamException, RecognitionException, IOException, InclusionScanException { + // Which files under the source set should we be looking for as grammar files + // + SourceMapping mapping = new SuffixMapping("g4", 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); + @SuppressWarnings("unchecked") + Set grammarFiles = (Set)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 : 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); + } + + args.add(relPath); + + } + + } + + + } + + public Set getIncludesPatterns() { + if (includes == null || includes.isEmpty()) { + return Collections.singleton("**/*.g4"); + } + 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; + } +} diff --git a/antlr4-maven-plugin/src/site/apt/examples/import.apt b/antlr4-maven-plugin/src/site/apt/examples/import.apt new file mode 100644 index 000000000..7e71ea913 --- /dev/null +++ b/antlr4-maven-plugin/src/site/apt/examples/import.apt @@ -0,0 +1,8 @@ +Imported Grammar Files + + In order to have the ANTLR plugin automatically locate and use grammars used + as imports in your main .g4 files, you need to place the imported grammar + files in the imports directory beneath the root directory of your grammar + files (which is <<>> by default of course). + + For a default layout, place your import grammars in the directory: <<>> diff --git a/antlr4-maven-plugin/src/site/apt/examples/libraries.apt b/antlr4-maven-plugin/src/site/apt/examples/libraries.apt new file mode 100644 index 000000000..8a052242d --- /dev/null +++ b/antlr4-maven-plugin/src/site/apt/examples/libraries.apt @@ -0,0 +1,47 @@ +Libraries + + The introduction of the import directive in a grammar allows reuse of common grammar files + as well as the ability to divide up functional components of large grammars. However it has + caused some confusion in regard to the fact that generated vocab files (<<>>) can also + be searched for with the <<<>>> directive. + + This has confused two separate functions and imposes a structure upon the layout of + your grammar files in certain cases. If you have grammars that both use the import + directive and also require the use of a vocab file then you will need to locate + the grammar that generates the .tokens file alongside the grammar that uses it. This + is because you will need to use the <<<>>> directive to specify the + location of your imported grammars and ANTLR will not find any vocab files in + this directory. + + The .tokens files for any grammars are generated within the same output directory structure + as the .java files. So, whereever the .java files are generated, you will also find the .tokens + files. ANTLR looks for .tokens files in both the <<<>>> and the output directory + where it is placing the geenrated .java files. Hence when you locate the grammars that generate + .tokens files in the same source directory as the ones that use the .tokens files, then + the Maven plugin will find the expected .tokens files. + + The <<<>>> is specified like any other directory parameter in Maven. Here is an + example: + ++-- + + org.antlr + antlr4-maven-plugin + 4.0-SNAPSHOT + + + + + + + antlr + + src/main/antlr4_imports + + + + ++-- + + + diff --git a/antlr4-maven-plugin/src/site/apt/examples/simple.apt b/antlr4-maven-plugin/src/site/apt/examples/simple.apt new file mode 100644 index 000000000..aa5ef0469 --- /dev/null +++ b/antlr4-maven-plugin/src/site/apt/examples/simple.apt @@ -0,0 +1,40 @@ +Simple configuration + + If your grammar files are organized into the default locations as described in the {{{../index.html}introduction}}, + then configuring the pom.xml file for your project is as simple as adding this to it + ++-- + + + org.antlr + antlr4-maven-plugin + 4.0-SNAPSHOT + + + + antlr + + + + +... + ++-- + + When the mvn command is executed all grammar files under <<>>, except any + import grammars under <<>> will be analyzed and converted to + java source code in the output directory <<>>. + + Your input files under <<>> should be stored in sub directories that + reflect the package structure of your java parsers. If your grammar file parser.g4 contains: + ++--- +@header { +package org.jimi.themuss; +} ++--- + + Then the .g4 file should be stored in: <<>>. THis way + the generated .java files will correctly reflect the package structure in which they will + finally rest as classes. + diff --git a/antlr4-maven-plugin/src/site/apt/index.apt b/antlr4-maven-plugin/src/site/apt/index.apt new file mode 100644 index 000000000..f954e5a3a --- /dev/null +++ b/antlr4-maven-plugin/src/site/apt/index.apt @@ -0,0 +1,63 @@ + ------------- + ANTLR v4 Maven Plugin + ------------- + Jim Idle + ------------- + March 2009 + ------------- + +ANTLR v4 Maven plugin + + The ANTLR v4 Maven plugin is completely re-written as of version 4.0; if you are familiar + with prior versions, you should note that there are some behavioral differences that make + it worthwhile reading this documentation. + + The job of the plugin is essentially to tell the standard ANTLR parser generator where the + input grammar files are and where the output files should be generated. As with all Maven + plugins, there are defaults, which you are advised to comply to, but are not forced to + comply to. + + This version of the plugin allows full control over ANTLR and allows configuration of all + options that are useful for a build system. The code required to calculate dependencies, + check the build order, and otherwise work with your grammar files is built into the ANTLR + tool as of version 4.0 of ANTLR and this plugin. + +* Plugin Versioning + + The plugin version tracks the version of the ANTLR tool that it controls. Hence if you + use version 4.0 of the plugin, you will build your grammars using version 4.0 of the + ANTLR tool, version 4.2 of the plugin will use version 4.2 of the ANTLR tool and so on. + + You may also find that there are patch versions of the plugin suchas 4.0-1 4.0-2 and + so on. Use the latest patch release of the plugin. + + The current version of the plugin is shown at the top of this page after the <> date. + + +* Default directories + + As with all Maven plugins, this plugin will automatically default to standard locations + for your grammar and import files. Organizing your source code to reflect this standard + layout will greatly reduce the configuration effort required. The standard layout lookd + like this: + ++-- + src/main/ + | + +--- antlr4/... .g4 files organized in the required package structure + | + +--- imports/ .g4 files that are imported by other grammars. ++-- + + If your grammar is intended to be part of a package called org.foo.bar then you would + place it in the directory <<>>. The plugin will then produce + .java and .tokens files in the output directory <<>> + When the Java files are compiled they will be in the correct location for the javac + compiler without any special configuration. The generated java files are automatically + submitted for compilation by the plugin. + + The <<>> directory is treated in a special way. It should contain + any grammar files that are imported by other grammar files (do not make subdirectories here.) + Such files are never built on their own, but the plugin will automatically tell the ANTLR + tool to look in this directory for library files. + diff --git a/antlr4-maven-plugin/src/site/apt/usage.apt.vm b/antlr4-maven-plugin/src/site/apt/usage.apt.vm new file mode 100644 index 000000000..cff53a01d --- /dev/null +++ b/antlr4-maven-plugin/src/site/apt/usage.apt.vm @@ -0,0 +1,193 @@ +Usage + + The Maven plugin for antlr is simple to use but is at its simplest when you use the default + layouts for your grammars, as so: + ++-- + src/main/ + | + +--- antlr4/... .g4 files organized in the required package structure + | + +--- imports/ .g4 files that are imported by other grammars. ++-- + + However, if you are not able to use this structure for whatever reason, you + can configure the locations of the grammar files, where library/import files + are located and where the output files should be generated. + +* Plugin Descriptor + + The current version of the plugin is shown at the top of this page after the <> date. + + The full layout of the descriptor (at least, those parts that are not standard Maven things), + showing the default values of the configuration options, is as follows: + ++-- + + org.antlr + antlr4-maven-plugin + 4.0-SNAPSHOT + + + + + + + antlr + + 10000 + false + false + false + + + src/main/antlr4/imports + antlr + target/generated-sources/antlr4 + false + false + false + src/main/antlr4 + false + true + + + + + ++-- + + Note that you can create multiple executions, and thus build some grammars with different + options to others (such as setting the debug option for instance). + +** Configuration parameters + +*** report + + If set to true, then after the tool has processed an input grammar file + it will report variaous statistics about the parser, such as information + on cyclic DFAs, which rules may use backtracking, and so on. + + default-value="false" + +*** printGrammar + + 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. + + default-value = "false" + +*** debug + + 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). + + default-value="false" + +*** profile + + If set to true, then then the generated parser will compute and report on + profile information at runtime. + + default-value="false" + +*** nfa + + If set to true then the ANTLR tool will generate a description of the nfa + for each rule in Dot format + + default-value="false" + + protected boolean nfa; + +*** dfa + + If set to true then the ANTLR tool will generate a description of the DFA + for each decision in the grammar in Dot format + + default-value="false" + +*** trace + + If set to true, the generated parser code will log rule entry and exit points + to stdout as an aid to debugging. + + default-value="false" + +*** messageFormat + + If this parameter is set, it indicates that any warning or error messages returned + by ANLTR, shoould be formatted in the specified way. Currently, ANTLR supports the + built-in formats of antlr, gnu and vs2005. + + default-value="antlr" + +*** verbose + + 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. + + default-value="true" + +*** conversionTimeout + + The number of milliseconds ANTLR will wait for analysis of each + alternative in the grammar to complete before giving up. You may raise + this value if ANTLR gives up on a complicated alt and tells you that + there are lots of ambiguties, but you know that it just needed to spend + more time on it. Note that this is an absolute time and not CPU time. + + default-value="10000" + +*** includes + + 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 ".g4" in any directory beneath src/main/antlr4. Note that + this version of the plugin looks for the directory antlr4 and not the directory + antlr, so as to avoid clashes and confusion for projects that use both v3 and v4 grammars + such as ANTLR itself. + +*** excludes + + 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. + +*** sourceDirectory + + Specifies the Antlr directory containing grammar files. For + antlr version 4.x we default this to a directory in the tree + called antlr4 because the antlr directory is occupied by version + 2.x grammars. + + <> Take careful note that the default location for antlr grammars + is now <> and NOT <> + + default-value="<<<${basedir}/src/main/antlr4>>>" + +*** outputDirectory + + Location for generated Java files. For antlr version 4.x we default + this to a directory in the tree called antlr4 because the antlr + directory is occupied by version 2.x grammars. + + default-value="<<<${project.build.directory}/generated-sources/antlr4>>>" + +*** libDirectory + + Location for imported token files, e.g. .tokens and imported grammars. + Note that ANTLR will not try to process grammars that it finds in this directory, but + will include this directory in the search for .tokens files and import grammars. + + <> If you change the lib directory from the default but the directory is + still under<<<${basedir}/src/main/antlr4>>>, then you will need to exclude + the grammars from processing specifically, using the <<<>>> option. + + default-value="<<<${basedir}/src/main/antlr4/imports>>>" + diff --git a/antlr4-maven-plugin/src/site/site.xml b/antlr4-maven-plugin/src/site/site.xml new file mode 100644 index 000000000..96467c1a3 --- /dev/null +++ b/antlr4-maven-plugin/src/site/site.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/tool/src/org/antlr/v4/Tool.java b/tool/src/org/antlr/v4/Tool.java index 2c8f4bb93..451ff33e3 100644 --- a/tool/src/org/antlr/v4/Tool.java +++ b/tool/src/org/antlr/v4/Tool.java @@ -111,6 +111,7 @@ public class Tool { // fields set by option manager + public File inputDirectory; public String outputDirectory; public String libDirectory; public boolean report = false; @@ -490,7 +491,12 @@ public class Tool { public GrammarRootAST loadGrammar(String fileName) { try { - ANTLRFileStream in = new ANTLRFileStream(fileName, grammarEncoding); + File file = new File(fileName); + if (!file.isAbsolute()) { + file = new File(inputDirectory, fileName); + } + + ANTLRFileStream in = new ANTLRFileStream(file.getAbsolutePath(), grammarEncoding); GrammarRootAST t = load(in); return t; } @@ -629,7 +635,7 @@ public class Tool { } public File getImportedGrammarFile(Grammar g, String fileName) { - File importedFile = new File(fileName); + File importedFile = new File(inputDirectory, fileName); if ( !importedFile.exists() ) { File gfile = new File(g.fileName); String parentDir = gfile.getParent();