Initial Maven plugin for ANTLR 4. Just replaced v3 references with v4, so documentation not up-to-date.

This commit is contained in:
Sam Harwell 2012-04-10 09:47:05 -05:00
parent 9b78d7ee18
commit d902a73834
9 changed files with 183 additions and 152 deletions

3
.gitignore vendored
View File

@ -1,4 +1,5 @@
/tool/target/
/runtime/Java/target/
/gunit/target/
*.hprof
*.hprof
/antlr4-maven-plugin/target/

View File

@ -51,8 +51,8 @@
<!--
This is the ANTLR plugin for ANTLR version 3.1.3 and above. It might
have been best to change the name of the plugin as the 3.1.2 plugins
This is the ANTLR plugin for ANTLR version 4.0 and above. It might
have been best to change the name of the plugin as the 4.0 plugins
behave a little differently, however for the sake of one transitional
phase to a much better plugin, it was decided that the name should
remain the same.
@ -67,7 +67,7 @@
<version>4.0-SNAPSHOT</version>
<name>Maven plugin for ANTLR V4</name>
<prerequisites>
<maven>2.0</maven>
<maven>3.0</maven>
</prerequisites>
<!--
@ -90,7 +90,7 @@ 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 v3 supports
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.
@ -115,7 +115,7 @@ Jim Idle - March 2009
<name>Jim Idle</name>
<url>http://www.temporal-wave.com</url>
<roles>
<role>Originator, version 3.1.3</role>
<role>Originator, version 4.0</role>
</roles>
</developer>
@ -179,7 +179,7 @@ Jim Idle - March 2009
<site>
<id>antlr-repo</id>
<name>ANTLR Maven Plugin Web Site</name>
<url>scpexe://antlr.org/home/mavensync/antlr-maven-webs/antlr3-maven-plugin</url>
<url>scpexe://antlr.org/home/mavensync/antlr-maven-webs/antlr4-maven-plugin</url>
</site>
</distributionManagement>
@ -262,7 +262,7 @@ Jim Idle - March 2009
<dependency>
<groupId>org.codehaus.plexus</groupId>
<artifactId>plexus-compiler-api</artifactId>
<version>1.5.3</version>
<version>1.8.6</version>
</dependency>
<!--
@ -283,7 +283,7 @@ Jim Idle - March 2009
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.8.2</version>
<version>4.10</version>
<scope>test</scope>
</dependency>
@ -291,7 +291,7 @@ Jim Idle - March 2009
<dependency>
<groupId>org.apache.maven.shared</groupId>
<artifactId>maven-plugin-testing-harness</artifactId>
<version>1.0</version>
<version>1.1</version>
<scope>test</scope>
</dependency>
@ -305,7 +305,7 @@ Jim Idle - March 2009
<extension>
<groupId>org.apache.maven.wagon</groupId>
<artifactId>wagon-ssh-external</artifactId>
<version>1.0-beta-2</version>
<version>2.2</version>
</extension>
</extensions>
@ -328,13 +328,13 @@ Jim Idle - March 2009
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-site-plugin</artifactId>
<version>2.0</version>
<version>3.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-project-info-reports-plugin</artifactId>
<version>2.1.1</version>
<version>2.4</version>
<configuration>
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
</configuration>

View File

