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> | ||||
<td valign="top" align="center">No</td> | <td valign="top" align="center">No</td> | ||||
</tr> | </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> | <!--tr> | ||||
<td valign="top">fork</td> | <td valign="top">fork</td> | ||||
<td valign="top">Run ANTLR in a separate VM.</td> | <td valign="top">Run ANTLR in a separate VM.</td> | ||||
@@ -40,10 +40,46 @@ | |||||
<target name="test7"> | <target name="test7"> | ||||
<antlr target="antlr.xml"/> | <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"> | <target name="cleanup"> | ||||
<delete dir="${tmp.dir}" /> | <delete dir="${tmp.dir}" /> | ||||
</target> | </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:emeade@geekfarm.org">Erik Meade</a> | ||||
* @author <a href="mailto:sbailliez@apache.org">Stephane Bailliez</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 { | public class ANTLR extends Task { | ||||
@@ -85,6 +86,30 @@ public class ANTLR extends Task { | |||||
/** where to output the result */ | /** where to output the result */ | ||||
private File outputDirectory; | 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 ? */ | /** should fork ? */ | ||||
private final boolean fork = true; | private final boolean fork = true; | ||||
@@ -106,15 +131,70 @@ public class ANTLR extends Task { | |||||
this.outputDirectory = outputDirectory; | 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 | // we are forced to fork ANTLR since there is a call | ||||
// to System.exit() and there is nothing we can do | // to System.exit() and there is nothing we can do | ||||
// right now to avoid this. :-( (SBa) | // right now to avoid this. :-( (SBa) | ||||
// I'm not removing this method to keep backward compatibility | // I'm not removing this method to keep backward compatibility | ||||
// and | |||||
public void setFork(boolean s) { | public void setFork(boolean s) { | ||||
//this.fork = s; | //this.fork = s; | ||||
} | } | ||||
/** | /** | ||||
* The working directory of the process | * The working directory of the process | ||||
*/ | */ | ||||
@@ -184,10 +264,9 @@ public class ANTLR extends Task { | |||||
validateAttributes(); | validateAttributes(); | ||||
//TODO: use ANTLR to parse the grammer file to do this. | //TODO: use ANTLR to parse the grammer file to do this. | ||||
if (target.lastModified() > getGeneratedFile().lastModified()) { | if (target.lastModified() > getGeneratedFile().lastModified()) { | ||||
commandline.createArgument().setValue("-o"); | |||||
commandline.createArgument().setValue(outputDirectory.toString()); | |||||
populateAttributes(); | |||||
commandline.createArgument().setValue(target.toString()); | commandline.createArgument().setValue(target.toString()); | ||||
log(commandline.describeCommand(), Project.MSG_VERBOSE); | log(commandline.describeCommand(), Project.MSG_VERBOSE); | ||||
int err = run(commandline.getCommandline()); | int err = run(commandline.getCommandline()); | ||||
if (err == 1) { | 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 { | private void validateAttributes() throws BuildException { | ||||
if (target == null || !target.isFile()) { | if (target == null || !target.isFile()) { | ||||
throw new BuildException("Invalid target: " + target); | 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 no output directory is specified, used the target's directory | ||||
if (outputDirectory == null) { | if (outputDirectory == null) { | ||||
String fileName = target.toString(); | String fileName = target.toString(); | ||||
@@ -68,6 +68,7 @@ import org.apache.tools.ant.BuildFileTest; | |||||
* system classpath. (see ANTLR install.html) | * system classpath. (see ANTLR install.html) | ||||
* | * | ||||
* @author Erik Meade <emeade@geekfarm.org> | * @author Erik Meade <emeade@geekfarm.org> | ||||
* @author Stephen Chin <aphid@browsecode.org> | |||||
*/ | */ | ||||
public class ANTLRTest extends BuildFileTest { | public class ANTLRTest extends BuildFileTest { | ||||
@@ -117,6 +118,57 @@ public class ANTLRTest extends BuildFileTest { | |||||
public void test7() { | public void test7() { | ||||
expectBuildException("test7", "Unable to determine generated class"); | 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 { | class CalcFileFilter implements FilenameFilter { | ||||
@@ -124,3 +176,9 @@ class CalcFileFilter implements FilenameFilter { | |||||
return name.startsWith("Calc"); | return name.startsWith("Calc"); | ||||
} | } | ||||
} | } | ||||
class HTMLFilter implements FilenameFilter { | |||||
public boolean accept(File dir, String name) { | |||||
return name.endsWith("html"); | |||||
} | |||||
} |