Submitted by: Stephen Chin, aphid@versionablestore.com git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@272941 13f79535-47bb-0310-9956-ffa450edef68master
| @@ -54,6 +54,71 @@ | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">glib</td> | |||
| <td valign="top"> | |||
| An optional super grammar file that the target grammar overrides. This | |||
| feature is only needed for advanced vocabularies. | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">debug</td> | |||
| <td valign="top"> | |||
| When set to "yes", this flag adds code to the generated parser that will | |||
| launch the ParseView debugger upon invocation. The default is "no". | |||
| <br> | |||
| Note: ParseView is a separate component that needs to be installed or your | |||
| grammar will have compilation errors. | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">html</td> | |||
| <td valign="top"> | |||
| Emit an html version of the grammar with hyperlinked actions. | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">diagnostic</td> | |||
| <td valign="top"> | |||
| Generates a text file with debugging infomation based on the target grammar. | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">trace</td> | |||
| <td valign="top"> | |||
| Forces <b>all</b> rules to call traceIn/traceOut if set to "yes". | |||
| The default is "no". | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">traceParser</td> | |||
| <td valign="top"> | |||
| Only forces parser rules to call traceIn/traceOut if set to "yes". | |||
| The default is "no". | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">traceLexer</td> | |||
| <td valign="top"> | |||
| Only forces lexer rules to call traceIn/traceOut if set to "yes". | |||
| The default is "no". | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <tr> | |||
| <td valign="top">traceTreeWalker</td> | |||
| <td valign="top"> | |||
| Only forces tree walker rules to call traceIn/traceOut if set to | |||
| "yes". The default is "no". | |||
| </td> | |||
| <td valign="top" align="center">No</td> | |||
| </tr> | |||
| <!--tr> | |||
| <td valign="top">fork</td> | |||
| <td valign="top">Run ANTLR in a separate VM.</td> | |||
| @@ -40,10 +40,46 @@ | |||
| <target name="test7"> | |||
| <antlr target="antlr.xml"/> | |||
| </target> | |||
| </target> | |||
| <target name="test8"> | |||
| <antlr target="extended.calc.g" outputdirectory="${tmp.dir}" glib="non-existant-file.g"/> | |||
| </target> | |||
| <target name="test9"> | |||
| <mkdir dir="${tmp.dir}"/> | |||
| <!-- Note that I had to copy the grammars over to the temporary directory. --> | |||
| <!-- This is because ANTLR expects the super grammar and its generated java --> | |||
| <!-- files to be in the same directory, which won't be the case if I use --> | |||
| <!-- the output directory option. --> | |||
| <copy file="antlr.g" todir="${tmp.dir}"/> | |||
| <copy file="extended.calc.g" todir="${tmp.dir}"/> | |||
| <antlr target="${tmp.dir}/antlr.g"/> | |||
| <antlr target="${tmp.dir}/extended.calc.g" glib="${tmp.dir}/antlr.g"/> | |||
| </target> | |||
| <target name="test10"> | |||
| <mkdir dir="${tmp.dir}"/> | |||
| <antlr target="antlr.g" outputdirectory="${tmp.dir}" html="yes"/> | |||
| </target> | |||
| <target name="test11"> | |||
| <mkdir dir="${tmp.dir}"/> | |||
| <antlr target="antlr.g" outputdirectory="${tmp.dir}" diagnostic="yes"/> | |||
| </target> | |||
| <target name="test12"> | |||
| <mkdir dir="${tmp.dir}"/> | |||
| <antlr target="antlr.g" outputdirectory="${tmp.dir}" trace="yes"/> | |||
| </target> | |||
| <target name="test13"> | |||
| <mkdir dir="${tmp.dir}"/> | |||
| <antlr target="antlr.g" outputdirectory="${tmp.dir}" traceLexer="yes" traceParser="yes" traceTreeWalker="yes"/> | |||
| </target> | |||
| <target name="cleanup"> | |||
| <delete dir="${tmp.dir}" /> | |||
| </target> | |||
| </project> | |||
| </project> | |||
| @@ -0,0 +1,7 @@ | |||
| // Not really a great extension, but it is only a test after all! | |||
| class ExtendedCalcParser extends CalcParser; | |||
| exprList | |||
| : LPAREN (expr)* RPAREN | |||
| ; | |||
| @@ -74,6 +74,7 @@ import org.apache.tools.ant.types.Path; | |||
| * | |||
| * @author <a href="mailto:emeade@geekfarm.org">Erik Meade</a> | |||
| * @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</a> | |||
| * @author <a href="mailto:aphid@browsecode.org">Stephen Chin</a> | |||
| */ | |||
| public class ANTLR extends Task { | |||
| @@ -85,6 +86,30 @@ public class ANTLR extends Task { | |||
| /** where to output the result */ | |||
| private File outputDirectory; | |||
| /** an optional super grammar file */ | |||
| private String superGrammar; | |||
| /** optional flag to enable parseView debugging */ | |||
| private boolean debug; | |||
| /** optional flag to enable html output */ | |||
| private boolean html; | |||
| /** optional flag to print out a diagnostic file */ | |||
| private boolean diagnostic; | |||
| /** optional flag to add trace methods */ | |||
| private boolean trace; | |||
| /** optional flag to add trace methods to the parser only */ | |||
| private boolean traceParser; | |||
| /** optional flag to add trace methods to the lexer only */ | |||
| private boolean traceLexer; | |||
| /** optional flag to add trace methods to the tree walker only */ | |||
| private boolean traceTreeWalker; | |||
| /** should fork ? */ | |||
| private final boolean fork = true; | |||
| @@ -106,15 +131,70 @@ public class ANTLR extends Task { | |||
| this.outputDirectory = outputDirectory; | |||
| } | |||
| /** | |||
| * Sets an optional super grammar file | |||
| */ | |||
| public void setGlib(String superGrammar) { | |||
| this.superGrammar = superGrammar; | |||
| } | |||
| /** | |||
| * Sets a flag to enable ParseView debugging | |||
| */ | |||
| public void setDebug(boolean enable) { | |||
| debug = enable; | |||
| } | |||
| /** | |||
| * Sets a flag to emit html | |||
| */ | |||
| public void setHtml(boolean enable) { | |||
| html = enable; | |||
| } | |||
| /** | |||
| * Sets a flag to emit diagnostic text | |||
| */ | |||
| public void setDiagnostic(boolean enable) { | |||
| diagnostic = enable; | |||
| } | |||
| /** | |||
| * Sets a flag to enable all tracing | |||
| */ | |||
| public void setTrace(boolean enable) { | |||
| trace = enable; | |||
| } | |||
| /** | |||
| * Sets a flag to enable parser tracing | |||
| */ | |||
| public void setTraceParser(boolean enable) { | |||
| traceParser = enable; | |||
| } | |||
| /** | |||
| * Sets a flag to allow the user to enable lexer tracing | |||
| */ | |||
| public void setTraceLexer(boolean enable) { | |||
| traceLexer = enable; | |||
| } | |||
| /** | |||
| * Sets a flag to allow the user to enable tree walker tracing | |||
| */ | |||
| public void setTraceTreeWalker(boolean enable) { | |||
| traceTreeWalker = enable; | |||
| } | |||
| // we are forced to fork ANTLR since there is a call | |||
| // to System.exit() and there is nothing we can do | |||
| // right now to avoid this. :-( (SBa) | |||
| // I'm not removing this method to keep backward compatibility | |||
| // and | |||
| public void setFork(boolean s) { | |||
| //this.fork = s; | |||
| } | |||
| /** | |||
| * The working directory of the process | |||
| */ | |||
| @@ -184,10 +264,9 @@ public class ANTLR extends Task { | |||
| validateAttributes(); | |||
| //TODO: use ANTLR to parse the grammer file to do this. | |||
| if (target.lastModified() > getGeneratedFile().lastModified()) { | |||
| commandline.createArgument().setValue("-o"); | |||
| commandline.createArgument().setValue(outputDirectory.toString()); | |||
| populateAttributes(); | |||
| commandline.createArgument().setValue(target.toString()); | |||
| log(commandline.describeCommand(), Project.MSG_VERBOSE); | |||
| int err = run(commandline.getCommandline()); | |||
| if (err == 1) { | |||
| @@ -198,11 +277,47 @@ public class ANTLR extends Task { | |||
| } | |||
| } | |||
| /** | |||
| * A refactored method for populating all the command line arguments based | |||
| * on the user-specified attributes. | |||
| */ | |||
| private void populateAttributes() { | |||
| commandline.createArgument().setValue("-o"); | |||
| commandline.createArgument().setValue(outputDirectory.toString()); | |||
| if (superGrammar != null) { | |||
| commandline.createArgument().setValue("-glib"); | |||
| commandline.createArgument().setValue(superGrammar); | |||
| } | |||
| if (html) { | |||
| commandline.createArgument().setValue("-html"); | |||
| } | |||
| if (diagnostic) { | |||
| commandline.createArgument().setValue("-diagnostic"); | |||
| } | |||
| if (trace) { | |||
| commandline.createArgument().setValue("-trace"); | |||
| } | |||
| if (traceParser) { | |||
| commandline.createArgument().setValue("-traceParser"); | |||
| } | |||
| if (traceLexer) { | |||
| commandline.createArgument().setValue("-traceLexer"); | |||
| } | |||
| if (traceTreeWalker) { | |||
| commandline.createArgument().setValue("-traceTreeWalker"); | |||
| } | |||
| } | |||
| private void validateAttributes() throws BuildException { | |||
| if (target == null || !target.isFile()) { | |||
| throw new BuildException("Invalid target: " + target); | |||
| } | |||
| // validate the superGrammar file | |||
| if (superGrammar != null && !new File(superGrammar).isFile()) { | |||
| throw new BuildException("Invalid super grammar file: " + superGrammar); | |||
| } | |||
| // if no output directory is specified, used the target's directory | |||
| if (outputDirectory == null) { | |||
| String fileName = target.toString(); | |||
| @@ -68,6 +68,7 @@ import org.apache.tools.ant.BuildFileTest; | |||
| * system classpath. (see ANTLR install.html) | |||
| * | |||
| * @author Erik Meade <emeade@geekfarm.org> | |||
| * @author Stephen Chin <aphid@browsecode.org> | |||
| */ | |||
| public class ANTLRTest extends BuildFileTest { | |||
| @@ -117,6 +118,57 @@ public class ANTLRTest extends BuildFileTest { | |||
| public void test7() { | |||
| expectBuildException("test7", "Unable to determine generated class"); | |||
| } | |||
| /** | |||
| * This is a negative test for the super grammar (glib) option. | |||
| */ | |||
| public void test8() { | |||
| expectBuildException("test8", "Invalid super grammar file"); | |||
| } | |||
| /** | |||
| * This is a positive test for the super grammar (glib) option. ANTLR | |||
| * will throw an error if everything is not correct. | |||
| */ | |||
| public void test9() { | |||
| executeTarget("test9"); | |||
| } | |||
| /** | |||
| * This test creates an html-ized version of the calculator grammar. | |||
| * The sanity check is simply whether or not an html file was generated. | |||
| */ | |||
| public void test10() { | |||
| executeTarget("test10"); | |||
| File outputDirectory = new File(TASKDEFS_DIR + "antlr.tmp"); | |||
| String[] calcFiles = outputDirectory.list(new HTMLFilter()); | |||
| assertEquals(1, calcFiles.length); | |||
| } | |||
| /** | |||
| * This is just a quick sanity check to run the diagnostic option and | |||
| * make sure that it doesn't throw any funny exceptions. | |||
| */ | |||
| public void test11() { | |||
| executeTarget("test11"); | |||
| } | |||
| /** | |||
| * This is just a quick sanity check to run the trace option and | |||
| * make sure that it doesn't throw any funny exceptions. | |||
| */ | |||
| public void test12() { | |||
| executeTarget("test12"); | |||
| } | |||
| /** | |||
| * This is just a quick sanity check to run all the rest of the | |||
| * trace options (traceLexer, traceParser, and traceTreeWalker) to | |||
| * make sure that they don't throw any funny exceptions. | |||
| */ | |||
| public void test13() { | |||
| executeTarget("test13"); | |||
| } | |||
| } | |||
| class CalcFileFilter implements FilenameFilter { | |||
| @@ -124,3 +176,9 @@ class CalcFileFilter implements FilenameFilter { | |||
| return name.startsWith("Calc"); | |||
| } | |||
| } | |||
| class HTMLFilter implements FilenameFilter { | |||
| public boolean accept(File dir, String name) { | |||
| return name.endsWith("html"); | |||
| } | |||
| } | |||