@ -30,34 +30,36 @@ 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.
* 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.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.v4.Tool;
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.File;
import java.io.IOException;
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/antlr3 ...
* that we use to compile them, such as target/generated-sources/antlr4 ...
*
* @goal antlr
*
@ -104,19 +106,12 @@ public class Antlr4Mojo
*/
protected boolean profile;
/**
* If set to true then the ANTLR tool will generate a description of the nfa
* If set to true then the ANTLR tool will generate a description of the atn
* 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;
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.
@ -140,6 +135,12 @@ public class Antlr4Mojo
*/
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.
@ -165,9 +166,9 @@ public class Antlr4Mojo
* 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
* 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
@ -189,20 +190,20 @@ public class Antlr4Mojo
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.
* 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/antlr3"
* @parameter default-value="${basedir}/src/main/antlr4"
* @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
* 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/antlr3"
* @parameter default-value="${project.build.directory}/generated-sources/antlr4"
* @required
*/
private File outputDirectory;
@ -211,7 +212,7 @@ public class Antlr4Mojo
* 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"
* @parameter default-value="${basedir}/src/main/antlr4/imports"
*/
private File libDirectory;
@ -237,7 +238,7 @@ public class Antlr4Mojo
/**
* The main entry point for this Mojo, it is responsible for converting
* ANTLR 3.x grammars into the target language specified by the grammar.
* 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
@ -279,8 +280,7 @@ public class Antlr4Mojo
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: atn : " + atn);
log.debug("ANTLR: trace : " + trace);
log.debug("ANTLR: messageFormat : " + messageFormat);
log.debug("ANTLR: maxSwitchCaseLabels : " + maxSwitchCaseLabels);
@ -297,69 +297,57 @@ public class Antlr4Mojo
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");
List<String> args = new ArrayList<String>();
throw new MojoFailureException("Jim failed you!");
}
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.
//
tool.debug = debug;
tool.generate_ATN_dot = atn;
tool.profile = profile;
tool.report = report;
tool.printGrammar = printGrammar;
tool.trace = trace;
tool.verbose_dfa = verbose_dfa;
tool.msgFormat = messageFormat;
tool.force_atn = force_atn;
// Where do we want ANTLR to produce its output? (Base directory)
//
if (log.isDebugEnabled())
{
log.debug("Output directory base will be " + outputDirectory.getAbsolutePath());
}
tool.outputDirectory = 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());
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(sourceDirectory, outputDirectory);
processGrammarFiles(args, sourceDirectory, outputDirectory);
} catch (InclusionScanException ie) {
@ -372,7 +360,48 @@ public class Antlr4Mojo
throw new MojoExecutionException(e.getMessage());
}
tool.process();
// Create an instance of the ANTLR 4 build tool
//
try {
tool = new Tool(args.toArray(new String[args.size()]));
// 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 grammars to compile in " + sourceDirectory.getAbsolutePath());
}
return;
} else {
if (log.isInfoEnabled()) {
log.info("ANTLR: Processing source directory " + sourceDirectory.getAbsolutePath());
}
}
} catch (Exception e) {
log.error("The attempt to create the ANTLR 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
@ -403,11 +432,11 @@ public class Antlr4Mojo
* @throws java.io.IOException
* @throws org.codehaus.plexus.compiler.util.scan.InclusionScanException
*/
private void processGrammarFiles(File sourceDirectory, File outputDirectory)
private void processGrammarFiles(List<String> 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("g", Collections.EMPTY_SET);
SourceMapping mapping = new SuffixMapping("g4", Collections.EMPTY_SET);
// What are the sets of includes (defaulted or otherwise).
//
@ -433,8 +462,8 @@ public class Antlr4Mojo
// Tell the ANTLR tool that we want sorted build mode
//
tool.setMake(true);
// tool.setMake(true);
// Iterate each grammar file we were given and add it into the tool's list of
// grammars to process.
//
@ -450,7 +479,8 @@ public class Antlr4Mojo
if (getLog().isDebugEnabled()) {
getLog().debug(" ... relative path is: " + relPath);
}
tool.addGrammarFile(relPath);
args.add(relPath);
}
@ -461,7 +491,7 @@ public class Antlr4Mojo
public Set<String> getIncludesPatterns() {
if (includes == null || includes.isEmpty()) {
return Collections.singleton("**/*.g");
return Collections.singleton("**/*.g4");
}
return includes;
}

View File

@ -1,8 +1,8 @@
Imported Grammar Files
In order to have the ANTLR plugin automatically locate and use grammars used
as imports in your main .g files, you need to place the imported grammar
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 <<<src/main/antlr3>>> by default of course).
files (which is <<<src/main/antlr4>>> by default of course).
For a default layout, place your import grammars in the directory: <<<src/main/antlr3/imports>>>
For a default layout, place your import grammars in the directory: <<<src/main/antlr4/imports>>>

View File

@ -26,8 +26,8 @@ Libraries
+--
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr3-maven-plugin</artifactId>
<version>3.1.3-1</version>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.0-SNAPSHOT</version>
<executions>
@ -36,7 +36,7 @@ Libraries
<goals>
<goal>antlr</goal>
</goals>
<libDirectory>src/main/antlr_imports</libDirectory>
<libDirectory>src/main/antlr4_imports</libDirectory>
</configuration>
</execution>
</executions>

View File

@ -7,8 +7,8 @@ Simple configuration
<plugins>
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr3-maven-plugin</artifactId>
<version>3.1.3-1</version>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.0-SNAPSHOT</version>
<executions>
<execution>
<goals>
@ -21,12 +21,12 @@ Simple configuration
</plugins>
+--
When the mvn command is executed all grammar files under <<<src/main/antlr3>>>, except any
import grammars under <<<src/main/antlr3/imports>>> will be analyzed and converted to
java source code in the output directory <<<target/generated-sources/antlr3>>>.
When the mvn command is executed all grammar files under <<<src/main/antlr4>>>, except any
import grammars under <<<src/main/antlr4/imports>>> will be analyzed and converted to
java source code in the output directory <<<target/generated-sources/antlr4>>>.
Your input files under <<<antlr3>>> should be stored in sub directories that
reflect the package structure of your java parsers. If your grammar file parser.g contains:
Your input files under <<<antlr4>>> should be stored in sub directories that
reflect the package structure of your java parsers. If your grammar file parser.g4 contains:
+---
@header {
@ -34,7 +34,7 @@ package org.jimi.themuss;
}
+---
Then the .g file should be stored in: <<<src/main/antlr3/org/jimi/themuss/parser.g>>>. THis way
Then the .g4 file should be stored in: <<<src/main/antlr4/org/jimi/themuss/parser.g4>>>. THis way
the generated .java files will correctly reflect the package structure in which they will
finally rest as classes.

