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"); | |||
} | |||
} |