View File

@ -1,14 +1,14 @@
-------------
ANTLR v3 Maven Plugin
ANTLR v4 Maven Plugin
-------------
Jim Idle
-------------
March 2009
-------------
ANTLR v3 Maven plugin
ANTLR v4 Maven plugin
The ANTLR v3 Maven plugin is completely re-written as of version 3.1.3; if you are familiar
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.
@ -20,15 +20,15 @@ ANTLR v3 Maven plugin
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 3.1.3 of ANTLR and this plugin.
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 3.1.3 of the plugin, you will build your grammars using version 3.1.3 of the
ANTLR tool, version 3.2 of the plugin will use version 3.2 of the ANTLR tool and so on.
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 3.1.3-1 3.1.3-2 and
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 <<Last Deployed>> date.
@ -44,19 +44,19 @@ ANTLR v3 Maven plugin
+--
src/main/
|
+--- antlr3/... .g files organized in the required package structure
+--- antlr4/... .g4 files organized in the required package structure
|
+--- imports/ .g files that are imported by other grammars.
+--- 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 <<<src/main/antlr3/org/foo/bar>>>. The plugin will then produce
.java and .tokens files in the output directory <<<target/generated-sources/antlr3/org/foo/bar>>>
place it in the directory <<<src/main/antlr4/org/foo/bar>>>. The plugin will then produce
.java and .tokens files in the output directory <<<target/generated-sources/antlr4/org/foo/bar>>>
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 <<<src/main/antlr3/imports>>> directory is treated in a special way. It should contain
The <<<src/main/antlr4/imports>>> 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.

View File

@ -6,9 +6,9 @@ Usage
+--
src/main/
|
+--- antlr3/... .g files organized in the required package structure
+--- antlr4/... .g4 files organized in the required package structure
|
+--- imports/ .g files that are imported by other grammars.
+--- imports/ .g4 files that are imported by other grammars.
+--
However, if you are not able to use this structure for whatever reason, you
@ -25,8 +25,8 @@ Usage
+--
<plugin>
<groupId>org.antlr</groupId>
<artifactId>antlr3-maven-plugin</artifactId>
<version>3.1.3-1</version>
<artifactId>antlr4-maven-plugin</artifactId>
<version>4.0-SNAPSHOT</version>
<executions>
@ -41,13 +41,13 @@ Usage
<nfa>false</nfa>
<excludes><exclude/></excludes>
<includes><include/></includes>
<libDirectory>src/main/antlr3/imports</libDirectory>
<libDirectory>src/main/antlr4/imports</libDirectory>
<messageFormat>antlr</messageFormat>
<outputDirectory>target/generated-sources/antlr3</outputDirectory>
<outputDirectory>target/generated-sources/antlr4</outputDirectory>
<printGrammar>false</printGrammar>
<profile>false</profile>
<report>false</report>
<sourceDirectory>src/main/antlr3</sourceDirectory>
<sourceDirectory>src/main/antlr4</sourceDirectory>
<trace>false</trace>
<verbose>true</verbose>
</configuration>
@ -148,9 +148,9 @@ Usage
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
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
@ -162,22 +162,22 @@ Usage
*** sourceDirectory
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
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.
<<NB>> Take careful note that the default location for antlr grammars
is now <<antlr3>> and NOT <<antlr>>
is now <<antlr4>> and NOT <<antlr>>
default-value="<<<${basedir}/src/main/antlr3>>>"
default-value="<<<${basedir}/src/main/antlr4>>>"
*** outputDirectory
Location for generated Java files. For antlr version 3.x we default
this to a directory in the tree called antlr3 because the antlr
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/antlr3>>>"
default-value="<<<${project.build.directory}/generated-sources/antlr4>>>"
*** libDirectory
@ -186,8 +186,8 @@ Usage
will include this directory in the search for .tokens files and import grammars.
<<NB>> If you change the lib directory from the default but the directory is
still under<<<${basedir}/src/main/antlr3>>>, then you will need to exclude
still under<<<${basedir}/src/main/antlr4>>>, then you will need to exclude
the grammars from processing specifically, using the <<<<excludes>>>> option.
default-value="<<<${basedir}/src/main/antlr3/imports>>>"
default-value="<<<${basedir}/src/main/antlr4/imports>>>"

View File

@ -7,7 +7,7 @@
<poweredBy>
<logo name="ANTLR Web Site" href="http://antlr.org/"
img="http://www.antlr.org/wiki/download/attachments/292/ANTLR3"/>
img="http://www.antlr.org/wiki/download/attachments/292/ANTLR4"/>
</poweredBy>
<body>