Added Antlr compiler/runtime and wrote initial grammar.
Grammar is just a collection of rules. Change-Id: I556a8f74668b11b80f673fc7d665704322c2dac9
This commit is contained in:
parent
a1bd87e7b2
commit
8242986221
9
Makefile
Normal file
9
Makefile
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
|
||||||
|
all: CongressLexer.py
|
||||||
|
|
||||||
|
CongressLexer.py CongressParser.py: policy/Congress.g
|
||||||
|
java -jar outside/antlr-3.5-complete.jar policy/Congress.g
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
BIN
outside/antlr-3.5-complete.jar
Normal file
BIN
outside/antlr-3.5-complete.jar
Normal file
Binary file not shown.
30
outside/antlr3-antlr-3.5/.gitignore
vendored
Normal file
30
outside/antlr3-antlr-3.5/.gitignore
vendored
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
# Maven build folders
|
||||||
|
target/
|
||||||
|
|
||||||
|
# IntelliJ project files
|
||||||
|
*.iml
|
||||||
|
*.ipr
|
||||||
|
*.iws
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Eclipse project files
|
||||||
|
.project
|
||||||
|
.classpath
|
||||||
|
.settings/
|
||||||
|
|
||||||
|
# NetBeans user configuration
|
||||||
|
nbactions.xml
|
||||||
|
nb-configuration.xml
|
||||||
|
|
||||||
|
# Python runtime files
|
||||||
|
*.py[co]
|
||||||
|
|
||||||
|
# ANTLR C# target build folders
|
||||||
|
/runtime/CSharp3/Sources/Antlr3.Runtime/bin/
|
||||||
|
/runtime/CSharp3/Sources/Antlr3.Runtime/obj/
|
||||||
|
/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/bin/
|
||||||
|
/runtime/CSharp3/Sources/Antlr3.Runtime.Debug/obj/
|
||||||
|
/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/bin/
|
||||||
|
/runtime/CSharp3/Sources/Antlr3.Runtime.JavaExtensions/obj/
|
||||||
|
/runtime/CSharp3/Sources/Antlr3.Runtime.Test/bin/
|
||||||
|
/runtime/CSharp3/Sources/Antlr3.Runtime.Test/obj/
|
6
outside/antlr3-antlr-3.5/BUILD.txt
Normal file
6
outside/antlr3-antlr-3.5/BUILD.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
We have moved instructions for building ANTLR with the maven build system to:
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/display/ANTLR3/Building+ANTLR+with+Maven
|
||||||
|
|
||||||
|
The notes are by Jim Idle (and are a bit out of date but we hope to
|
||||||
|
update them).
|
142
outside/antlr3-antlr-3.5/README.txt
Normal file
142
outside/antlr3-antlr-3.5/README.txt
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
ANTLR v3.5
|
||||||
|
January 4, 2013
|
||||||
|
|
||||||
|
Terence Parr, parrt at cs usfca edu
|
||||||
|
ANTLR project lead and supreme dictator for life
|
||||||
|
University of San Francisco
|
||||||
|
|
||||||
|
INTRODUCTION
|
||||||
|
|
||||||
|
Welcome to ANTLR v3! ANTLR (ANother Tool for Language Recognition) is
|
||||||
|
a language tool that provides a framework for constructing
|
||||||
|
recognizers, interpreters, compilers, and translators from grammatical
|
||||||
|
descriptions containing actions in a variety of target
|
||||||
|
languages. ANTLR provides excellent support for tree construction,
|
||||||
|
tree walking, translation, error recovery, and error reporting. I've
|
||||||
|
been working on parser generators for 25 years and on this particular
|
||||||
|
version of ANTLR for 9 years.
|
||||||
|
|
||||||
|
You should use v3 in conjunction with ANTLRWorks:
|
||||||
|
|
||||||
|
http://www.antlr.org/works/index.html
|
||||||
|
|
||||||
|
and gUnit (grammar unit testing tool included in distribution):
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/display/ANTLR3/gUnit+-+Grammar+Unit+Testing
|
||||||
|
|
||||||
|
The book will also help you a great deal (printed May 15, 2007); you
|
||||||
|
can also buy the PDF:
|
||||||
|
|
||||||
|
http://www.pragmaticprogrammer.com/titles/tpantlr/index.html
|
||||||
|
|
||||||
|
2nd book, Language Implementation Patterns:
|
||||||
|
|
||||||
|
http://pragprog.com/titles/tpdsl/language-implementation-patterns
|
||||||
|
|
||||||
|
See the getting started document:
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/display/ANTLR3/FAQ+-+Getting+Started
|
||||||
|
|
||||||
|
You also have the examples plus the source to guide you.
|
||||||
|
|
||||||
|
See the wiki FAQ:
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/display/ANTLR3/ANTLR+v3+FAQ
|
||||||
|
|
||||||
|
and general doc root:
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/display/ANTLR3/ANTLR+3+Wiki+Home
|
||||||
|
|
||||||
|
Please help add/update FAQ entries.
|
||||||
|
|
||||||
|
If all else fails, you can buy support or ask the antlr-interest list:
|
||||||
|
|
||||||
|
http://www.antlr.org/support.html
|
||||||
|
|
||||||
|
Per the license in LICENSE.txt, this software is not guaranteed to
|
||||||
|
work and might even destroy all life on this planet:
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
|
||||||
|
ANTLR v3 sample grammars:
|
||||||
|
|
||||||
|
https://github.com/antlr/examples-v3
|
||||||
|
|
||||||
|
Examples from Language Implementation Patterns:
|
||||||
|
|
||||||
|
http://www.pragprog.com/titles/tpdsl/source_code
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
What is ANTLR?
|
||||||
|
|
||||||
|
ANTLR stands for (AN)other (T)ool for (L)anguage (R)ecognition
|
||||||
|
and generates LL(*) recursive-descent parsers. ANTLR is a language tool
|
||||||
|
that provides a framework for constructing recognizers, compilers, and
|
||||||
|
translators from grammatical descriptions containing actions.
|
||||||
|
Target language list:
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/display/ANTLR3/Code+Generation+Targets
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
How is ANTLR v3 different than ANTLR v2?
|
||||||
|
|
||||||
|
See "What is the difference between ANTLR v2 and v3?"
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/pages/viewpage.action?pageId=719
|
||||||
|
|
||||||
|
See migration guide:
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/display/ANTLR3/Migrating+from+ANTLR+2+to+ANTLR+3
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
How do I install this damn thing?
|
||||||
|
|
||||||
|
You will have grabbed either of these:
|
||||||
|
|
||||||
|
http://antlr.org/download/antlr-3.5-complete-no-antlrv2.jar
|
||||||
|
http://antlr.org/download/antlr-3.5-complete.jar
|
||||||
|
|
||||||
|
It has all of the jars you need combined into one. Then you need to
|
||||||
|
add antlr-3.5-complete.jar to your CLASSPATH or add to arg list; e.g., on unix:
|
||||||
|
|
||||||
|
$ java -cp "/usr/local/lib/antlr-3.5-complete.jar:$CLASSPATH" org.antlr.Tool Test.g
|
||||||
|
|
||||||
|
Source + java binaries: Just untar antlr-3.5.tar.gz and you'll get:
|
||||||
|
|
||||||
|
antlr-3.5/BUILD.txt
|
||||||
|
antlr-3.5/antlr3-maven-plugin
|
||||||
|
antlr-3.5/antlrjar.xml
|
||||||
|
antlr-3.5/antlrsources.xml
|
||||||
|
antlr-3.5/gunit
|
||||||
|
antlr-3.5/gunit-maven-plugin
|
||||||
|
antlr-3.5/pom.xml
|
||||||
|
antlr-3.5/runtime
|
||||||
|
antlr-3.5/tool
|
||||||
|
antlr-3.5/lib
|
||||||
|
|
||||||
|
Please see the FAQ
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/display/ANTLR3/ANTLR+v3+FAQ
|
||||||
|
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
How can I contribute to ANTLR v3?
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/pages/viewpage.action?pageId=33947666
|
@ -0,0 +1,61 @@
|
|||||||
|
Changes:
|
||||||
|
|
||||||
|
19.08.2008
|
||||||
|
Dependency check for composed grammars added.
|
||||||
|
Might need some further improvements.
|
||||||
|
|
||||||
|
09.08.2008
|
||||||
|
Inspecting environment variable ANTLR_HOME to detect and add
|
||||||
|
antlr- and stringtemplate libraries to the classpath
|
||||||
|
|
||||||
|
09.08.2008
|
||||||
|
Removed routine checkGenerateFile. It got feeble with the
|
||||||
|
introduction of composed grammars, e.g. "import T.g".
|
||||||
|
From now one it is always antlr itself via the depend option
|
||||||
|
which decides about dependecies
|
||||||
|
|
||||||
|
31.12.2007
|
||||||
|
With option "depend=true" proceed even if first pass failed so
|
||||||
|
that ANTLR can spit out its errors
|
||||||
|
|
||||||
|
31.12.2007
|
||||||
|
Support the -Xconversiontimeout option (Jim Idle)
|
||||||
|
|
||||||
|
21.10.2007
|
||||||
|
Evaluation of dependencies via ANTLRs 'depend' option.
|
||||||
|
Added noprune and nocollapse option.
|
||||||
|
'grammar parser' will be recognized.
|
||||||
|
|
||||||
|
17.05.2007
|
||||||
|
Adapted the grammar type recognition to the changed naming conventions for tree parsers.
|
||||||
|
Compiled the antlr3 taks with -source 5 -target 5 for compatibility with Java 5.
|
||||||
|
Dropped trace, tracelexer and traceparser options as they are not supported by antlr any more.
|
||||||
|
Added depend and dbgST options.
|
||||||
|
Added project "SimpleTreeWalker" as an example for a multi grammar project.
|
||||||
|
|
||||||
|
How to build the antlr3 task:
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
1) apache-ant-1.7.0 installed
|
||||||
|
2) antlr jar files (antlr-3.1b1.jar, antlr-2.7.7.jar and stringtemplate-3.1b1.jar)
|
||||||
|
contained in the CLASSPATH environment variable
|
||||||
|
3) Java 5 or Java 6 installed
|
||||||
|
|
||||||
|
javac -source 5 -target 5 -classpath C:/Programme/apache-ant-1.7.0/lib/ant.jar org/apache/tools/ant/antlr/ANTLR3.java
|
||||||
|
jar cvf antlr3.jar org/apache/tools/ant/antlr/antlib.xml org/apache/tools/ant/antlr/ANTLR3.class
|
||||||
|
|
||||||
|
a) d2u.tp
|
||||||
|
|
||||||
|
Simple example on how to use the antlr3 task with ant
|
||||||
|
|
||||||
|
b) simplecTreeParser.tp
|
||||||
|
|
||||||
|
Example on how to build a multi grammar project with ant.
|
||||||
|
|
||||||
|
c) polydiff_build.zip
|
||||||
|
|
||||||
|
Example build file for polydiff example grammar added.
|
||||||
|
|
||||||
|
d) composite-java_build.zip
|
||||||
|
|
||||||
|
Example build file for composite-java example grammar added
|
@ -0,0 +1,776 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2000-2004 The Apache Software Foundation
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*
|
||||||
|
* 2006-12-29: Modified to work for antlr3 by Jürgen Pfundt
|
||||||
|
* 2007-01-04: Some minor correction after checking code with findBugs tool
|
||||||
|
* 2007-02-10: Adapted the grammar type recognition to the changed naming
|
||||||
|
* conventions for Tree Parser
|
||||||
|
* 2007-10-17: Options "trace", "traceLexer", "traceParser" and "glib" emit
|
||||||
|
* warnings when being used.
|
||||||
|
* Added recognition of "parser grammar T".
|
||||||
|
* Added options "nocollapse", "noprune".
|
||||||
|
* ANTLR option "depend" is being used to resolve build dependencies.
|
||||||
|
* 2007-11-15: Embedded Classpath statement had not been observed
|
||||||
|
* with option depend="true" (Reported by Mats Behre)
|
||||||
|
* 2008-03-31: Support the option conversiontimeout. (Jim Idle)
|
||||||
|
* 2007-12-31: With option "depend=true" proceed even if first pass failed so
|
||||||
|
* that ANTLR can spit out its errors
|
||||||
|
* 2008-08-09: Inspecting environment variable ANTLR_HOME to detect and add
|
||||||
|
* antlr- and stringtemplate libraries to the classpath
|
||||||
|
* 2008-08-09: Removed routine checkGenerateFile. It got feeble with the
|
||||||
|
* introduction of composed grammars, e.g. "import T.g" and after
|
||||||
|
* a short struggle it started it's journey to /dev/null.
|
||||||
|
* From now one it is always antlr itself via the depend option
|
||||||
|
* which decides about dependecies
|
||||||
|
* 2008-08-19: Dependency check for composed grammars added.
|
||||||
|
* Might need some further improvements.
|
||||||
|
*/
|
||||||
|
package org.apache.tools.ant.antlr;
|
||||||
|
|
||||||
|
import java.util.regex.*;
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.apache.tools.ant.BuildException;
|
||||||
|
import org.apache.tools.ant.DirectoryScanner;
|
||||||
|
import org.apache.tools.ant.Project;
|
||||||
|
import org.apache.tools.ant.Task;
|
||||||
|
import org.apache.tools.ant.taskdefs.Execute;
|
||||||
|
import org.apache.tools.ant.taskdefs.LogOutputStream;
|
||||||
|
import org.apache.tools.ant.taskdefs.PumpStreamHandler;
|
||||||
|
import org.apache.tools.ant.taskdefs.Redirector;
|
||||||
|
import org.apache.tools.ant.types.Commandline;
|
||||||
|
import org.apache.tools.ant.types.CommandlineJava;
|
||||||
|
import org.apache.tools.ant.types.Path;
|
||||||
|
import org.apache.tools.ant.util.JavaEnvUtils;
|
||||||
|
import org.apache.tools.ant.util.LoaderUtils;
|
||||||
|
import org.apache.tools.ant.util.TeeOutputStream;
|
||||||
|
import org.apache.tools.ant.util.FileUtils;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Invokes the ANTLR3 Translator generator on a grammar file.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class ANTLR3 extends Task {
|
||||||
|
|
||||||
|
private CommandlineJava commandline = new CommandlineJava();
|
||||||
|
/** the file to process */
|
||||||
|
private File target = null;
|
||||||
|
/** where to output the result */
|
||||||
|
private File outputDirectory = null;
|
||||||
|
/** location of token files */
|
||||||
|
private File libDirectory = null;
|
||||||
|
/** an optional super grammar file */
|
||||||
|
private File superGrammar;
|
||||||
|
/** depend */
|
||||||
|
private boolean depend = false;
|
||||||
|
/** fork */
|
||||||
|
private boolean fork;
|
||||||
|
/** name of output style for messages */
|
||||||
|
private String messageFormatName;
|
||||||
|
/** optional flag to print out a diagnostic file */
|
||||||
|
private boolean diagnostic;
|
||||||
|
/** optional flag to add 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;
|
||||||
|
/** working directory */
|
||||||
|
private File workingdir = null;
|
||||||
|
/** captures ANTLR's output */
|
||||||
|
private ByteArrayOutputStream bos = new ByteArrayOutputStream();
|
||||||
|
/** The debug attribute */
|
||||||
|
private boolean debug;
|
||||||
|
/** The report attribute */
|
||||||
|
private boolean report;
|
||||||
|
/** The print attribute */
|
||||||
|
private boolean print;
|
||||||
|
/** The profile attribute */
|
||||||
|
private boolean profile;
|
||||||
|
/** The nfa attribute */
|
||||||
|
private boolean nfa;
|
||||||
|
/** The dfa attribute */
|
||||||
|
private boolean dfa;
|
||||||
|
/** multi threaded analysis */
|
||||||
|
private boolean multiThreaded;
|
||||||
|
/** collapse incident edges into DFA states */
|
||||||
|
private boolean nocollapse;
|
||||||
|
/** test lookahead against EBNF block exit branches */
|
||||||
|
private boolean noprune;
|
||||||
|
/** put tags at start/stop of all templates in output */
|
||||||
|
private boolean dbgST;
|
||||||
|
/** print AST */
|
||||||
|
private boolean grammarTree;
|
||||||
|
/** Instance of a utility class to use for file operations. */
|
||||||
|
private FileUtils fileUtils;
|
||||||
|
/**
|
||||||
|
* Whether to override the default conversion timeout with -Xconversiontimeout nnnn
|
||||||
|
*/
|
||||||
|
private String conversiontimeout;
|
||||||
|
|
||||||
|
public ANTLR3() {
|
||||||
|
commandline.setVm(JavaEnvUtils.getJreExecutable("java"));
|
||||||
|
commandline.setClassname("org.antlr.Tool");
|
||||||
|
fileUtils = FileUtils.getFileUtils();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The grammar file to process.
|
||||||
|
*/
|
||||||
|
public void setTarget(File targetFile) {
|
||||||
|
log("Setting target to: " + targetFile.toString(), Project.MSG_VERBOSE);
|
||||||
|
this.target = targetFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The directory to write the generated files to.
|
||||||
|
*/
|
||||||
|
public void setOutputdirectory(File outputDirectoryFile) {
|
||||||
|
log("Setting output directory to: " + outputDirectoryFile.toString(), Project.MSG_VERBOSE);
|
||||||
|
this.outputDirectory = outputDirectoryFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The directory to write the generated files to.
|
||||||
|
*/
|
||||||
|
public File getOutputdirectory() {
|
||||||
|
return outputDirectory;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The token files output directory.
|
||||||
|
*/
|
||||||
|
public void setLibdirectory(File libDirectoryFile) {
|
||||||
|
log("Setting lib directory to: " + libDirectoryFile.toString(), Project.MSG_VERBOSE);
|
||||||
|
this.libDirectory = libDirectoryFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The output style for messages.
|
||||||
|
*/
|
||||||
|
public void setMessageformat(String name) {
|
||||||
|
log("Setting message-format to: " + name, Project.MSG_VERBOSE);
|
||||||
|
this.messageFormatName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets an optional super grammar file
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public void setGlib(File superGrammarFile) {
|
||||||
|
this.superGrammar = superGrammarFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a flag to enable ParseView debugging
|
||||||
|
*/
|
||||||
|
public void setDebug(boolean enable) {
|
||||||
|
this.debug = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a flag to enable report statistics
|
||||||
|
*/
|
||||||
|
public void setReport(boolean enable) {
|
||||||
|
this.report = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a flag to print out the grammar without actions
|
||||||
|
*/
|
||||||
|
public void setPrint(boolean enable) {
|
||||||
|
this.print = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a flag to enable profiling
|
||||||
|
*/
|
||||||
|
public void setProfile(boolean enable) {
|
||||||
|
this.profile = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a flag to enable nfa generation
|
||||||
|
*/
|
||||||
|
public void setNfa(boolean enable) {
|
||||||
|
this.nfa = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a flag to enable nfa generation
|
||||||
|
*/
|
||||||
|
public void setDfa(boolean enable) {
|
||||||
|
this.dfa = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Run the analysis multithreaded
|
||||||
|
* @param enable
|
||||||
|
*/
|
||||||
|
public void setMultithreaded(boolean enable) {
|
||||||
|
multiThreaded = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* collapse incident edges into DFA states
|
||||||
|
* @param enable
|
||||||
|
*/
|
||||||
|
public void setNocollapse(boolean enable) {
|
||||||
|
nocollapse = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test lookahead against EBNF block exit branches
|
||||||
|
* @param enable
|
||||||
|
*/
|
||||||
|
public void setNoprune(boolean enable) {
|
||||||
|
noprune = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* test lookahead against EBNF block exit branches
|
||||||
|
* @param enable
|
||||||
|
*/
|
||||||
|
public void setDbgST(boolean enable) {
|
||||||
|
dbgST = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* override the default conversion timeout with -Xconversiontimeout nnnn
|
||||||
|
* @param conversiontimeoutString
|
||||||
|
*/
|
||||||
|
public void setConversiontimeout(String conversiontimeoutString) {
|
||||||
|
log("Setting conversiontimeout to: " + conversiontimeoutString, Project.MSG_VERBOSE);
|
||||||
|
try {
|
||||||
|
int timeout = Integer.valueOf(conversiontimeoutString);
|
||||||
|
this.conversiontimeout = conversiontimeoutString;
|
||||||
|
} catch (NumberFormatException e) {
|
||||||
|
log("Option ConversionTimeOut ignored due to illegal value: '" + conversiontimeoutString + "'", Project.MSG_ERR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a flag to enable printing of the grammar tree
|
||||||
|
*/
|
||||||
|
public void setGrammartree(boolean enable) {
|
||||||
|
grammarTree = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Set a flag to enable dependency checking by ANTLR itself
|
||||||
|
* The depend option is always used implicitely inside the antlr3 task
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public void setDepend(boolean s) {
|
||||||
|
this.depend = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets a flag to emit diagnostic text
|
||||||
|
*/
|
||||||
|
public void setDiagnostic(boolean enable) {
|
||||||
|
diagnostic = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, enables all tracing.
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public void setTrace(boolean enable) {
|
||||||
|
trace = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, enables parser tracing.
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public void setTraceParser(boolean enable) {
|
||||||
|
traceParser = enable;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If true, enables lexer tracing.
|
||||||
|
* @deprecated
|
||||||
|
*/
|
||||||
|
public void setTraceLexer(boolean enable) {
|
||||||
|
traceLexer = 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
|
||||||
|
/**
|
||||||
|
* @ant.attribute ignore="true"
|
||||||
|
*/
|
||||||
|
public void setFork(boolean s) {
|
||||||
|
this.fork = s;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The working directory of the process
|
||||||
|
*/
|
||||||
|
public void setDir(File d) {
|
||||||
|
this.workingdir = d;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a classpath to be set
|
||||||
|
* because a directory might be given for Antlr debug.
|
||||||
|
*/
|
||||||
|
public Path createClasspath() {
|
||||||
|
return commandline.createClasspath(getProject()).createPath();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds a new JVM argument.
|
||||||
|
* @return create a new JVM argument so that any argument can be passed to the JVM.
|
||||||
|
* @see #setFork(boolean)
|
||||||
|
*/
|
||||||
|
public Commandline.Argument createJvmarg() {
|
||||||
|
return commandline.createVmArgument();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds the jars or directories containing Antlr and associates.
|
||||||
|
* This should make the forked JVM work without having to
|
||||||
|
* specify it directly.
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void init() throws BuildException {
|
||||||
|
/* Inquire environment variables */
|
||||||
|
Map<String, String> variables = System.getenv();
|
||||||
|
/* Get value for key "ANTLR_HOME" which should hopefully point to
|
||||||
|
* the directory where the current version of antlr3 is installed */
|
||||||
|
String antlrHome = variables.get("ANTLR_HOME");
|
||||||
|
if (antlrHome != null) {
|
||||||
|
/* Environment variable ANTLR_HOME has been defined.
|
||||||
|
* Now add all antlr and stringtemplate libraries to the
|
||||||
|
* classpath */
|
||||||
|
addAntlrJarsToClasspath(antlrHome + "/lib");
|
||||||
|
}
|
||||||
|
addClasspathEntry("/antlr/ANTLRGrammarParseBehavior.class", "AntLR2");
|
||||||
|
addClasspathEntry("/org/antlr/tool/ANTLRParser.class", "AntLR3");
|
||||||
|
addClasspathEntry("/org/antlr/stringtemplate/StringTemplate.class", "Stringtemplate");
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Search for the given resource and add the directory or archive
|
||||||
|
* that contains it to the classpath.
|
||||||
|
*
|
||||||
|
* <p>Doesn't work for archives in JDK 1.1 as the URL returned by
|
||||||
|
* getResource doesn't contain the name of the archive.</p>
|
||||||
|
*/
|
||||||
|
protected void addClasspathEntry(String resource, String msg) {
|
||||||
|
/*
|
||||||
|
* pre Ant 1.6 this method used to call getClass().getResource
|
||||||
|
* while Ant 1.6 will call ClassLoader.getResource().
|
||||||
|
*
|
||||||
|
* The difference is that Class.getResource expects a leading
|
||||||
|
* slash for "absolute" resources and will strip it before
|
||||||
|
* delegating to ClassLoader.getResource - so we now have to
|
||||||
|
* emulate Class's behavior.
|
||||||
|
*/
|
||||||
|
if (resource.startsWith("/")) {
|
||||||
|
resource = resource.substring(1);
|
||||||
|
} else {
|
||||||
|
resource = "org/apache/tools/ant/taskdefs/optional/" + resource;
|
||||||
|
}
|
||||||
|
|
||||||
|
File f = LoaderUtils.getResourceSource(getClass().getClassLoader(), resource);
|
||||||
|
if (f != null) {
|
||||||
|
log("Found via classpath: " + f.getAbsolutePath(), Project.MSG_VERBOSE);
|
||||||
|
createClasspath().setLocation(f);
|
||||||
|
} else {
|
||||||
|
log("Couldn\'t find resource " + resource + " for library " + msg + " in external classpath", Project.MSG_VERBOSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the environment variable ANTLR_HOME is defined and points
|
||||||
|
* to the installation directory of antlr3 then look for all antlr-*.jar and
|
||||||
|
* stringtemplate-*.jar files in the lib directory and add them
|
||||||
|
* to the classpath.
|
||||||
|
* This feature should make working with eclipse or netbeans projects a
|
||||||
|
* little bit easier. As wildcards are being used for the version part
|
||||||
|
* of the jar-archives it makes the task independent of
|
||||||
|
* new releases. Just let ANTLR_HOME point to the new installation
|
||||||
|
* directory.
|
||||||
|
*/
|
||||||
|
private void addAntlrJarsToClasspath(String antlrLibDir) {
|
||||||
|
String[] includes = {"antlr-*.jar", "stringtemplate-*.jar"};
|
||||||
|
|
||||||
|
DirectoryScanner ds = new DirectoryScanner();
|
||||||
|
ds.setIncludes(includes);
|
||||||
|
ds.setBasedir(new File(antlrLibDir));
|
||||||
|
ds.setCaseSensitive(true);
|
||||||
|
ds.scan();
|
||||||
|
|
||||||
|
String separator = System.getProperty("file.separator");
|
||||||
|
String[] files = ds.getIncludedFiles();
|
||||||
|
for (String file : files) {
|
||||||
|
File f = new File(antlrLibDir + separator + file);
|
||||||
|
log("Found via ANTLR_HOME: " + f.getAbsolutePath(), Project.MSG_VERBOSE);
|
||||||
|
createClasspath().setLocation(f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute() throws BuildException {
|
||||||
|
|
||||||
|
validateAttributes();
|
||||||
|
|
||||||
|
// Use ANTLR itself to resolve dependencies and decide whether
|
||||||
|
// to invoke ANTLR for compilation
|
||||||
|
if (dependencyCheck()) {
|
||||||
|
populateAttributes();
|
||||||
|
commandline.createArgument().setValue(target.toString());
|
||||||
|
|
||||||
|
log(commandline.describeCommand(), Project.MSG_VERBOSE);
|
||||||
|
int err = 0;
|
||||||
|
try {
|
||||||
|
err = run(commandline.getCommandline(), new LogOutputStream(this, Project.MSG_INFO), new LogOutputStream(this, Project.MSG_WARN));
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new BuildException(e, getLocation());
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
bos.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
throw new BuildException("ANTLR returned: " + err, getLocation());
|
||||||
|
} else {
|
||||||
|
Pattern p = Pattern.compile("error\\([0-9]+\\):");
|
||||||
|
Matcher m = p.matcher(bos.toString());
|
||||||
|
if (m.find()) {
|
||||||
|
throw new BuildException("ANTLR signaled an error.", getLocation());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
try {
|
||||||
|
log("All dependencies of grammar file \'" + target.getCanonicalPath() + "\' are up to date.", Project.MSG_VERBOSE);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
log("All dependencies of grammar file \'" + target.toString() + "\' are up to date.", Project.MSG_VERBOSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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());
|
||||||
|
|
||||||
|
commandline.createArgument().setValue("-lib");
|
||||||
|
commandline.createArgument().setValue(libDirectory.toString());
|
||||||
|
|
||||||
|
if (superGrammar != null) {
|
||||||
|
log("Option 'glib' is not supported by ANTLR v3. Option ignored!", Project.MSG_WARN);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (diagnostic) {
|
||||||
|
commandline.createArgument().setValue("-diagnostic");
|
||||||
|
}
|
||||||
|
if (depend) {
|
||||||
|
log("Option 'depend' is implicitely always used by ANTLR v3. Option can safely be omitted!", Project.MSG_WARN);
|
||||||
|
}
|
||||||
|
if (trace) {
|
||||||
|
log("Option 'trace' is not supported by ANTLR v3. Option ignored!", Project.MSG_WARN);
|
||||||
|
}
|
||||||
|
if (traceParser) {
|
||||||
|
log("Option 'traceParser' is not supported by ANTLR v3. Option ignored!", Project.MSG_WARN);
|
||||||
|
}
|
||||||
|
if (traceLexer) {
|
||||||
|
log("Option 'traceLexer' is not supported by ANTLR v3. Option ignored!", Project.MSG_WARN);
|
||||||
|
}
|
||||||
|
if (debug) {
|
||||||
|
commandline.createArgument().setValue("-debug");
|
||||||
|
}
|
||||||
|
if (report) {
|
||||||
|
commandline.createArgument().setValue("-report");
|
||||||
|
}
|
||||||
|
if (print) {
|
||||||
|
commandline.createArgument().setValue("-print");
|
||||||
|
}
|
||||||
|
if (profile) {
|
||||||
|
commandline.createArgument().setValue("-profile");
|
||||||
|
}
|
||||||
|
if (messageFormatName != null) {
|
||||||
|
commandline.createArgument().setValue("-message-format");
|
||||||
|
commandline.createArgument().setValue(messageFormatName);
|
||||||
|
}
|
||||||
|
if (nfa) {
|
||||||
|
commandline.createArgument().setValue("-nfa");
|
||||||
|
}
|
||||||
|
if (dfa) {
|
||||||
|
commandline.createArgument().setValue("-dfa");
|
||||||
|
}
|
||||||
|
if (multiThreaded) {
|
||||||
|
commandline.createArgument().setValue("-Xmultithreaded");
|
||||||
|
}
|
||||||
|
if (nocollapse) {
|
||||||
|
commandline.createArgument().setValue("-Xnocollapse");
|
||||||
|
}
|
||||||
|
if (noprune) {
|
||||||
|
commandline.createArgument().setValue("-Xnoprune");
|
||||||
|
}
|
||||||
|
if (dbgST) {
|
||||||
|
commandline.createArgument().setValue("-XdbgST");
|
||||||
|
}
|
||||||
|
if (conversiontimeout != null) {
|
||||||
|
commandline.createArgument().setValue("-Xconversiontimeout");
|
||||||
|
commandline.createArgument().setValue(conversiontimeout);
|
||||||
|
}
|
||||||
|
if (grammarTree) {
|
||||||
|
commandline.createArgument().setValue("-Xgrtree");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateAttributes() throws BuildException {
|
||||||
|
|
||||||
|
if (target == null) {
|
||||||
|
throw new BuildException("No target grammar, lexer grammar or tree parser specified!");
|
||||||
|
} else if (!target.isFile()) {
|
||||||
|
throw new BuildException("Target: " + target + " is not a file!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no output directory is specified, use the target's directory
|
||||||
|
if (outputDirectory == null) {
|
||||||
|
setOutputdirectory(new File(target.getParent()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!outputDirectory.isDirectory()) {
|
||||||
|
throw new BuildException("Invalid output directory: " + outputDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (workingdir != null && !workingdir.isDirectory()) {
|
||||||
|
throw new BuildException("Invalid working directory: " + workingdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no libDirectory is specified, use the target's directory
|
||||||
|
if (libDirectory == null) {
|
||||||
|
setLibdirectory(new File(target.getParent()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!libDirectory.isDirectory()) {
|
||||||
|
throw new BuildException("Invalid lib directory: " + libDirectory);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean dependencyCheck() throws BuildException {
|
||||||
|
// using "antlr -o <OutputDirectory> -lib <LibDirectory> -depend <T>"
|
||||||
|
// to get the list of dependencies
|
||||||
|
CommandlineJava cmdline;
|
||||||
|
try {
|
||||||
|
cmdline = (CommandlineJava) commandline.clone();
|
||||||
|
} catch (java.lang.CloneNotSupportedException e) {
|
||||||
|
throw new BuildException("Clone of commandline failed: " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
cmdline.createArgument().setValue("-depend");
|
||||||
|
cmdline.createArgument().setValue("-o");
|
||||||
|
cmdline.createArgument().setValue(outputDirectory.toString());
|
||||||
|
cmdline.createArgument().setValue("-lib");
|
||||||
|
cmdline.createArgument().setValue(libDirectory.toString());
|
||||||
|
cmdline.createArgument().setValue(target.toString());
|
||||||
|
|
||||||
|
log(cmdline.describeCommand(), Project.MSG_VERBOSE);
|
||||||
|
|
||||||
|
// redirect output generated by ANTLR to temporary file
|
||||||
|
Redirector r = new Redirector(this);
|
||||||
|
File f;
|
||||||
|
try {
|
||||||
|
f = File.createTempFile("depend", null, getOutputdirectory());
|
||||||
|
f.deleteOnExit();
|
||||||
|
log("Write dependencies for '" + target.toString() + "' to file '" + f.getCanonicalPath() + "'", Project.MSG_VERBOSE);
|
||||||
|
r.setOutput(f);
|
||||||
|
r.setAlwaysLog(false);
|
||||||
|
r.createStreams();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new BuildException("Redirection of output failed: " + e);
|
||||||
|
}
|
||||||
|
|
||||||
|
// execute antlr -depend ...
|
||||||
|
int err = 0;
|
||||||
|
try {
|
||||||
|
err = run(cmdline.getCommandline(), r.getOutputStream(), null);
|
||||||
|
} catch (IOException e) {
|
||||||
|
try {
|
||||||
|
r.complete();
|
||||||
|
log("Redirection of output terminated.", Project.MSG_VERBOSE);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
log("Termination of output redirection failed: " + ex, Project.MSG_ERR);
|
||||||
|
}
|
||||||
|
throw new BuildException(e, getLocation());
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
bos.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
// ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
r.complete();
|
||||||
|
log("Redirection of output terminated.", Project.MSG_VERBOSE);
|
||||||
|
} catch (IOException e) {
|
||||||
|
log("Termination of output redirection failed: " + e, Project.MSG_ERR);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (err != 0) {
|
||||||
|
if (f.exists()) {
|
||||||
|
f.delete();
|
||||||
|
}
|
||||||
|
if (cmdline.getClasspath() == null) {
|
||||||
|
log("Antlr libraries not found in external classpath or embedded classpath statement ", Project.MSG_ERR);
|
||||||
|
}
|
||||||
|
log("Dependency check failed. ANTLR returned: " + err, Project.MSG_ERR);
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
Pattern p = Pattern.compile("error\\([0-9]+\\):");
|
||||||
|
Matcher m = p.matcher(bos.toString());
|
||||||
|
if (m.find()) {
|
||||||
|
if (f.exists()) {
|
||||||
|
f.delete();
|
||||||
|
}
|
||||||
|
// On error always recompile
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean compile = false;
|
||||||
|
|
||||||
|
// open temporary file
|
||||||
|
BufferedReader in = null;
|
||||||
|
try {
|
||||||
|
in = new BufferedReader(new FileReader(f));
|
||||||
|
} catch (IOException e) {
|
||||||
|
try {
|
||||||
|
if (in != null) {
|
||||||
|
in.close();
|
||||||
|
}
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new BuildException("Could not close file\'" + f.toString() + "\'.");
|
||||||
|
}
|
||||||
|
if (f.exists()) {
|
||||||
|
f.delete();
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
throw new BuildException("Could not open \'" + f.getCanonicalPath() + "\' for reading.");
|
||||||
|
} catch (IOException ex) {
|
||||||
|
throw new BuildException("Could not open \'" + f.toString() + "\' for reading.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// evaluate dependencies in temporary file
|
||||||
|
String s;
|
||||||
|
|
||||||
|
try {
|
||||||
|
while ((s = in.readLine()) != null) {
|
||||||
|
String a;
|
||||||
|
String b;
|
||||||
|
// As the separator string in lines emitted by the depend option
|
||||||
|
// is either " : " or ": " trim is invoked for the first file name of a line
|
||||||
|
int to = s.indexOf(": ");
|
||||||
|
if (to >= 0) {
|
||||||
|
a = s.substring(0, to).trim();
|
||||||
|
File lhs = new File(a);
|
||||||
|
if (!lhs.isFile()) {
|
||||||
|
log("File '" + a + "' is not a regular file", Project.MSG_VERBOSE);
|
||||||
|
String name = lhs.getName();
|
||||||
|
String[] parts = splitRightHandSide(name, "\\u002E");
|
||||||
|
if (parts.length <= 1) {
|
||||||
|
a += ".java";
|
||||||
|
lhs = new File(a);
|
||||||
|
if (lhs.isFile()) {
|
||||||
|
log("File '" + a + "' is a regular file last modified at " + lhs.lastModified(), Project.MSG_VERBOSE);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
b = s.substring(to + ": ".length());
|
||||||
|
String[] names = splitRightHandSide(b, ", ?");
|
||||||
|
File aFile = new File(a);
|
||||||
|
for (String name : names) {
|
||||||
|
File bFile = new File(name);
|
||||||
|
log("File '" + a + "' depends on file '" + name + "'", Project.MSG_VERBOSE);
|
||||||
|
log("File '" + a + "' modified at " + aFile.lastModified(), Project.MSG_VERBOSE);
|
||||||
|
log("File '" + name + "' modified at " + bFile.lastModified(), Project.MSG_VERBOSE);
|
||||||
|
if (fileUtils.isUpToDate(aFile, bFile)) {
|
||||||
|
log("Compiling " + target + " as '" + name + "' is newer than '" + a + "'", Project.MSG_VERBOSE);
|
||||||
|
// Feeling not quite comfortable with touching the file
|
||||||
|
fileUtils.setFileLastModified(aFile, -1);
|
||||||
|
log("Touching file '" + a + "'", Project.MSG_VERBOSE);
|
||||||
|
compile = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (compile) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
in.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
if (f.exists()) {
|
||||||
|
f.delete();
|
||||||
|
}
|
||||||
|
throw new BuildException("Error reading file '" + f.toString() + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (f.exists()) {
|
||||||
|
f.delete();
|
||||||
|
}
|
||||||
|
|
||||||
|
return compile;
|
||||||
|
}
|
||||||
|
|
||||||
|
private String[] splitRightHandSide(String fileNames, String pattern) {
|
||||||
|
String[] names = fileNames.split(pattern);
|
||||||
|
for (String name : names) {
|
||||||
|
log("Split right hand side '" + name + "'", Project.MSG_VERBOSE);
|
||||||
|
}
|
||||||
|
return names;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** execute in a forked VM */
|
||||||
|
private int run(String[] command, OutputStream out, OutputStream err) throws IOException {
|
||||||
|
PumpStreamHandler psh;
|
||||||
|
if (err == null) {
|
||||||
|
psh = new PumpStreamHandler(out, bos);
|
||||||
|
} else {
|
||||||
|
psh = new PumpStreamHandler(out, new TeeOutputStream(err, bos));
|
||||||
|
}
|
||||||
|
|
||||||
|
Execute exe = new Execute(psh, null);
|
||||||
|
|
||||||
|
exe.setAntRun(getProject());
|
||||||
|
if (workingdir != null) {
|
||||||
|
exe.setWorkingDirectory(workingdir);
|
||||||
|
}
|
||||||
|
|
||||||
|
exe.setCommandline(command);
|
||||||
|
|
||||||
|
return exe.execute();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,7 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<antlib>
|
||||||
|
<taskdef
|
||||||
|
name="antlr3"
|
||||||
|
classname="org.apache.tools.ant.antlr.ANTLR3"
|
||||||
|
/>
|
||||||
|
</antlib>
|
Binary file not shown.
1957
outside/antlr3-antlr-3.5/antlr-ant/main/antlr3-task/antlr3-task.htm
Normal file
1957
outside/antlr3-antlr-3.5/antlr-ant/main/antlr3-task/antlr3-task.htm
Normal file
File diff suppressed because it is too large
Load Diff
BIN
outside/antlr3-antlr-3.5/antlr-ant/main/antlr3-task/antlr3.jar
Normal file
BIN
outside/antlr3-antlr-3.5/antlr-ant/main/antlr3-task/antlr3.jar
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
outside/antlr3-antlr-3.5/antlr-ant/main/antlr3-task/d2u.zip
Normal file
BIN
outside/antlr3-antlr-3.5/antlr-ant/main/antlr3-task/d2u.zip
Normal file
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
144
outside/antlr3-antlr-3.5/antlr-complete/pom.xml
Normal file
144
outside/antlr3-antlr-3.5/antlr-complete/pom.xml
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>antlr-complete</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>ANTLR 3 Complete</name>
|
||||||
|
<description>Complete distribution for ANTLR 3</description>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Inherit from the ANTLR master pom, which tells us what
|
||||||
|
version we are and allows us to inherit dependencies
|
||||||
|
and so on.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<parent>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr-master</artifactId>
|
||||||
|
<version>3.5</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<url>http://antlr.org/</url>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The complete distribution includes the following modules and their dependencies:
|
||||||
|
ANTLR 3 Tool
|
||||||
|
ANTLR 3 Runtime
|
||||||
|
gUnit for ANTLR 3
|
||||||
|
StringTemplate 4 (dependency of code generator in the ANTLR 3 Tool)
|
||||||
|
StringTemplate 3 (dependency of grammars with output=template)
|
||||||
|
ANTLR 2.7.7 (dependency of template parser in StringTemplate 3)
|
||||||
|
-->
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr-runtime</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>gunit</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr3-maven-plugin</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<configuration></configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>antlr</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-shade-plugin</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
<configuration>
|
||||||
|
<minimizeJar>false</minimizeJar>
|
||||||
|
<createSourcesJar>true</createSourcesJar>
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>org.antlr:antlr-complete</artifact>
|
||||||
|
<includes>
|
||||||
|
<include>META-INF/**</include>
|
||||||
|
</includes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
|
<transformers>
|
||||||
|
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
|
||||||
|
<mainClass>org.antlr.Tool</mainClass>
|
||||||
|
</transformer>
|
||||||
|
</transformers>
|
||||||
|
</configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>complete-no-st3</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
<shadedArtifactAttached>true</shadedArtifactAttached>
|
||||||
|
<shadedClassifierName>no-st3</shadedClassifierName>
|
||||||
|
<filters>
|
||||||
|
<filter>
|
||||||
|
<artifact>antlr:antlr</artifact>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
<filter>
|
||||||
|
<artifact>org.antlr:stringtemplate</artifact>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**</exclude>
|
||||||
|
</excludes>
|
||||||
|
</filter>
|
||||||
|
</filters>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
|
||||||
|
<execution>
|
||||||
|
<id>complete</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>shade</goal>
|
||||||
|
</goals>
|
||||||
|
<configuration>
|
||||||
|
<createDependencyReducedPom>false</createDependencyReducedPom>
|
||||||
|
<shadedArtifactAttached>false</shadedArtifactAttached>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
0
outside/antlr3-antlr-3.5/antlr.config
Normal file
0
outside/antlr3-antlr-3.5/antlr.config
Normal file
50
outside/antlr3-antlr-3.5/antlr3-maven-archetype/pom.xml
Normal file
50
outside/antlr3-antlr-3.5/antlr3-maven-archetype/pom.xml
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||||
|
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr3-maven-archetype</artifactId>
|
||||||
|
<packaging>maven-archetype</packaging>
|
||||||
|
<name>ANTLR 3 Maven Archetype</name>
|
||||||
|
<description>ANTLR 3 Maven Archetype</description>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Inherit from the ANTLR master pom, which tells us what
|
||||||
|
version we are and allows us to inherit dependencies
|
||||||
|
and so on.
|
||||||
|
-->
|
||||||
|
<parent>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr-master</artifactId>
|
||||||
|
<version>3.5</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
|
||||||
|
<extensions>
|
||||||
|
|
||||||
|
<extension>
|
||||||
|
<groupId>org.apache.maven.archetype</groupId>
|
||||||
|
<artifactId>archetype-packaging</artifactId>
|
||||||
|
<version>2.2</version>
|
||||||
|
</extension>
|
||||||
|
|
||||||
|
</extensions>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-archetype-plugin</artifactId>
|
||||||
|
<version>2.2</version>
|
||||||
|
<extensions>true</extensions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,25 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?><archetype-descriptor name="antlr3-maven-archetype">
|
||||||
|
<fileSets>
|
||||||
|
<fileSet filtered="true" packaged="true" encoding="UTF-8">
|
||||||
|
<directory>src/main/java</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*.java</include>
|
||||||
|
</includes>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet filtered="true" packaged="true" encoding="UTF-8">
|
||||||
|
<directory>src/main/antlr3</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*.g</include>
|
||||||
|
</includes>
|
||||||
|
<excludes>
|
||||||
|
<exclude>**/imports/*.*</exclude>
|
||||||
|
</excludes>
|
||||||
|
</fileSet>
|
||||||
|
<fileSet filtered="true" encoding="UTF-8">
|
||||||
|
<directory>src/main/antlr3/imports</directory>
|
||||||
|
<includes>
|
||||||
|
<include>**/*.g</include>
|
||||||
|
</includes>
|
||||||
|
</fileSet>
|
||||||
|
</fileSets>
|
||||||
|
</archetype-descriptor>
|
@ -0,0 +1,15 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<archetype>
|
||||||
|
<id>antlr3-maven-archetype</id>
|
||||||
|
<sources>
|
||||||
|
<source>src\main\java\org\antlr\demo\AbstractTLexer.java</source>
|
||||||
|
<source>src\main\java\org\antlr\demo\AbstractTParser.java</source>
|
||||||
|
<source>src\main\java\org\antlr\demo\Main.java</source>
|
||||||
|
</sources>
|
||||||
|
<resources>
|
||||||
|
<resource>src\main\antlr3\imports\Ruleb.g</resource>
|
||||||
|
<resource>src\main\antlr3\TLexer.g</resource>
|
||||||
|
<resource>src\main\antlr3\TParser.g</resource>
|
||||||
|
<resource>src\main\antlr3\TTree.g</resource>
|
||||||
|
</resources>
|
||||||
|
</archetype>
|
@ -0,0 +1,182 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<!-- =======================================================================
|
||||||
|
A quickstart pom.xml that creates a sample project that uses ANTLR 3.x
|
||||||
|
grammars. You should replace the sample grammars in src/main/antlr3
|
||||||
|
with your own grammar files and use packages.
|
||||||
|
|
||||||
|
A .g file in
|
||||||
|
|
||||||
|
src/main/antlr3/com/temporalwave
|
||||||
|
|
||||||
|
belongs in the package
|
||||||
|
|
||||||
|
com.temporalwave
|
||||||
|
|
||||||
|
See http://antlr.org/antlr3-maven-plugin for more details.
|
||||||
|
|
||||||
|
This project produces both a jar file of the project and an executeable
|
||||||
|
jar file that contains all the dependencies so you can run it standalone.
|
||||||
|
See below for more details.
|
||||||
|
|
||||||
|
Archetype by Jim Idle (jimi@temporal-wave.com) - Oct 2009
|
||||||
|
Report bugs to the ANTLR interest list at http://www.antlr.org
|
||||||
|
|
||||||
|
Generated by antlr3-maven-archetype version 3.4.1-SNAPSHOT
|
||||||
|
=======================================================================
|
||||||
|
-->
|
||||||
|
|
||||||
|
<!-- This is your organizations normal group name
|
||||||
|
such as org.antlr
|
||||||
|
All the artifacts you create will be under this
|
||||||
|
group id.
|
||||||
|
-->
|
||||||
|
<groupId>${groupId}</groupId>
|
||||||
|
|
||||||
|
<!-- This is how maven knows your artifact
|
||||||
|
-->
|
||||||
|
<artifactId>${artifactId}</artifactId>
|
||||||
|
|
||||||
|
<!-- This is the human oriented name for the package
|
||||||
|
so you can call it anything you like
|
||||||
|
-->
|
||||||
|
<name>ANTLR3 project: ${package}</name>
|
||||||
|
|
||||||
|
<!-- This is the version of YOUR project -->
|
||||||
|
<version>${version}</version>
|
||||||
|
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
<url>http://antlr.org</url>
|
||||||
|
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
We need to have the ANTLR runtime jar when running and compiling.
|
||||||
|
-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr-runtime</artifactId>
|
||||||
|
<version>3.4.1-SNAPSHOT</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Tell Maven which other artifacts we need in order to
|
||||||
|
build with the ANTLR Tool. Here we also make the default
|
||||||
|
goal be install so that you can just type mvn at the command
|
||||||
|
line instead of mvn install. And we add the java compiler plugin
|
||||||
|
for convenience to show how you can use 1.6 source files but
|
||||||
|
generate 1.4 compatible .class files (as few people seem to
|
||||||
|
know about the jsr14 target).
|
||||||
|
-->
|
||||||
|
<build>
|
||||||
|
|
||||||
|
<defaultGoal>install</defaultGoal>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr3-maven-plugin</artifactId>
|
||||||
|
<version>3.4.1-SNAPSHOT</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>antlr</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Strictly speaking, we did not need to generate this for you from
|
||||||
|
the prototype, but we use it to illustrate how you can get
|
||||||
|
the JDK 6 Java compiler to accept 1.5 or 1.6 targeted source code
|
||||||
|
but produce class files that are compatible with JRE 1.4. As
|
||||||
|
Michael Caine might say, "Not a lot of people know that!"
|
||||||
|
-->
|
||||||
|
<plugin>
|
||||||
|
<artifactId>maven-compiler-plugin</artifactId>
|
||||||
|
<version>2.0.2</version>
|
||||||
|
<configuration>
|
||||||
|
<source>1.6</source>
|
||||||
|
<target>jsr14</target>
|
||||||
|
<sourceDirectory>src</sourceDirectory>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Build an uber-jar that is packaged with all the other dependencies,
|
||||||
|
such as the antlr-runtime and so on. This will be useful
|
||||||
|
for developers, who then do not need to download anything else or
|
||||||
|
remember that they need antlr.jar in their CLASSPATH and so
|
||||||
|
on.
|
||||||
|
|
||||||
|
You can delete this plugin of course and you will then
|
||||||
|
get a jar file with only the code generated and included
|
||||||
|
directly in this project. With this plugin though you will
|
||||||
|
find that when you build with:
|
||||||
|
|
||||||
|
mvn install
|
||||||
|
|
||||||
|
There will be an executable jar generated. You can run this
|
||||||
|
as:
|
||||||
|
|
||||||
|
java -jar ${artifactId}-${version}-jar-with-dependencies.jar demosource.dmo
|
||||||
|
|
||||||
|
assuming you have a file called demosource.dmo to attempt a parse.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<artifactId>maven-assembly-plugin</artifactId>
|
||||||
|
|
||||||
|
<configuration>
|
||||||
|
<descriptorRefs>
|
||||||
|
<descriptorRef>jar-with-dependencies</descriptorRef>
|
||||||
|
</descriptorRefs>
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Specify that we want the resulting jar to be executable
|
||||||
|
via java -jar, which we do by modifying the manifest
|
||||||
|
of course.
|
||||||
|
-->
|
||||||
|
<archive>
|
||||||
|
|
||||||
|
<manifest>
|
||||||
|
<mainClass>${package}.Main</mainClass>
|
||||||
|
</manifest>
|
||||||
|
</archive>
|
||||||
|
|
||||||
|
</configuration>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
We don't want to have to specifically ask for the uber jar, so we attach the
|
||||||
|
running of this plugin to the execution of the package life-cycle
|
||||||
|
phase.
|
||||||
|
-->
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>make-assembly</id>
|
||||||
|
<phase>package</phase>
|
||||||
|
<goals>
|
||||||
|
<goal>attached</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,80 @@
|
|||||||
|
// This is a sample lexer generated by the ANTLR3 Maven Archetype
|
||||||
|
// generator. It shows how to use a superclass to implement
|
||||||
|
// support methods and variables you may use in the lexer actions
|
||||||
|
// rather than create a messy lexer that has the Java code embedded
|
||||||
|
// in it.
|
||||||
|
//
|
||||||
|
|
||||||
|
lexer grammar TLexer;
|
||||||
|
|
||||||
|
options {
|
||||||
|
|
||||||
|
language=Java; // Default
|
||||||
|
|
||||||
|
// Tell ANTLR to make the generated lexer class extend the
|
||||||
|
// the named class, which is where any supporting code and
|
||||||
|
// variables will be placed.
|
||||||
|
//
|
||||||
|
superClass = AbstractTLexer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// What package should the generated source exist in?
|
||||||
|
//
|
||||||
|
@header {
|
||||||
|
|
||||||
|
package ${package};
|
||||||
|
}
|
||||||
|
|
||||||
|
// This is just a simple lexer that matches the usual suspects
|
||||||
|
//
|
||||||
|
|
||||||
|
KEYSER : 'Keyser' ;
|
||||||
|
SOZE : 'Soze' ;
|
||||||
|
|
||||||
|
ADD : '+' ;
|
||||||
|
SEMI: ';' ;
|
||||||
|
|
||||||
|
ID : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
|
||||||
|
;
|
||||||
|
|
||||||
|
INT : '0'..'9'+
|
||||||
|
;
|
||||||
|
|
||||||
|
COMMENT
|
||||||
|
: '//' ~('\n'|'\r')* '\r'? '\n' {skip();}
|
||||||
|
| '/*' ( options {greedy=false;} : . )* '*/' {skip();}
|
||||||
|
;
|
||||||
|
|
||||||
|
WS : ( ' '
|
||||||
|
| '\t'
|
||||||
|
| '\r'
|
||||||
|
| '\n'
|
||||||
|
) {skip();}
|
||||||
|
;
|
||||||
|
|
||||||
|
STRING
|
||||||
|
: '"' ( ESC_SEQ | ~('\\'|'"') )* '"'
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
ESC_SEQ
|
||||||
|
: '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
|
||||||
|
| UNICODE_ESC
|
||||||
|
| OCTAL_ESC
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
OCTAL_ESC
|
||||||
|
: '\\' ('0'..'3') ('0'..'7') ('0'..'7')
|
||||||
|
| '\\' ('0'..'7') ('0'..'7')
|
||||||
|
| '\\' ('0'..'7')
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
UNICODE_ESC
|
||||||
|
: '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
|
||||||
|
;
|
||||||
|
|
@ -0,0 +1,74 @@
|
|||||||
|
parser grammar TParser;
|
||||||
|
|
||||||
|
options {
|
||||||
|
|
||||||
|
// Default language but name it anyway
|
||||||
|
//
|
||||||
|
language = Java;
|
||||||
|
|
||||||
|
// Produce an AST
|
||||||
|
//
|
||||||
|
output = AST;
|
||||||
|
|
||||||
|
// Use a superclass to implement all helper
|
||||||
|
// methods, instance variables and overrides
|
||||||
|
// of ANTLR default methods, such as error
|
||||||
|
// handling.
|
||||||
|
//
|
||||||
|
superClass = AbstractTParser;
|
||||||
|
|
||||||
|
// Use the vocabulary generated by the accompanying
|
||||||
|
// lexer. Maven knows how to work out the relationship
|
||||||
|
// between the lexer and parser and will build the
|
||||||
|
// lexer before the parser. It will also rebuild the
|
||||||
|
// parser if the lexer changes.
|
||||||
|
//
|
||||||
|
tokenVocab = TLexer;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Import a grammar file, even though it does not really need it in this
|
||||||
|
// simle demo parser. We do the import to show where imported grammars should be
|
||||||
|
// stored for maven builds.
|
||||||
|
//
|
||||||
|
import Ruleb;
|
||||||
|
|
||||||
|
// Some imaginary tokens for tree rewrites
|
||||||
|
//
|
||||||
|
tokens {
|
||||||
|
SCRIPT;
|
||||||
|
}
|
||||||
|
|
||||||
|
// What package should the generated source exist in?
|
||||||
|
//
|
||||||
|
@header {
|
||||||
|
|
||||||
|
package ${package};
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// This is just a simple parser for demo purpose
|
||||||
|
//
|
||||||
|
a : b* EOF
|
||||||
|
|
||||||
|
-> ^(SCRIPT b*)
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
keyser
|
||||||
|
: KEYSER^ SOZE
|
||||||
|
;
|
||||||
|
|
||||||
|
expression
|
||||||
|
: addExpr (ADD^ addExpr)*
|
||||||
|
;
|
||||||
|
|
||||||
|
addExpr
|
||||||
|
: ID
|
||||||
|
| INT
|
||||||
|
| STRING
|
||||||
|
;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,49 @@
|
|||||||
|
tree grammar TTree;
|
||||||
|
|
||||||
|
options {
|
||||||
|
|
||||||
|
// Default but name it anyway
|
||||||
|
//
|
||||||
|
language = Java;
|
||||||
|
|
||||||
|
// Use the vocab from the parser (not the lexer)
|
||||||
|
// The ANTLR Maven plugin knows how to work out the
|
||||||
|
// relationships between the .g files and it will build
|
||||||
|
// the tree parser after the parser. It will also rebuild
|
||||||
|
// the tree parser if the parser is rebuilt.
|
||||||
|
//
|
||||||
|
tokenVocab = TParser;
|
||||||
|
|
||||||
|
// Use ANTLR built-in CommonToken for tree nodes
|
||||||
|
//
|
||||||
|
ASTLabelType = CommonToken;
|
||||||
|
}
|
||||||
|
|
||||||
|
// What package should the generated source exist in?
|
||||||
|
//
|
||||||
|
@header {
|
||||||
|
|
||||||
|
package ${package};
|
||||||
|
}
|
||||||
|
|
||||||
|
a : ^(SCRIPT stuff+)
|
||||||
|
| SCRIPT
|
||||||
|
;
|
||||||
|
|
||||||
|
stuff
|
||||||
|
: keyser
|
||||||
|
| expression
|
||||||
|
;
|
||||||
|
|
||||||
|
keyser
|
||||||
|
: ^(KEYSER SOZE)
|
||||||
|
{ System.out.println("Found Keyser Soze!!"); }
|
||||||
|
;
|
||||||
|
|
||||||
|
expression
|
||||||
|
: ^(ADD expression expression)
|
||||||
|
| ID
|
||||||
|
| INT
|
||||||
|
| STRING
|
||||||
|
;
|
||||||
|
|
@ -0,0 +1,11 @@
|
|||||||
|
// A single rule in a grammar that must be imported by the demo
|
||||||
|
// parser Tparser.g
|
||||||
|
// This is just here to show that import grammars are stored in their
|
||||||
|
// own imports directory: src/main/antlr3/imports
|
||||||
|
//
|
||||||
|
parser grammar Ruleb;
|
||||||
|
|
||||||
|
b
|
||||||
|
: keyser SEMI!
|
||||||
|
| expression SEMI!
|
||||||
|
;
|
@ -0,0 +1,55 @@
|
|||||||
|
#set( $symbol_pound = '#' )
|
||||||
|
#set( $symbol_dollar = '$' )
|
||||||
|
#set( $symbol_escape = '\' )
|
||||||
|
package ${package};
|
||||||
|
|
||||||
|
import org.antlr.runtime.CharStream;
|
||||||
|
import org.antlr.runtime.Lexer;
|
||||||
|
import org.antlr.runtime.RecognizerSharedState;
|
||||||
|
|
||||||
|
/**
|
||||||
|
|
||||||
|
* This is the super class for the lexer. It is extended by the lexer class
|
||||||
|
* generated from TLexer.g.
|
||||||
|
*
|
||||||
|
* Do not place code and declarations in the lexer .g files, use
|
||||||
|
* a superclass like this and place all the support methods and
|
||||||
|
* error overrides etc in the super class. This way you will keep
|
||||||
|
* the lexer grammar clean and hunky dory.
|
||||||
|
*
|
||||||
|
* @author Jim Idle - Temporal Wave LLC (jimi@idle.ws)
|
||||||
|
*/
|
||||||
|
public abstract class AbstractTLexer
|
||||||
|
extends Lexer
|
||||||
|
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Default constructor for the lexer, when you do not yet know what
|
||||||
|
* the character stream to be provided is.
|
||||||
|
*/
|
||||||
|
public AbstractTLexer() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new instance of the lexer using the given character stream as
|
||||||
|
* the input to lex into tokens.
|
||||||
|
*
|
||||||
|
* @param input A valid character stream that contains the ruleSrc code you
|
||||||
|
* wish to compile (or lex at least)
|
||||||
|
*/
|
||||||
|
public AbstractTLexer(CharStream input) {
|
||||||
|
this(input, new RecognizerSharedState());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Internal constructor for ANTLR - do not use.
|
||||||
|
*
|
||||||
|
* @param input The character stream we are going to lex
|
||||||
|
* @param state The shared state object, shared between all lexer comonents
|
||||||
|
*/
|
||||||
|
public AbstractTLexer(CharStream input, RecognizerSharedState state) {
|
||||||
|
super(input,state);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,64 @@
|
|||||||
|
#set( $symbol_pound = '#' )
|
||||||
|
#set( $symbol_dollar = '$' )
|
||||||
|
#set( $symbol_escape = '\' )
|
||||||
|
package ${package};
|
||||||
|
|
||||||
|
import org.antlr.runtime.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The super class of the generated parser. It is extended by the generated
|
||||||
|
* code because of the superClass optoin in the .g file.
|
||||||
|
*
|
||||||
|
* This class contains any helper functions used within the parser
|
||||||
|
* grammar itself, as well as any overrides of the standard ANTLR Java
|
||||||
|
* runtime methods, such as an implementation of a custom error reporting
|
||||||
|
* method, symbol table populating methods and so on.
|
||||||
|
*
|
||||||
|
* @author Jim Idle - Temporal Wave LLC - jimi@temporal-wave.com
|
||||||
|
*/
|
||||||
|
public abstract class AbstractTParser
|
||||||
|
|
||||||
|
extends Parser
|
||||||
|
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Create a new parser instance, pre-supplying the input token stream.
|
||||||
|
*
|
||||||
|
* @param input The stream of tokens that will be pulled from the lexer
|
||||||
|
*/
|
||||||
|
protected AbstractTParser(TokenStream input) {
|
||||||
|
super(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a new parser instance, pre-supplying the input token stream
|
||||||
|
* and the shared state.
|
||||||
|
*
|
||||||
|
* This is only used when a grammar is imported into another grammar, but
|
||||||
|
* we must supply this constructor to satisfy the super class contract.
|
||||||
|
*
|
||||||
|
* @param input The stream of tokesn that will be pulled from the lexer
|
||||||
|
* @param state The shared state object created by an interconnectd grammar
|
||||||
|
*/
|
||||||
|
protected AbstractTParser(TokenStream input, RecognizerSharedState state) {
|
||||||
|
super(input, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates the error/warning message that we need to show users/IDEs when
|
||||||
|
* ANTLR has found a parsing error, has recovered from it and is now
|
||||||
|
* telling us that a parsing exception occurred.
|
||||||
|
*
|
||||||
|
* @param tokenNames token names as known by ANTLR (which we ignore)
|
||||||
|
* @param e The exception that was thrown
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public void displayRecognitionError(String[] tokenNames, RecognitionException e) {
|
||||||
|
|
||||||
|
// This is just a place holder that shows how to override this method
|
||||||
|
//
|
||||||
|
super.displayRecognitionError(tokenNames, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,250 @@
|
|||||||
|
#set( $symbol_pound = '#' )
|
||||||
|
#set( $symbol_dollar = '$' )
|
||||||
|
#set( $symbol_escape = '\' )
|
||||||
|
package ${package};
|
||||||
|
|
||||||
|
import org.antlr.runtime.*;
|
||||||
|
import org.antlr.runtime.tree.*;
|
||||||
|
import org.antlr.stringtemplate.*;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import ${package}.TParser.a_return;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Test driver program for the ANTLR3 Maven Architype demo
|
||||||
|
*
|
||||||
|
* @author Jim Idle (jimi@temporal-wave.com)
|
||||||
|
*/
|
||||||
|
class Main {
|
||||||
|
|
||||||
|
private static boolean makeDot = false;
|
||||||
|
|
||||||
|
static TLexer lexer;
|
||||||
|
|
||||||
|
/** Just a simple test driver for the ASP parser
|
||||||
|
* to show how to call it.
|
||||||
|
*/
|
||||||
|
|
||||||
|
public static void main(String[] args)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Create the lexer, which we can keep reusing if we like
|
||||||
|
//
|
||||||
|
lexer = new TLexer();
|
||||||
|
|
||||||
|
if (args.length > 0)
|
||||||
|
{
|
||||||
|
int s = 0;
|
||||||
|
|
||||||
|
if (args[0].startsWith("-dot"))
|
||||||
|
{
|
||||||
|
makeDot = true;
|
||||||
|
s = 1;
|
||||||
|
}
|
||||||
|
// Recursively parse each directory, and each file on the
|
||||||
|
// command line
|
||||||
|
//
|
||||||
|
for (int i=s; i<args.length; i++)
|
||||||
|
{
|
||||||
|
parse(new File(args[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
System.err.println("Usage: java -jar ${artifactId}-${version}-jar-with-dependencies.jar <directory | filename.dmo>");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.err.println("ANTLR demo parser threw exception:");
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void parse(File source) throws Exception
|
||||||
|
{
|
||||||
|
|
||||||
|
// Open the supplied file or directory
|
||||||
|
//
|
||||||
|
try
|
||||||
|
{
|
||||||
|
|
||||||
|
// From here, any exceptions are just thrown back up the chain
|
||||||
|
//
|
||||||
|
if (source.isDirectory())
|
||||||
|
{
|
||||||
|
System.out.println("Directory: " + source.getAbsolutePath());
|
||||||
|
String files[] = source.list();
|
||||||
|
|
||||||
|
for (int i=0; i<files.length; i++)
|
||||||
|
{
|
||||||
|
parse(new File(source, files[i]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else find out if it is an ASP.Net file and parse it if it is
|
||||||
|
//
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// File without paths etc
|
||||||
|
//
|
||||||
|
String sourceFile = source.getName();
|
||||||
|
|
||||||
|
if (sourceFile.length() > 3)
|
||||||
|
{
|
||||||
|
String suffix = sourceFile.substring(sourceFile.length()-4).toLowerCase();
|
||||||
|
|
||||||
|
// Ensure that this is a DEMO script (or seemingly)
|
||||||
|
//
|
||||||
|
if (suffix.compareTo(".dmo") == 0)
|
||||||
|
{
|
||||||
|
parseSource(source.getAbsolutePath());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
System.err.println("ANTLR demo parser caught error on file open:");
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void parseSource(String source) throws Exception
|
||||||
|
{
|
||||||
|
// Parse an ANTLR demo file
|
||||||
|
//
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// First create a file stream using the povided file/path
|
||||||
|
// and tell the lexer that that is the character source.
|
||||||
|
// You can also use text that you have already read of course
|
||||||
|
// by using the string stream.
|
||||||
|
//
|
||||||
|
lexer.setCharStream(new ANTLRFileStream(source, "UTF8"));
|
||||||
|
|
||||||
|
// Using the lexer as the token source, we create a token
|
||||||
|
// stream to be consumed by the parser
|
||||||
|
//
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
|
||||||
|
// Now we need an instance of our parser
|
||||||
|
//
|
||||||
|
TParser parser = new TParser(tokens);
|
||||||
|
|
||||||
|
System.out.println("file: " + source);
|
||||||
|
|
||||||
|
// Provide some user feedback
|
||||||
|
//
|
||||||
|
System.out.println(" Lexer Start");
|
||||||
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
|
// Force token load and lex (don't do this normally,
|
||||||
|
// it is just for timing the lexer)
|
||||||
|
//
|
||||||
|
tokens.LT(1);
|
||||||
|
long lexerStop = System.currentTimeMillis();
|
||||||
|
System.out.println(" lexed in " + (lexerStop - start) + "ms.");
|
||||||
|
|
||||||
|
// And now we merely invoke the start rule for the parser
|
||||||
|
//
|
||||||
|
System.out.println(" Parser Start");
|
||||||
|
long pStart = System.currentTimeMillis();
|
||||||
|
a_return psrReturn = parser.a();
|
||||||
|
long stop = System.currentTimeMillis();
|
||||||
|
System.out.println(" Parsed in " + (stop - pStart) + "ms.");
|
||||||
|
|
||||||
|
// If we got a valid a tree (the syntactic validity of the source code
|
||||||
|
// was found to be solid), then let's print the tree to show we
|
||||||
|
// did something; our testing public wants to know!
|
||||||
|
// We do something fairly cool here and generate a graphviz/dot
|
||||||
|
// specification for the tree, which will allow the users to visualize
|
||||||
|
// it :-) we only do that if asked via the -dot option though as not
|
||||||
|
// all users will hsve installed the graphviz toolset from
|
||||||
|
// http://www.graphviz.org
|
||||||
|
//
|
||||||
|
|
||||||
|
// Pick up the generic tree
|
||||||
|
//
|
||||||
|
Tree t = (Tree)psrReturn.getTree();
|
||||||
|
|
||||||
|
// NOw walk it with the generic tree walker, which does nothing but
|
||||||
|
// verify the tree really.
|
||||||
|
//
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (parser.getNumberOfSyntaxErrors() == 0) {
|
||||||
|
TTree walker = new TTree(new CommonTreeNodeStream(t));
|
||||||
|
System.out.println(" AST Walk Start${symbol_escape}n");
|
||||||
|
pStart = System.currentTimeMillis();
|
||||||
|
walker.a();
|
||||||
|
stop = System.currentTimeMillis();
|
||||||
|
System.out.println("${symbol_escape}n AST Walked in " + (stop - pStart) + "ms.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception w)
|
||||||
|
{
|
||||||
|
System.out.println("AST walk caused exception.");
|
||||||
|
w.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (makeDot && tokens.size() < 4096)
|
||||||
|
{
|
||||||
|
|
||||||
|
// Now stringify it if you want to...
|
||||||
|
//
|
||||||
|
// System.out.println(t.toStringTree());
|
||||||
|
|
||||||
|
// Use the ANLTR built in dot generator
|
||||||
|
//
|
||||||
|
DOTTreeGenerator gen = new DOTTreeGenerator();
|
||||||
|
|
||||||
|
// Which we can cause to generate the DOT specification
|
||||||
|
// with the input file name suffixed with .dot. You can then use
|
||||||
|
// the graphviz tools or zgrviewer (Java) to view the graphical
|
||||||
|
// version of the dot file.
|
||||||
|
//
|
||||||
|
source = source.substring(0, source.length()-3);
|
||||||
|
String outputName = source + "dot";
|
||||||
|
|
||||||
|
System.out.println(" Producing AST dot (graphviz) file");
|
||||||
|
|
||||||
|
// It produces a jguru string template.
|
||||||
|
//
|
||||||
|
StringTemplate st = gen.toDOT(t, new CommonTreeAdaptor());
|
||||||
|
|
||||||
|
// Create the output file and write the dot spec to it
|
||||||
|
//
|
||||||
|
FileWriter outputStream = new FileWriter(outputName);
|
||||||
|
outputStream.write(st.toString());
|
||||||
|
outputStream.close();
|
||||||
|
|
||||||
|
// Invoke dot to generate a .png file
|
||||||
|
//
|
||||||
|
System.out.println(" Producing png graphic for tree");
|
||||||
|
pStart = System.currentTimeMillis();
|
||||||
|
Process proc = Runtime.getRuntime().exec("dot -Tpng -o" + source + "png " + outputName);
|
||||||
|
proc.waitFor();
|
||||||
|
stop = System.currentTimeMillis();
|
||||||
|
System.out.println(" PNG graphic produced in " + (stop - pStart) + "ms.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (FileNotFoundException ex)
|
||||||
|
{
|
||||||
|
// The file we tried to parse does not exist
|
||||||
|
//
|
||||||
|
System.err.println("${symbol_escape}n !!The file " + source + " does not exist!!${symbol_escape}n");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
// Something went wrong in the parser, report this
|
||||||
|
//
|
||||||
|
System.err.println("Parser threw an exception:${symbol_escape}n${symbol_escape}n");
|
||||||
|
ex.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
234
outside/antlr3-antlr-3.5/antlr3-maven-plugin/pom.xml
Normal file
234
outside/antlr3-antlr-3.5/antlr3-maven-plugin/pom.xml
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
[The "BSD license"]
|
||||||
|
|
||||||
|
ANTLR - Copyright (c) 2005-2010 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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
|
||||||
|
<!-- Maven model we are inheriting from
|
||||||
|
-->
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Now that the ANTLR project has adopted Maven with a vengence,
|
||||||
|
all ANTLR tools will be grouped under org.antlr and will be
|
||||||
|
controlled by a project member.
|
||||||
|
-->
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
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
|
||||||
|
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.
|
||||||
|
-->
|
||||||
|
<artifactId>antlr3-maven-plugin</artifactId>
|
||||||
|
<packaging>maven-plugin</packaging>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr-master</artifactId>
|
||||||
|
<version>3.5</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<name>ANTLR 3 Maven plugin</name>
|
||||||
|
<prerequisites>
|
||||||
|
<maven>2.0</maven>
|
||||||
|
</prerequisites>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Where does our actual project live on the interwebs.
|
||||||
|
-->
|
||||||
|
<url>http://antlr.org</url>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<description>
|
||||||
|
|
||||||
|
This is the brand new, re-written from scratch plugin for ANTLR v3.
|
||||||
|
|
||||||
|
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 v3 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
|
||||||
|
|
||||||
|
</description>
|
||||||
|
|
||||||
|
<developers>
|
||||||
|
|
||||||
|
<developer>
|
||||||
|
<name>Jim Idle</name>
|
||||||
|
<url>http://www.temporal-wave.com</url>
|
||||||
|
<roles>
|
||||||
|
<role>Originator, version 3.1.3</role>
|
||||||
|
</roles>
|
||||||
|
</developer>
|
||||||
|
|
||||||
|
<developer>
|
||||||
|
<name>Terence Parr</name>
|
||||||
|
<url>http://antlr.org/wiki/display/~admin/Home</url>
|
||||||
|
<roles>
|
||||||
|
<role>Project lead - ANTLR</role>
|
||||||
|
</roles>
|
||||||
|
</developer>
|
||||||
|
|
||||||
|
<developer>
|
||||||
|
<name>David Holroyd</name>
|
||||||
|
<url>http://david.holroyd.me.uk/</url>
|
||||||
|
<roles>
|
||||||
|
<role>Originator - prior version</role>
|
||||||
|
</roles>
|
||||||
|
</developer>
|
||||||
|
|
||||||
|
<developer>
|
||||||
|
<name>Kenny MacDermid</name>
|
||||||
|
<url>mailto:kenny "at" kmdconsulting.ca</url>
|
||||||
|
<roles>
|
||||||
|
<role>Contributor - prior versions</role>
|
||||||
|
</roles>
|
||||||
|
</developer>
|
||||||
|
|
||||||
|
</developers>
|
||||||
|
|
||||||
|
<!-- ============================================================================= -->
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
What are we depedent on for the Mojos to execute? We need the
|
||||||
|
plugin API itself and of course we need the ANTLR Tool and runtime
|
||||||
|
and any of their dependencies, which we inherit. The Tool itself provides
|
||||||
|
us with all the dependencies, so we need only name it here.
|
||||||
|
-->
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The things we need to build the target language recognizer
|
||||||
|
-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>maven-plugin-api</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>maven-project</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.plexus</groupId>
|
||||||
|
<artifactId>plexus-compiler-api</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The version of ANTLR tool that this version of the plugin controls.
|
||||||
|
We have decided that this should be in lockstep with ANTLR itself, other
|
||||||
|
than -1 -2 -3 etc patch releases.
|
||||||
|
-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.shared</groupId>
|
||||||
|
<artifactId>maven-plugin-testing-harness</artifactId>
|
||||||
|
<version>1.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-site-plugin</artifactId>
|
||||||
|
<version>3.2</version>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
<configuration>
|
||||||
|
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
|
||||||
|
<reporting>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-plugin-plugin</artifactId>
|
||||||
|
<version>3.2</version>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
</reporting>
|
||||||
|
</project>
|
@ -0,0 +1,90 @@
|
|||||||
|
/**
|
||||||
|
[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.antlr3;
|
||||||
|
|
||||||
|
import org.antlr.tool.ANTLRErrorListener;
|
||||||
|
import org.antlr.tool.Message;
|
||||||
|
import org.antlr.tool.ToolMessage;
|
||||||
|
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 Antlr3ErrorLog implements ANTLRErrorListener {
|
||||||
|
|
||||||
|
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 Antlr3ErrorLog(Log log) {
|
||||||
|
this.log = log;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an informational message to the Maven log sink.
|
||||||
|
* @param s The message to send to Maven
|
||||||
|
*/
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
public void error(Message message) {
|
||||||
|
log.error(message.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends a warning message to the Maven log sink.
|
||||||
|
*
|
||||||
|
* @param message
|
||||||
|
*/
|
||||||
|
public void warning(Message message) {
|
||||||
|
log.warn(message.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sends an error message from the ANTLR tool to the Maven Log sink.
|
||||||
|
* @param toolMessage
|
||||||
|
*/
|
||||||
|
public void error(ToolMessage toolMessage) {
|
||||||
|
log.error(toolMessage.toString());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,501 @@
|
|||||||
|
/**
|
||||||
|
[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 ANTLR3 Mojo set. All other sets are belong to us.
|
||||||
|
*/
|
||||||
|
package org.antlr.mojo.antlr3;
|
||||||
|
|
||||||
|
import antlr.RecognitionException;
|
||||||
|
import antlr.TokenStreamException;
|
||||||
|
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.Tool;
|
||||||
|
import org.apache.maven.plugin.logging.Log;
|
||||||
|
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;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses ANTLR grammar files {@code *.g} and transforms them into Java source
|
||||||
|
* files.
|
||||||
|
*
|
||||||
|
* @goal antlr
|
||||||
|
* @phase generate-sources
|
||||||
|
* @requiresDependencyResolution compile
|
||||||
|
* @requiresProject true
|
||||||
|
*
|
||||||
|
* @author <a href="mailto:jimi@temporal-wave.com">Jim Idle</a>
|
||||||
|
*/
|
||||||
|
public class Antlr3Mojo
|
||||||
|
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 various 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(s) which are stripped of any embedded actions.
|
||||||
|
*
|
||||||
|
* @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 the generated parser will compute and report 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
|
||||||
|
* NFA 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;
|
||||||
|
/**
|
||||||
|
* If set to true, the generated parser code will log rule entry and exit
|
||||||
|
* points to stdout ({@link System#out} for the Java target) 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, should be formatted in the specified way. Currently,
|
||||||
|
* ANTLR supports the built-in formats {@code antlr}, {@code gnu} and
|
||||||
|
* {@code vs2005}.
|
||||||
|
*
|
||||||
|
* @parameter default-value="antlr"
|
||||||
|
*/
|
||||||
|
protected String messageFormat;
|
||||||
|
/**
|
||||||
|
* If set to true, then ANTLR will report verbose messages during the code
|
||||||
|
* generation process. This includes the names of files, the version of
|
||||||
|
* ANTLR, and more.
|
||||||
|
*
|
||||||
|
* @parameter default-value="true"
|
||||||
|
*/
|
||||||
|
protected boolean verbose;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of alternatives allowed in an inline switch statement.
|
||||||
|
* Beyond this, ANTLR will not generate a switch statement for the DFA.
|
||||||
|
*
|
||||||
|
* @parameter default-value="300"
|
||||||
|
*/
|
||||||
|
private int maxSwitchCaseLabels;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The minimum number of alternatives for ANTLR to generate a switch
|
||||||
|
* statement. For decisions with fewer alternatives, an if/else if/else
|
||||||
|
* statement will be used instead.
|
||||||
|
*
|
||||||
|
* @parameter default-value="3"
|
||||||
|
*/
|
||||||
|
private int minSwitchAlts;
|
||||||
|
|
||||||
|
/* --------------------------------------------------------------------
|
||||||
|
* The following are Maven specific parameters, rather than specific
|
||||||
|
* 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.
|
||||||
|
* <p/>
|
||||||
|
* A set of Ant-like inclusion patterns used to select files from the source
|
||||||
|
* directory for processing. By default, the pattern <code>**/*.g</code>
|
||||||
|
* is used to select grammar files.
|
||||||
|
*
|
||||||
|
* @parameter
|
||||||
|
*/
|
||||||
|
protected Set<String> includes = new HashSet<String>();
|
||||||
|
/**
|
||||||
|
* A set of Ant-like exclusion patterns used to prevent certain files from
|
||||||
|
* being processed. By default, this set is empty such that no files are
|
||||||
|
* excluded.
|
||||||
|
*
|
||||||
|
* @parameter
|
||||||
|
*/
|
||||||
|
protected Set<String> excludes = new HashSet<String>();
|
||||||
|
/**
|
||||||
|
* The current Maven project.
|
||||||
|
*
|
||||||
|
* @parameter expression="${project}"
|
||||||
|
* @required
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
protected MavenProject project;
|
||||||
|
/**
|
||||||
|
* The directory where the ANTLR grammar files ({@code *.g}) are located.
|
||||||
|
*
|
||||||
|
* @parameter default-value="${basedir}/src/main/antlr3"
|
||||||
|
*/
|
||||||
|
private File sourceDirectory;
|
||||||
|
/**
|
||||||
|
* The directory where the parser files generated by ANTLR will be stored.
|
||||||
|
* The directory will be registered as a compile source root of the project
|
||||||
|
* such that the generated files will participate in later build phases like
|
||||||
|
* compiling and packaging.
|
||||||
|
*
|
||||||
|
* @parameter default-value="${project.build.directory}/generated-sources/antlr3"
|
||||||
|
* @required
|
||||||
|
*/
|
||||||
|
private File outputDirectory;
|
||||||
|
/**
|
||||||
|
* Location for imported token files, e.g. {@code *.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/antlr3/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 3.x grammars into the target language specified by the grammar.
|
||||||
|
*
|
||||||
|
* @throws MojoExecutionException if a configuration or grammar error causes
|
||||||
|
* the code generation process to fail
|
||||||
|
* @throws MojoFailureException if an instance of the ANTLR 3 {@link Tool}
|
||||||
|
* cannot be created
|
||||||
|
*/
|
||||||
|
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: nfa : " + nfa);
|
||||||
|
log.debug("ANTLR: dfa : " + dfa);
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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");
|
||||||
|
|
||||||
|
throw new MojoFailureException("Jim failed you!");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Next we need to set the options given to us in the pom into the
|
||||||
|
// tool instance we have created.
|
||||||
|
//
|
||||||
|
tool.setDebug(debug);
|
||||||
|
tool.setGenerate_DFA_dot(dfa);
|
||||||
|
tool.setGenerate_NFA_dot(nfa);
|
||||||
|
tool.setProfile(profile);
|
||||||
|
tool.setReport(report);
|
||||||
|
tool.setPrintGrammar(printGrammar);
|
||||||
|
tool.setTrace(trace);
|
||||||
|
tool.setVerbose(verbose);
|
||||||
|
tool.setMessageFormat(messageFormat);
|
||||||
|
tool.setMaxSwitchCaseLabels(maxSwitchCaseLabels);
|
||||||
|
tool.setMinSwitchAlts(minSwitchAlts);
|
||||||
|
|
||||||
|
// Where do we want ANTLR to produce its output? (Base directory)
|
||||||
|
//
|
||||||
|
if (log.isDebugEnabled())
|
||||||
|
{
|
||||||
|
log.debug("Output directory base will be " + outputDirectory.getAbsolutePath());
|
||||||
|
}
|
||||||
|
tool.setOutputDirectory(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());
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Now pick up all the files and process them with the Tool
|
||||||
|
//
|
||||||
|
processGrammarFiles(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());
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
tool.process();
|
||||||
|
|
||||||
|
// 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 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 TokenStreamException
|
||||||
|
* @throws RecognitionException
|
||||||
|
* @throws IOException
|
||||||
|
* @throws InclusionScanException
|
||||||
|
*/
|
||||||
|
private void processGrammarFiles(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.<String>emptySet());
|
||||||
|
|
||||||
|
// What are the sets of includes (defaulted or otherwise).
|
||||||
|
//
|
||||||
|
Set<String> 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);
|
||||||
|
Set<File> grammarFiles = 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);
|
||||||
|
}
|
||||||
|
tool.addGrammarFile(relPath);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getIncludesPatterns() {
|
||||||
|
if (includes == null || includes.isEmpty()) {
|
||||||
|
return Collections.singleton("**/*.g");
|
||||||
|
}
|
||||||
|
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 {@code 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 {@link 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()));
|
||||||
|
if ( unprefixedGrammarFileName.getParent()!=null ) {
|
||||||
|
return unprefixedGrammarFileName.getParent() + File.separator;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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 <<<.g>>> 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).
|
||||||
|
|
||||||
|
For a default layout, place your import grammars in the directory: <<<src/main/antlr3/imports>>>
|
@ -0,0 +1,46 @@
|
|||||||
|
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 vocabulary files (<<<*.tokens>>>) can also
|
||||||
|
be searched for with the <<<<libDirectory>>>> 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 vocabulary 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 <<<<libDirectory>>>> directive to specify the
|
||||||
|
location of your imported grammars and ANTLR will not find any vocabulary files in
|
||||||
|
this directory.
|
||||||
|
|
||||||
|
The <<<.tokens>>> files for any grammars are generated within the same output directory structure
|
||||||
|
as the <<<.java>>> files. So, wherever the <<<.java>>> files are generated, you will also find the <<<.tokens>>>
|
||||||
|
files. ANTLR looks for <<<.tokens>>> files in both the <<<<libDirectory>>>> and the output directory
|
||||||
|
where it is placing the generated <<<.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 <<<<libDirectory>>>> is specified like any other directory parameter in Maven. Here is an
|
||||||
|
example:
|
||||||
|
|
||||||
|
+--
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr3-maven-plugin</artifactId>
|
||||||
|
<version>${plugin.version}</version>
|
||||||
|
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<configuration>
|
||||||
|
<goals>
|
||||||
|
<goal>antlr</goal>
|
||||||
|
</goals>
|
||||||
|
<libDirectory>src/main/antlr_imports</libDirectory>
|
||||||
|
</configuration>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
+--
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
+--
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr3-maven-plugin</artifactId>
|
||||||
|
<version>3.1.3-1</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>antlr</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
...
|
||||||
|
</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>>>.
|
||||||
|
|
||||||
|
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:
|
||||||
|
|
||||||
|
+---
|
||||||
|
@header {
|
||||||
|
package org.jimi.themuss;
|
||||||
|
}
|
||||||
|
+---
|
||||||
|
|
||||||
|
Then the <<<.g>>> file should be stored in: <<<src/main/antlr3/org/jimi/themuss/parser.g>>>. This way
|
||||||
|
the generated <<<.java>>> files will correctly reflect the package structure in which they will
|
||||||
|
finally rest as classes.
|
||||||
|
|
@ -0,0 +1 @@
|
|||||||
|
FAQ
|
@ -0,0 +1,62 @@
|
|||||||
|
-------------
|
||||||
|
ANTLR v3 Maven Plugin
|
||||||
|
-------------
|
||||||
|
Jim Idle
|
||||||
|
-------------
|
||||||
|
March 2009
|
||||||
|
-------------
|
||||||
|
|
||||||
|
ANTLR v3 Maven plugin
|
||||||
|
|
||||||
|
The ANTLR v3 Maven plugin is completely re-written as of version 3.1.3; 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 3.1.3 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.
|
||||||
|
|
||||||
|
You may also find that there are patch versions of the plugin such as 3.1.3-1 3.1.3-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.
|
||||||
|
|
||||||
|
|
||||||
|
* 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/
|
||||||
|
|
|
||||||
|
+--- antlr3/... .g files organized in the required package structure
|
||||||
|
|
|
||||||
|
+--- imports/ .g 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>>>
|
||||||
|
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
|
||||||
|
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.
|
@ -0,0 +1,59 @@
|
|||||||
|
Usage
|
||||||
|
|
||||||
|
The ANTLR 3 plugin for Maven can generate parsers for any number of grammars in
|
||||||
|
your project.
|
||||||
|
|
||||||
|
* Compiling Grammars into Parsers
|
||||||
|
|
||||||
|
By default, the <<<{{{./antlr-mojo.html}antlr}}>>> goal will search for grammar
|
||||||
|
files in the directory <<<$\{basedir\}/src/main/antlr3>>> and any additional
|
||||||
|
<<<.tokens>>> files in the directory <<<$\{basedir\}/src/main/antlr3/imports>>>.
|
||||||
|
This can be configured to search other directories using the plugin configuration
|
||||||
|
parameters as described in the <<<{{{./antlr-mojo.html}antlr}}>>> goal
|
||||||
|
documentation.
|
||||||
|
|
||||||
|
The following figure shows the expected layout of files for the default
|
||||||
|
configuration of this plugin.
|
||||||
|
|
||||||
|
+--
|
||||||
|
src/main/
|
||||||
|
|
|
||||||
|
+--- antlr3/... .g files organized in the required package structure
|
||||||
|
|
|
||||||
|
+--- imports/ user-created .tokens files and .g files that are imported by other grammars
|
||||||
|
+--
|
||||||
|
|
||||||
|
The next step is to configure your POM to call the plugin. The goals will
|
||||||
|
normally run during the generate-sources phase of the build. Examples of how to
|
||||||
|
configure your POM can be found on the various examples pages, reachable via
|
||||||
|
the page menu. If you stick with the default values, the snippet below will
|
||||||
|
suffice:
|
||||||
|
|
||||||
|
+--
|
||||||
|
<project>
|
||||||
|
...
|
||||||
|
<build>
|
||||||
|
<plugins>
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr3-maven-plugin</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<id>antlr</id>
|
||||||
|
<goals>
|
||||||
|
<goal>antlr</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
</plugins>
|
||||||
|
...
|
||||||
|
</build>
|
||||||
|
...
|
||||||
|
</project>
|
||||||
|
+--
|
||||||
|
|
||||||
|
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).
|
@ -0,0 +1,35 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
|
||||||
|
<project name="ANTLR v3 Maven plugin">
|
||||||
|
|
||||||
|
<publishDate position="left"/>
|
||||||
|
<version position="left"/>
|
||||||
|
|
||||||
|
<poweredBy>
|
||||||
|
<logo name="ANTLR Web Site" href="http://antlr3.org/"
|
||||||
|
img="http://www.antlr.org/wiki/download/attachments/292/ANTLR3"/>
|
||||||
|
</poweredBy>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<links>
|
||||||
|
<item name="Antlr Web Site" href="http://www.antlr3.org/"/>
|
||||||
|
</links>
|
||||||
|
|
||||||
|
<menu name="Overview">
|
||||||
|
<item name="Introduction" href="index.html"/>
|
||||||
|
<item name="Goals" href="plugin-info.html"/>
|
||||||
|
<item name="Usage" href="usage.html"/>
|
||||||
|
<item name="FAQ" href="faq.html"/>
|
||||||
|
</menu>
|
||||||
|
|
||||||
|
<menu name="Examples">
|
||||||
|
<item name="Simple configurations" href="examples/simple.html"/>
|
||||||
|
<item name="Using library directories" href="examples/libraries.html"/>
|
||||||
|
<item name="Using imported grammars" href="examples/import.html"/>
|
||||||
|
</menu>
|
||||||
|
|
||||||
|
<menu ref="reports" />
|
||||||
|
<menu ref="modules" />
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</project>
|
56
outside/antlr3-antlr-3.5/contributors.txt
Normal file
56
outside/antlr3-antlr-3.5/contributors.txt
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
ANTLR Project Contributors Certification of Origin and Rights
|
||||||
|
|
||||||
|
All contributors to ANTLR v3 must formally agree to abide by this
|
||||||
|
certificate of origin by signing on the bottom with their github
|
||||||
|
userid, full name, email address (you can obscure your e-mail, but it
|
||||||
|
must be computable by human), and date.
|
||||||
|
|
||||||
|
By signing this agreement, you are warranting and representing that
|
||||||
|
you have the right to release code contributions or other content free
|
||||||
|
of any obligations to third parties and are granting Terence Parr and
|
||||||
|
ANTLR project contributors, henceforth referred to as The ANTLR
|
||||||
|
Project, a license to incorporate it into The ANTLR Project tools
|
||||||
|
(such as ANTLRWorks and StringTemplate) or related works under the BSD
|
||||||
|
license. You understand that The ANTLR Project may or may not
|
||||||
|
incorporate your contribution and you warrant and represent the
|
||||||
|
following:
|
||||||
|
|
||||||
|
1. I am the creator of all my contributions. I am the author of all
|
||||||
|
contributed work submitted and further warrant and represent that
|
||||||
|
such work is my original creation and I have the right to license
|
||||||
|
it to The ANTLR Project for release under the 3-clause BSD
|
||||||
|
license. I hereby grant The ANTLR Project a nonexclusive,
|
||||||
|
irrevocable, royalty-free, worldwide license to reproduce,
|
||||||
|
distribute, prepare derivative works, and otherwise use this
|
||||||
|
contribution as part of the ANTLR project, associated
|
||||||
|
documentation, books, and tools at no cost to The ANTLR Project.
|
||||||
|
|
||||||
|
2. I have the right to submit. This submission does not violate the
|
||||||
|
rights of any person or entity and that I have legal authority over
|
||||||
|
this submission and to make this certification.
|
||||||
|
|
||||||
|
3. If I violate another's rights, liability lies with me. I agree to
|
||||||
|
defend, indemnify, and hold The ANTLR Project and ANTLR users
|
||||||
|
harmless from any claim or demand, including reasonable attorney
|
||||||
|
fees, made by any third party due to or arising out of my violation
|
||||||
|
of these terms and conditions or my violation of the rights of
|
||||||
|
another person or entity.
|
||||||
|
|
||||||
|
4. I understand and agree that this project and the contribution are
|
||||||
|
public and that a record of the contribution (including all
|
||||||
|
personal information I submit with it, including my sign-off) is
|
||||||
|
maintained indefinitely and may be redistributed consistent with
|
||||||
|
this project or the open source license indicated in the file.
|
||||||
|
|
||||||
|
I have read this agreement and do so certify by adding my signoff to
|
||||||
|
the end of the following contributors list.
|
||||||
|
|
||||||
|
CONTRIBUTORS:
|
||||||
|
|
||||||
|
YYYY/MM/DD, github id, Full name, email
|
||||||
|
2012/07/12, parrt, Terence Parr, parrt@antlr.org
|
||||||
|
2012/08/08, Zannick, Benjamin S Wolf, jokeserver@gmail.com
|
||||||
|
2012/09/15, martint, Martin Traverso, mtraverso@gmail.com
|
||||||
|
2012/09/16, qmx, Douglas Campos, qmx@qmx.me
|
||||||
|
2012/09/17, ksgokul, Gokulakannan Somasundaram, gokul007@gmail.com
|
||||||
|
2012/11/22, sharwell, Sam Harwell, sam@tunnelvisionlabs.com
|
144
outside/antlr3-antlr-3.5/gunit-maven-plugin/pom.xml
Normal file
144
outside/antlr3-antlr-3.5/gunit-maven-plugin/pom.xml
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
<!--
|
||||||
|
|
||||||
|
[The "BSD license"]
|
||||||
|
|
||||||
|
ANTLR - Copyright (c) 2005-2010 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.
|
||||||
|
|
||||||
|
-->
|
||||||
|
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
|
||||||
|
<prerequisites>
|
||||||
|
<maven>2.0</maven>
|
||||||
|
</prerequisites>
|
||||||
|
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>maven-gunit-plugin</artifactId>
|
||||||
|
<packaging>maven-plugin</packaging>
|
||||||
|
|
||||||
|
<name>ANTLR 3 gUnit Maven plugin</name>
|
||||||
|
<description>A Maven plugin for incorporating gUnit testing of grammars</description>
|
||||||
|
<url>http://antlr.org</url>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Inherit from the ANTLR master pom, which tells us what
|
||||||
|
version we are and allows us to inherit dependencies
|
||||||
|
and so on.
|
||||||
|
-->
|
||||||
|
<parent>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr-master</artifactId>
|
||||||
|
<version>3.5</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<properties>
|
||||||
|
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||||
|
</properties>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
What are we depedent on for the Mojos to execute? We need the
|
||||||
|
plugin API itself and of course we need the ANTLR Tool and runtime
|
||||||
|
and any of their dependencies, which we inherit. The Tool itself provides
|
||||||
|
us with all the dependencies, so we need only name it here.
|
||||||
|
-->
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The things we need to build the target language recognizer
|
||||||
|
-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>maven-plugin-api</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven</groupId>
|
||||||
|
<artifactId>maven-project</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.codehaus.plexus</groupId>
|
||||||
|
<artifactId>plexus-compiler-api</artifactId>
|
||||||
|
<version>2.0</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
The version of ANTLR tool that this version of the plugin controls.
|
||||||
|
We have decided that this should be in lockstep with ANTLR itself, other
|
||||||
|
than -1 -2 -3 etc patch releases.
|
||||||
|
-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Dependency on the gUnit artifact.
|
||||||
|
-->
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>gunit</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.maven.shared</groupId>
|
||||||
|
<artifactId>maven-plugin-testing-harness</artifactId>
|
||||||
|
<version>1.1</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.apache.maven.plugins</groupId>
|
||||||
|
<artifactId>maven-project-info-reports-plugin</artifactId>
|
||||||
|
<version>2.6</version>
|
||||||
|
<configuration>
|
||||||
|
<dependencyLocationsEnabled>false</dependencyLocationsEnabled>
|
||||||
|
</configuration>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,397 @@
|
|||||||
|
package org.antlr.mojo.antlr3;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.Writer;
|
||||||
|
import java.io.FileWriter;
|
||||||
|
import java.io.BufferedWriter;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.net.URLClassLoader;
|
||||||
|
|
||||||
|
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 org.apache.maven.artifact.Artifact;
|
||||||
|
import org.apache.maven.artifact.DependencyResolutionRequiredException;
|
||||||
|
import org.apache.maven.artifact.versioning.ArtifactVersion;
|
||||||
|
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
|
||||||
|
import org.apache.maven.artifact.versioning.OverConstrainedVersionException;
|
||||||
|
import org.codehaus.plexus.util.StringUtils;
|
||||||
|
import org.codehaus.plexus.util.FileUtils;
|
||||||
|
import org.codehaus.plexus.compiler.util.scan.mapping.SourceMapping;
|
||||||
|
import org.codehaus.plexus.compiler.util.scan.mapping.SuffixMapping;
|
||||||
|
import org.codehaus.plexus.compiler.util.scan.SourceInclusionScanner;
|
||||||
|
import org.codehaus.plexus.compiler.util.scan.SimpleSourceInclusionScanner;
|
||||||
|
import org.codehaus.plexus.compiler.util.scan.InclusionScanException;
|
||||||
|
import org.antlr.runtime.ANTLRFileStream;
|
||||||
|
import org.antlr.runtime.RecognitionException;
|
||||||
|
import org.antlr.gunit.GrammarInfo;
|
||||||
|
import org.antlr.gunit.gUnitExecutor;
|
||||||
|
import org.antlr.gunit.AbstractTest;
|
||||||
|
import org.antlr.gunit.Interp;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Takes gUnit scripts and directly performs testing.
|
||||||
|
*
|
||||||
|
* @goal gunit
|
||||||
|
*
|
||||||
|
* @phase test
|
||||||
|
* @requiresDependencyResolution test
|
||||||
|
* @requiresProject true
|
||||||
|
*
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
public class GUnitExecuteMojo extends AbstractMojo {
|
||||||
|
public static final String ANTLR_GROUP_ID = "org.antlr";
|
||||||
|
public static final String ANTLR_ARTIFACT_NAME = "antlr";
|
||||||
|
public static final String ANTLR_RUNTIME_ARTIFACT_NAME = "antlr-runtime";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* INTERNAL : The Maven Project to which we are attached
|
||||||
|
*
|
||||||
|
* @parameter expression="${project}"
|
||||||
|
* @required
|
||||||
|
*/
|
||||||
|
private MavenProject project;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* INTERNAL : The artifacts associated to the dependencies defined as part
|
||||||
|
* of our configuration within the project to which we are being attached.
|
||||||
|
*
|
||||||
|
* @parameter expression="${plugin.artifacts}"
|
||||||
|
* @required
|
||||||
|
* @readonly
|
||||||
|
*/
|
||||||
|
private List<Artifact> pluginArtifacts;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies the directory containing the gUnit testing files.
|
||||||
|
*
|
||||||
|
* @parameter expression="${basedir}/src/test/gunit"
|
||||||
|
* @required
|
||||||
|
*/
|
||||||
|
private File sourceDirectory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of patterns for matching files from the sourceDirectory that
|
||||||
|
* should be included as gUnit source files.
|
||||||
|
*
|
||||||
|
* @parameter
|
||||||
|
*/
|
||||||
|
private Set<String> includes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A set of exclude patterns.
|
||||||
|
*
|
||||||
|
* @parameter
|
||||||
|
*/
|
||||||
|
private Set<String> excludes;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Specifies directory to which gUnit reports should get written.
|
||||||
|
*
|
||||||
|
* @parameter expression="${basedir}/target/gunit-report"
|
||||||
|
* @required
|
||||||
|
*/
|
||||||
|
private File reportDirectory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Should gUnit functionality be completely by-passed?
|
||||||
|
* <p/>
|
||||||
|
* By default we skip gUnit tests if the user requested that all testing be skipped using 'maven.test.skip'
|
||||||
|
*
|
||||||
|
* @parameter expression="${maven.test.skip}"
|
||||||
|
*/
|
||||||
|
private boolean skip;
|
||||||
|
|
||||||
|
public Set<String> getIncludePatterns() {
|
||||||
|
return includes == null || includes.isEmpty()
|
||||||
|
? Collections.singleton( "**/*.testsuite" )
|
||||||
|
: includes;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Set<String> getExcludePatterns() {
|
||||||
|
return excludes == null
|
||||||
|
? Collections.<String>emptySet()
|
||||||
|
: excludes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public final void execute() throws MojoExecutionException, MojoFailureException {
|
||||||
|
if ( skip ) {
|
||||||
|
getLog().info( "Skipping gUnit processing" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Artifact pluginAntlrArtifact = determinePluginAntlrArtifact();
|
||||||
|
|
||||||
|
validateProjectsAntlrVersion( determineArtifactVersion( pluginAntlrArtifact ) );
|
||||||
|
|
||||||
|
performExecution( determineProjectCompileScopeClassLoader( pluginAntlrArtifact ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
private Artifact determinePluginAntlrArtifact() throws MojoExecutionException {
|
||||||
|
for ( Artifact artifact : pluginArtifacts ) {
|
||||||
|
boolean match = ANTLR_GROUP_ID.equals( artifact.getGroupId() )
|
||||||
|
&& ANTLR_ARTIFACT_NAME.equals( artifact.getArtifactId() );
|
||||||
|
if ( match ) {
|
||||||
|
return artifact;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new MojoExecutionException(
|
||||||
|
"Unexpected state : could not locate " + ANTLR_GROUP_ID + ':' + ANTLR_ARTIFACT_NAME +
|
||||||
|
" in plugin dependencies"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ArtifactVersion determineArtifactVersion(Artifact artifact) throws MojoExecutionException {
|
||||||
|
try {
|
||||||
|
return artifact.getVersion() != null
|
||||||
|
? new DefaultArtifactVersion( artifact.getVersion() )
|
||||||
|
: artifact.getSelectedVersion();
|
||||||
|
}
|
||||||
|
catch ( OverConstrainedVersionException e ) {
|
||||||
|
throw new MojoExecutionException( "artifact [" + artifact.getId() + "] defined an overly constrained version range" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void validateProjectsAntlrVersion(ArtifactVersion pluginAntlrVersion) throws MojoExecutionException {
|
||||||
|
Artifact antlrArtifact = null;
|
||||||
|
Artifact antlrRuntimeArtifact = null;
|
||||||
|
|
||||||
|
if ( project.getCompileArtifacts() != null ) {
|
||||||
|
for ( Object o : project.getCompileArtifacts() ) {
|
||||||
|
final Artifact artifact = ( Artifact ) o;
|
||||||
|
if ( ANTLR_GROUP_ID.equals( artifact.getGroupId() ) ) {
|
||||||
|
if ( ANTLR_ARTIFACT_NAME.equals( artifact.getArtifactId() ) ) {
|
||||||
|
antlrArtifact = artifact;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if ( ANTLR_RUNTIME_ARTIFACT_NAME.equals( artifact.getArtifactId() ) ) {
|
||||||
|
antlrRuntimeArtifact = artifact;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
validateBuildTimeArtifact( antlrArtifact, pluginAntlrVersion );
|
||||||
|
validateRunTimeArtifact( antlrRuntimeArtifact, pluginAntlrVersion );
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings(value = "unchecked")
|
||||||
|
protected void validateBuildTimeArtifact(Artifact antlrArtifact, ArtifactVersion pluginAntlrVersion)
|
||||||
|
throws MojoExecutionException {
|
||||||
|
if ( antlrArtifact == null ) {
|
||||||
|
validateMissingBuildtimeArtifact();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// otherwise, lets make sure they match...
|
||||||
|
ArtifactVersion projectAntlrVersion = determineArtifactVersion( antlrArtifact );
|
||||||
|
if ( pluginAntlrVersion.compareTo( projectAntlrVersion ) != 0 ) {
|
||||||
|
getLog().warn(
|
||||||
|
"Encountered " + ANTLR_GROUP_ID + ':' + ANTLR_ARTIFACT_NAME + ':' + projectAntlrVersion.toString() +
|
||||||
|
" which did not match Antlr version used by plugin [" + pluginAntlrVersion.toString() + "]"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void validateMissingBuildtimeArtifact() {
|
||||||
|
// generally speaking, its ok for the project to not define a dep on the build-time artifact...
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings(value = "unchecked")
|
||||||
|
protected void validateRunTimeArtifact(Artifact antlrRuntimeArtifact, ArtifactVersion pluginAntlrVersion)
|
||||||
|
throws MojoExecutionException {
|
||||||
|
if ( antlrRuntimeArtifact == null ) {
|
||||||
|
// its possible, if the project instead depends on the build-time (or full) artifact.
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ArtifactVersion projectAntlrVersion = determineArtifactVersion( antlrRuntimeArtifact );
|
||||||
|
if ( pluginAntlrVersion.compareTo( projectAntlrVersion ) != 0 ) {
|
||||||
|
getLog().warn(
|
||||||
|
"Encountered " + ANTLR_GROUP_ID + ':' + ANTLR_RUNTIME_ARTIFACT_NAME + ':' + projectAntlrVersion.toString() +
|
||||||
|
" which did not match Antlr version used by plugin [" + pluginAntlrVersion.toString() + "]"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Builds the classloader to pass to gUnit.
|
||||||
|
*
|
||||||
|
* @param antlrArtifact The plugin's (our) Antlr dependency artifact.
|
||||||
|
*
|
||||||
|
* @return The classloader for gUnit to use
|
||||||
|
*
|
||||||
|
* @throws MojoExecutionException Problem resolving artifacts to {@link java.net.URL urls}.
|
||||||
|
*/
|
||||||
|
private ClassLoader determineProjectCompileScopeClassLoader(Artifact antlrArtifact)
|
||||||
|
throws MojoExecutionException {
|
||||||
|
ArrayList<URL> classPathUrls = new ArrayList<URL>();
|
||||||
|
getLog().info( "Adding Antlr artifact : " + antlrArtifact.getId() );
|
||||||
|
classPathUrls.add( resolveLocalURL( antlrArtifact ) );
|
||||||
|
|
||||||
|
for ( String path : classpathElements() ) {
|
||||||
|
try {
|
||||||
|
getLog().info( "Adding project compile classpath element : " + path );
|
||||||
|
classPathUrls.add( new File( path ).toURI().toURL() );
|
||||||
|
}
|
||||||
|
catch ( MalformedURLException e ) {
|
||||||
|
throw new MojoExecutionException( "Unable to build path URL [" + path + "]" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return new URLClassLoader( classPathUrls.toArray( new URL[classPathUrls.size()] ), getClass().getClassLoader() );
|
||||||
|
}
|
||||||
|
|
||||||
|
protected static URL resolveLocalURL(Artifact artifact) throws MojoExecutionException {
|
||||||
|
try {
|
||||||
|
return artifact.getFile().toURI().toURL();
|
||||||
|
}
|
||||||
|
catch ( MalformedURLException e ) {
|
||||||
|
throw new MojoExecutionException( "Unable to resolve artifact url : " + artifact.getId(), e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings( "unchecked" )
|
||||||
|
private List<String> classpathElements() throws MojoExecutionException {
|
||||||
|
try {
|
||||||
|
// todo : should we combine both compile and test scoped elements?
|
||||||
|
return ( List<String> ) project.getTestClasspathElements();
|
||||||
|
}
|
||||||
|
catch ( DependencyResolutionRequiredException e ) {
|
||||||
|
throw new MojoExecutionException( "Call to Project#getCompileClasspathElements required dependency resolution" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void performExecution(ClassLoader projectCompileScopeClassLoader) throws MojoExecutionException {
|
||||||
|
getLog().info( "gUnit report directory : " + reportDirectory.getAbsolutePath() );
|
||||||
|
if ( !reportDirectory.exists() ) {
|
||||||
|
boolean directoryCreated = reportDirectory.mkdirs();
|
||||||
|
if ( !directoryCreated ) {
|
||||||
|
getLog().warn( "mkdirs() reported problem creating report directory" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Result runningResults = new Result();
|
||||||
|
ArrayList<String> failureNames = new ArrayList<String>();
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println( "-----------------------------------------------------------" );
|
||||||
|
System.out.println( " G U N I T R E S U L T S" );
|
||||||
|
System.out.println( "-----------------------------------------------------------" );
|
||||||
|
|
||||||
|
for ( File script : collectIncludedSourceGrammars() ) {
|
||||||
|
final String scriptPath = script.getAbsolutePath();
|
||||||
|
System.out.println( "Executing script " + scriptPath );
|
||||||
|
try {
|
||||||
|
String scriptBaseName = StringUtils.chompLast( FileUtils.basename( script.getName() ), "." );
|
||||||
|
|
||||||
|
ANTLRFileStream antlrStream = new ANTLRFileStream( scriptPath );
|
||||||
|
GrammarInfo grammarInfo = Interp.parse( antlrStream );
|
||||||
|
gUnitExecutor executor = new gUnitExecutor(
|
||||||
|
grammarInfo,
|
||||||
|
projectCompileScopeClassLoader,
|
||||||
|
script.getParentFile().getAbsolutePath()
|
||||||
|
);
|
||||||
|
|
||||||
|
String report = executor.execTest();
|
||||||
|
writeReportFile( new File( reportDirectory, scriptBaseName + ".txt" ), report );
|
||||||
|
|
||||||
|
Result testResult = new Result();
|
||||||
|
testResult.tests = executor.numOfTest;
|
||||||
|
testResult.failures = executor.numOfFailure;
|
||||||
|
testResult.invalids = executor.numOfInvalidInput;
|
||||||
|
|
||||||
|
System.out.println( testResult.render() );
|
||||||
|
|
||||||
|
runningResults.add( testResult );
|
||||||
|
for ( AbstractTest test : executor.failures ) {
|
||||||
|
failureNames.add( scriptBaseName + "#" + test.getHeader() );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( IOException e ) {
|
||||||
|
throw new MojoExecutionException( "Could not open specified script file", e );
|
||||||
|
}
|
||||||
|
catch ( RecognitionException e ) {
|
||||||
|
throw new MojoExecutionException( "Could not parse gUnit script", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
System.out.println();
|
||||||
|
System.out.println( "Summary :" );
|
||||||
|
if ( ! failureNames.isEmpty() ) {
|
||||||
|
System.out.println( " Found " + failureNames.size() + " failures" );
|
||||||
|
for ( String name : failureNames ) {
|
||||||
|
System.out.println( " - " + name );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
System.out.println( runningResults.render() );
|
||||||
|
System.out.println();
|
||||||
|
|
||||||
|
if ( runningResults.failures > 0 ) {
|
||||||
|
throw new MojoExecutionException( "Found gUnit test failures" );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( runningResults.invalids > 0 ) {
|
||||||
|
throw new MojoExecutionException( "Found invalid gUnit tests" );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Set<File> collectIncludedSourceGrammars() throws MojoExecutionException {
|
||||||
|
SourceMapping mapping = new SuffixMapping( "g", Collections.<String>emptySet() );
|
||||||
|
SourceInclusionScanner scan = new SimpleSourceInclusionScanner( getIncludePatterns(), getExcludePatterns() );
|
||||||
|
scan.addSourceMapping( mapping );
|
||||||
|
try {
|
||||||
|
return scan.getIncludedSources( sourceDirectory, null );
|
||||||
|
}
|
||||||
|
catch ( InclusionScanException e ) {
|
||||||
|
throw new MojoExecutionException( "Error determining gUnit sources", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void writeReportFile(File reportFile, String results) {
|
||||||
|
try {
|
||||||
|
Writer writer = new FileWriter( reportFile );
|
||||||
|
writer = new BufferedWriter( writer );
|
||||||
|
try {
|
||||||
|
writer.write( results );
|
||||||
|
writer.flush();
|
||||||
|
}
|
||||||
|
finally {
|
||||||
|
try {
|
||||||
|
writer.close();
|
||||||
|
}
|
||||||
|
catch ( IOException ignore ) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch ( IOException e ) {
|
||||||
|
getLog().warn( "Error writing gUnit report file", e );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class Result {
|
||||||
|
private int tests = 0;
|
||||||
|
private int failures = 0;
|
||||||
|
private int invalids = 0;
|
||||||
|
|
||||||
|
public String render() {
|
||||||
|
return String.format( "Tests run: %d, Failures: %d, Invalid: %d", tests, failures, invalids );
|
||||||
|
}
|
||||||
|
|
||||||
|
public void add(Result result) {
|
||||||
|
this.tests += result.tests;
|
||||||
|
this.failures += result.failures;
|
||||||
|
this.invalids += result.invalids;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
127
outside/antlr3-antlr-3.5/gunit/CHANGES.txt
Normal file
127
outside/antlr3-antlr-3.5/gunit/CHANGES.txt
Normal file
@ -0,0 +1,127 @@
|
|||||||
|
gUnit
|
||||||
|
|
||||||
|
Leon, Jen-Yuan Su
|
||||||
|
leonsu at mac com
|
||||||
|
|
||||||
|
CHANGES
|
||||||
|
|
||||||
|
December 15, 2010
|
||||||
|
|
||||||
|
* TJP gunit checked tokens.index() != size instead of size()-1
|
||||||
|
|
||||||
|
November 26, 2010
|
||||||
|
|
||||||
|
* Added -p package-name-for-junit-output since test package is usually
|
||||||
|
different than parser package. TJP
|
||||||
|
|
||||||
|
January 24, 2009
|
||||||
|
|
||||||
|
* Improved error messages
|
||||||
|
|
||||||
|
* stderr was being ignored upon exception.
|
||||||
|
|
||||||
|
* generated junit test code indicate lines in gunit script. also error
|
||||||
|
messages during parse time show line number from gunit script.
|
||||||
|
|
||||||
|
* refactored template generation / parameters
|
||||||
|
|
||||||
|
* Allow strings in AST descriptions (gUnit.g). E.g., it handle this rule
|
||||||
|
(I had to quote the "^(" root tokens):
|
||||||
|
|
||||||
|
block:
|
||||||
|
"( ^(A B) | ^(b C) )" -> (BLOCK (ALT ("^(" A B)) (ALT ("^(" b C)))
|
||||||
|
|
||||||
|
|
||||||
|
January 23, 2009
|
||||||
|
|
||||||
|
* whitespace ignored and "x y z" turned into x y z now in expected tree p\
|
||||||
|
attern. E.g.,
|
||||||
|
|
||||||
|
rule:
|
||||||
|
"a : A<X,Y=a.b.c>;" -> (RULE a (BLOCK (ALT
|
||||||
|
(A (ELEMENT_OPTIONS X (= Y "a.b.c")))))
|
||||||
|
)
|
||||||
|
|
||||||
|
July 31, 2009
|
||||||
|
|
||||||
|
* support custom tree adaptor in gUnit script
|
||||||
|
|
||||||
|
March 21, 2009
|
||||||
|
|
||||||
|
* gUnitTestSuite.java: use lexer rule name if parser rule name is null (by Shaoting)
|
||||||
|
|
||||||
|
* add gunit/swingui package for gUnitEditor GUI
|
||||||
|
|
||||||
|
Feb 17, 2009
|
||||||
|
|
||||||
|
* added new interfaces for GUI editor
|
||||||
|
|
||||||
|
* recognizes invalid input as a FAIL case instead of throwing an exception
|
||||||
|
|
||||||
|
Steve Ebersole provided a patch for the following two fixes.
|
||||||
|
* allows setting an output directory (for JUnitCodeGen)
|
||||||
|
|
||||||
|
* allows providing a classloader (for both JUnitCodeGen and gUnitExecutor)
|
||||||
|
|
||||||
|
Nov 25, 2008
|
||||||
|
|
||||||
|
* fixed external test file path issue. if an input test file is not found under the current dir, then try to look for it under the package dir also.
|
||||||
|
|
||||||
|
* fixed multiple-line input indentation issue.
|
||||||
|
|
||||||
|
* fixed bug: FileNotFoundException terminated gUnit tests due to any non-existent input test file.
|
||||||
|
|
||||||
|
* display escaped text for newline characters in the test result for comparing expected and actual string.
|
||||||
|
|
||||||
|
Nov 20, 2008
|
||||||
|
|
||||||
|
* added new functionality of testing lexical rules
|
||||||
|
|
||||||
|
* fixed bug of using PipedInput/Output Stream and changed to ByteArrayOutputStream. Jared Bunting provided a patch on this issue.
|
||||||
|
|
||||||
|
* improved jUnit translation mode and moved supporting codes into gUnitBaseTest.
|
||||||
|
|
||||||
|
Oct 31, 2008
|
||||||
|
|
||||||
|
* fixed bug of testing a tree grammar's template output
|
||||||
|
|
||||||
|
July 9, 2008
|
||||||
|
|
||||||
|
* fixed bug: program exited upon InvocationTargetException
|
||||||
|
Sumanto Biswas pointed out the issue and provided suggestions.
|
||||||
|
|
||||||
|
* Better handle on test rule's StringTemplate output
|
||||||
|
|
||||||
|
May 10, 2008
|
||||||
|
|
||||||
|
* added exit code functionality
|
||||||
|
|
||||||
|
* fixed string escaping bug for junit generator
|
||||||
|
|
||||||
|
1.0.2 - Apr 01, 2008
|
||||||
|
|
||||||
|
* fixed grammar bug: multiple-line input, AST output
|
||||||
|
|
||||||
|
* adjusted the output of test result
|
||||||
|
|
||||||
|
Mar 20, 2008
|
||||||
|
|
||||||
|
* moved test result to string template (gUnitTestResult.stg)
|
||||||
|
|
||||||
|
* added the display of line of test in the test result
|
||||||
|
|
||||||
|
Feb 19, 2008
|
||||||
|
|
||||||
|
* fixed bug of displaying test sequence and error message from ANTLR
|
||||||
|
|
||||||
|
Feb 8, 2008
|
||||||
|
|
||||||
|
* made compatible with ANTLR 3.1b1
|
||||||
|
|
||||||
|
1.0.1 - Jan 11, 2008
|
||||||
|
|
||||||
|
* Kenny MacDermid helps with code refactoring
|
||||||
|
|
||||||
|
1.0 - Aug 20, 2007
|
||||||
|
|
||||||
|
Initial early access release
|
26
outside/antlr3-antlr-3.5/gunit/LICENSE.txt
Normal file
26
outside/antlr3-antlr-3.5/gunit/LICENSE.txt
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon, Jen-Yuan Su
|
||||||
|
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.
|
56
outside/antlr3-antlr-3.5/gunit/README.txt
Normal file
56
outside/antlr3-antlr-3.5/gunit/README.txt
Normal file
@ -0,0 +1,56 @@
|
|||||||
|
gUnit
|
||||||
|
Feb 21, 2009
|
||||||
|
|
||||||
|
Leon, Jen-Yuan Su
|
||||||
|
leonsu at mac com
|
||||||
|
|
||||||
|
INTRODUCTION
|
||||||
|
|
||||||
|
Welcome to gUnit! I've been working on gUnit from 2007 summer and
|
||||||
|
this is a project in USF CS, sponsored by professor Terence Parr.
|
||||||
|
|
||||||
|
You should use the latest ANTLR v3 with gUnit:
|
||||||
|
|
||||||
|
http://www.antlr.org/download.html
|
||||||
|
|
||||||
|
See the wiki document:
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/display/ANTLR3/gUnit+-+Grammar+Unit+Testing
|
||||||
|
|
||||||
|
Per the license in LICENSE.txt, this software is not guaranteed to
|
||||||
|
work and might even destroy all life on this planet:
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
EXAMPLES
|
||||||
|
|
||||||
|
See the wiki tutorial of gUnit:
|
||||||
|
|
||||||
|
http://www.antlr.org/wiki/display/ANTLR3/gUnit+-+Grammar+Unit+Testing
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
What is gUnit?
|
||||||
|
|
||||||
|
gUnit is an unit testing framework for ANTLR grammars. It provides a
|
||||||
|
simple way to write and run automated tests for grammars in a manner
|
||||||
|
similar to what jUnit does for unit testing.
|
||||||
|
|
||||||
|
----------------------------------------------------------------------
|
||||||
|
|
||||||
|
How do I install gUnit?
|
||||||
|
|
||||||
|
It is included in ANTLR v3; it needs both ANTLR and StringTemplate jars
|
||||||
|
in CLASSPATH.
|
0
outside/antlr3-antlr-3.5/gunit/antlr.config
Normal file
0
outside/antlr3-antlr-3.5/gunit/antlr.config
Normal file
82
outside/antlr3-antlr-3.5/gunit/pom.xml
Normal file
82
outside/antlr3-antlr-3.5/gunit/pom.xml
Normal file
@ -0,0 +1,82 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>gunit</artifactId>
|
||||||
|
<packaging>jar</packaging>
|
||||||
|
|
||||||
|
<name>ANTLR 3 gUnit</name>
|
||||||
|
<description>gUnit grammar testing tool for ANTLR 3</description>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Inherit from the ANTLR master pom, which tells us what
|
||||||
|
version we are and allows us to inherit dependencies
|
||||||
|
and so on.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<parent>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr-master</artifactId>
|
||||||
|
<version>3.5</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<url>http://www.antlr.org/wiki/display/ANTLR3/gUnit+-+Grammar+Unit+Testing</url>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
|
||||||
|
Tell Maven which other artifacts we need in order to
|
||||||
|
build, run and test the ANTLR Tool. The ANTLR Tool uses earlier versions
|
||||||
|
of ANTLR at runtime (for the moment), uses the current
|
||||||
|
released version of ANTLR String template, but obviously is
|
||||||
|
reliant on the latest snapshot of the runtime, which will either be
|
||||||
|
taken from the antlr-snapshot repository, or your local .m2
|
||||||
|
repository if you built and installed that locally.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<dependencies>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>junit</groupId>
|
||||||
|
<artifactId>junit</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<scope>compile</scope>
|
||||||
|
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>stringtemplate</artifactId>
|
||||||
|
<scope>compile</scope>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
</dependencies>
|
||||||
|
|
||||||
|
<build>
|
||||||
|
|
||||||
|
<plugins>
|
||||||
|
|
||||||
|
<plugin>
|
||||||
|
<groupId>org.antlr</groupId>
|
||||||
|
<artifactId>antlr3-maven-plugin</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
<configuration></configuration>
|
||||||
|
<executions>
|
||||||
|
<execution>
|
||||||
|
<goals>
|
||||||
|
<goal>antlr</goal>
|
||||||
|
</goals>
|
||||||
|
</execution>
|
||||||
|
</executions>
|
||||||
|
</plugin>
|
||||||
|
|
||||||
|
</plugins>
|
||||||
|
|
||||||
|
</build>
|
||||||
|
|
||||||
|
</project>
|
@ -0,0 +1,352 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon Jen-Yuan Su
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
grammar gUnit;
|
||||||
|
options {language=Java;}
|
||||||
|
tokens {
|
||||||
|
OK = 'OK';
|
||||||
|
FAIL = 'FAIL';
|
||||||
|
DOC_COMMENT;
|
||||||
|
}
|
||||||
|
@header {package org.antlr.gunit;}
|
||||||
|
@lexer::header {
|
||||||
|
package org.antlr.gunit;
|
||||||
|
import java.io.BufferedReader;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.StringReader;
|
||||||
|
}
|
||||||
|
@members {
|
||||||
|
public GrammarInfo grammarInfo;
|
||||||
|
public gUnitParser(TokenStream input, GrammarInfo grammarInfo) {
|
||||||
|
super(input);
|
||||||
|
this.grammarInfo = grammarInfo;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
gUnitDef: 'gunit' g1=id ('walks' g2=id)? ';'
|
||||||
|
{
|
||||||
|
if ( $g2.text!=null ) {
|
||||||
|
grammarInfo.setGrammarName($g2.text);
|
||||||
|
grammarInfo.setTreeGrammarName($g1.text);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
grammarInfo.setGrammarName($g1.text);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
optionsSpec? header? testsuite*
|
||||||
|
;
|
||||||
|
|
||||||
|
optionsSpec
|
||||||
|
: OPTIONS (option ';')+ '}'
|
||||||
|
;
|
||||||
|
|
||||||
|
// Note: currently, this is the only valid option for setting customized tree adaptor
|
||||||
|
option : id '=' treeAdaptor
|
||||||
|
{
|
||||||
|
if ( $id.text.equals("TreeAdaptor") ) {
|
||||||
|
grammarInfo.setAdaptor($treeAdaptor.text);
|
||||||
|
}
|
||||||
|
// TODO: need a better error logging strategy
|
||||||
|
else System.err.println("Invalid option detected: "+$text);
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
treeAdaptor
|
||||||
|
: id EXT*
|
||||||
|
;
|
||||||
|
|
||||||
|
header : '@header' ACTION
|
||||||
|
{
|
||||||
|
int pos1, pos2;
|
||||||
|
if ( (pos1=$ACTION.text.indexOf("package"))!=-1 && (pos2=$ACTION.text.indexOf(';'))!=-1 ) {
|
||||||
|
grammarInfo.setGrammarPackage($ACTION.text.substring(pos1+8, pos2).trim()); // substring the package path
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
System.err.println("error(line "+$ACTION.getLine()+"): invalid header");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
testsuite // gUnit test suite based on individual rule
|
||||||
|
scope {
|
||||||
|
boolean isLexicalRule;
|
||||||
|
}
|
||||||
|
@init {
|
||||||
|
gUnitTestSuite ts = null;
|
||||||
|
$testsuite::isLexicalRule = false;
|
||||||
|
}
|
||||||
|
: ( r1=RULE_REF ('walks' r2=RULE_REF)?
|
||||||
|
{
|
||||||
|
if ( $r2==null ) ts = new gUnitTestSuite($r1.text);
|
||||||
|
else ts = new gUnitTestSuite($r1.text, $r2.text);
|
||||||
|
}
|
||||||
|
| t=TOKEN_REF
|
||||||
|
{
|
||||||
|
ts = new gUnitTestSuite();
|
||||||
|
ts.setLexicalRuleName($t.text);
|
||||||
|
$testsuite::isLexicalRule = true;
|
||||||
|
}
|
||||||
|
)
|
||||||
|
':'
|
||||||
|
testcase[ts]+ {grammarInfo.addRuleTestSuite(ts);}
|
||||||
|
;
|
||||||
|
|
||||||
|
// TODO : currently gUnit just ignores illegal test for lexer rule, but should also emit a reminding message
|
||||||
|
testcase[gUnitTestSuite ts] // individual test within a (rule)testsuite
|
||||||
|
: input expect {$ts.addTestCase($input.in, $expect.out);}
|
||||||
|
;
|
||||||
|
|
||||||
|
input returns [gUnitTestInput in]
|
||||||
|
@init {
|
||||||
|
String testInput = null;
|
||||||
|
boolean inputIsFile = false;
|
||||||
|
int line = -1;
|
||||||
|
}
|
||||||
|
@after {
|
||||||
|
in = new gUnitTestInput(testInput, inputIsFile, line);
|
||||||
|
}
|
||||||
|
: STRING
|
||||||
|
{
|
||||||
|
testInput = $STRING.text.replace("\\n", "\n").replace("\\r", "\r").replace("\\t", "\t")
|
||||||
|
.replace("\\b", "\b").replace("\\f", "\f").replace("\\\"", "\"").replace("\\'", "\'").replace("\\\\", "\\");
|
||||||
|
line = $STRING.line;
|
||||||
|
}
|
||||||
|
| ML_STRING
|
||||||
|
{
|
||||||
|
testInput = $ML_STRING.text;
|
||||||
|
line = $ML_STRING.line;
|
||||||
|
}
|
||||||
|
| file
|
||||||
|
{
|
||||||
|
testInput = $file.text;
|
||||||
|
inputIsFile = true;
|
||||||
|
line = $file.line;
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
expect returns [AbstractTest out]
|
||||||
|
: OK {$out = new BooleanTest(true);}
|
||||||
|
| FAIL {$out = new BooleanTest(false);}
|
||||||
|
| 'returns' RETVAL {if ( !$testsuite::isLexicalRule ) $out = new ReturnTest($RETVAL);}
|
||||||
|
| '->' output {if ( !$testsuite::isLexicalRule ) $out = new OutputTest($output.token);}
|
||||||
|
;
|
||||||
|
|
||||||
|
output returns [Token token]
|
||||||
|
: STRING
|
||||||
|
{
|
||||||
|
$STRING.setText($STRING.text.replace("\\n", "\n").replace("\\r", "\r").replace("\\t", "\t")
|
||||||
|
.replace("\\b", "\b").replace("\\f", "\f").replace("\\\"", "\"").replace("\\'", "\'").replace("\\\\", "\\"));
|
||||||
|
$token = $STRING;
|
||||||
|
}
|
||||||
|
| ML_STRING {$token = $ML_STRING;}
|
||||||
|
| AST {$token = $AST;}
|
||||||
|
| ACTION {$token = $ACTION;}
|
||||||
|
;
|
||||||
|
|
||||||
|
file returns [int line]
|
||||||
|
: id EXT? {$line = $id.line;}
|
||||||
|
;
|
||||||
|
|
||||||
|
id returns [int line]
|
||||||
|
: TOKEN_REF {$line = $TOKEN_REF.line;}
|
||||||
|
| RULE_REF {$line = $RULE_REF.line;}
|
||||||
|
;
|
||||||
|
|
||||||
|
// L E X I C A L R U L E S
|
||||||
|
|
||||||
|
SL_COMMENT
|
||||||
|
: '//' ~('\r'|'\n')* '\r'? '\n' {$channel=HIDDEN;}
|
||||||
|
;
|
||||||
|
|
||||||
|
ML_COMMENT
|
||||||
|
: '/*' {$channel=HIDDEN;} .* '*/'
|
||||||
|
;
|
||||||
|
|
||||||
|
STRING : '"' ( ESC | ~('\\'|'"') )* '"' {setText(getText().substring(1, getText().length()-1));}
|
||||||
|
;
|
||||||
|
|
||||||
|
ML_STRING
|
||||||
|
: {// we need to determine the number of spaces or tabs (indentation) for multi-line input
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
int i = -1;
|
||||||
|
int c = input.LA(-1);
|
||||||
|
while ( c==' ' || c=='\t' ) {
|
||||||
|
buf.append((char)c);
|
||||||
|
c = input.LA(--i);
|
||||||
|
}
|
||||||
|
String indentation = buf.reverse().toString();
|
||||||
|
}
|
||||||
|
'<<' .* '>>'
|
||||||
|
{// also determine the appropriate newline separator and get info of the first and last 2 characters (exclude '<<' and '>>')
|
||||||
|
String newline = System.getProperty("line.separator");
|
||||||
|
String front, end;
|
||||||
|
int oldFrontIndex = 2;
|
||||||
|
int oldEndIndex = getText().length()-2;
|
||||||
|
int newFrontIndex, newEndIndex;
|
||||||
|
if ( newline.length()==1 ) {
|
||||||
|
front = getText().substring(2, 3);
|
||||||
|
end = getText().substring(getText().length()-3, getText().length()-2);
|
||||||
|
newFrontIndex = 3;
|
||||||
|
newEndIndex = getText().length()-3;
|
||||||
|
}
|
||||||
|
else {// must be 2, e.g. Windows System which uses \r\n as a line separator
|
||||||
|
front = getText().substring(2, 4);
|
||||||
|
end = getText().substring(getText().length()-4, getText().length()-2);
|
||||||
|
newFrontIndex = 4;
|
||||||
|
newEndIndex = getText().length()-4;
|
||||||
|
}
|
||||||
|
// strip unwanted characters, e.g. '<<' (including a newline after it) or '>>' (including a newline before it)
|
||||||
|
String temp = null;
|
||||||
|
if ( front.equals(newline) && end.equals(newline) ) {
|
||||||
|
// need to handle the special case: <<\n>> or <<\r\n>>
|
||||||
|
if ( newline.length()==1 && getText().length()==5 ) temp = "";
|
||||||
|
else if ( newline.length()==2 && getText().length()==6 ) temp = "";
|
||||||
|
else temp = getText().substring(newFrontIndex, newEndIndex);
|
||||||
|
}
|
||||||
|
else if ( front.equals(newline) ) {
|
||||||
|
temp = getText().substring(newFrontIndex, oldEndIndex);
|
||||||
|
}
|
||||||
|
else if ( end.equals(newline) ) {
|
||||||
|
temp = getText().substring(oldFrontIndex, newEndIndex);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
temp = getText().substring(oldFrontIndex, oldEndIndex);
|
||||||
|
}
|
||||||
|
// finally we need to prpcess the indentation line by line
|
||||||
|
BufferedReader bufReader = new BufferedReader(new StringReader(temp));
|
||||||
|
buf = new StringBuffer();
|
||||||
|
String line = null;
|
||||||
|
int count = 0;
|
||||||
|
try {
|
||||||
|
while((line = bufReader.readLine()) != null) {
|
||||||
|
if ( line.startsWith(indentation) ) line = line.substring(indentation.length());
|
||||||
|
if ( count>0 ) buf.append(newline);
|
||||||
|
buf.append(line);
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
setText(buf.toString());
|
||||||
|
}
|
||||||
|
catch (IOException ioe) {
|
||||||
|
setText(temp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
TOKEN_REF
|
||||||
|
: 'A'..'Z' ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
|
||||||
|
;
|
||||||
|
|
||||||
|
RULE_REF
|
||||||
|
: 'a'..'z' ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
|
||||||
|
;
|
||||||
|
|
||||||
|
EXT : '.'('a'..'z'|'A'..'Z'|'0'..'9')+;
|
||||||
|
|
||||||
|
RETVAL : NESTED_RETVAL {setText(getText().substring(1, getText().length()-1));}
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
NESTED_RETVAL :
|
||||||
|
'['
|
||||||
|
( options {greedy=false;}
|
||||||
|
: NESTED_RETVAL
|
||||||
|
| .
|
||||||
|
)*
|
||||||
|
']'
|
||||||
|
;
|
||||||
|
|
||||||
|
AST : NESTED_AST (' '? NESTED_AST)*;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
NESTED_AST :
|
||||||
|
'('
|
||||||
|
( NESTED_AST
|
||||||
|
| STRING_LITERAL
|
||||||
|
| ~('('|')'|'"')
|
||||||
|
)*
|
||||||
|
')'
|
||||||
|
;
|
||||||
|
|
||||||
|
OPTIONS : 'options' WS* '{'
|
||||||
|
;
|
||||||
|
|
||||||
|
ACTION
|
||||||
|
: NESTED_ACTION {setText(getText().substring(1, getText().length()-1));}
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
NESTED_ACTION :
|
||||||
|
'{'
|
||||||
|
( options {greedy=false; k=3;}
|
||||||
|
: NESTED_ACTION
|
||||||
|
| STRING_LITERAL
|
||||||
|
| CHAR_LITERAL
|
||||||
|
| .
|
||||||
|
)*
|
||||||
|
'}'
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
CHAR_LITERAL
|
||||||
|
: '\'' ( ESC | ~('\''|'\\') ) '\''
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
STRING_LITERAL
|
||||||
|
: '"' ( ESC | ~('\\'|'"') )* '"'
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
ESC : '\\'
|
||||||
|
( 'n'
|
||||||
|
| 'r'
|
||||||
|
| 't'
|
||||||
|
| 'b'
|
||||||
|
| 'f'
|
||||||
|
| '"'
|
||||||
|
| '\''
|
||||||
|
| '\\'
|
||||||
|
| '>'
|
||||||
|
| 'u' XDIGIT XDIGIT XDIGIT XDIGIT
|
||||||
|
| . // unknown, leave as it is
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
XDIGIT :
|
||||||
|
'0' .. '9'
|
||||||
|
| 'a' .. 'f'
|
||||||
|
| 'A' .. 'F'
|
||||||
|
;
|
||||||
|
|
||||||
|
WS : ( ' '
|
||||||
|
| '\t'
|
||||||
|
| '\r'? '\n'
|
||||||
|
)+
|
||||||
|
{$channel=HIDDEN;}
|
||||||
|
;
|
@ -0,0 +1,619 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2005-2007 Terence Parr
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** ANTLR v3 grammar written in ANTLR v3 with AST construction */
|
||||||
|
grammar ANTLRv3;
|
||||||
|
|
||||||
|
options {
|
||||||
|
output=AST;
|
||||||
|
ASTLabelType=CommonTree;
|
||||||
|
}
|
||||||
|
|
||||||
|
tokens {
|
||||||
|
DOC_COMMENT;
|
||||||
|
PARSER;
|
||||||
|
LEXER;
|
||||||
|
RULE;
|
||||||
|
BLOCK;
|
||||||
|
OPTIONAL;
|
||||||
|
CLOSURE;
|
||||||
|
POSITIVE_CLOSURE;
|
||||||
|
SYNPRED;
|
||||||
|
RANGE;
|
||||||
|
CHAR_RANGE;
|
||||||
|
EPSILON;
|
||||||
|
ALT;
|
||||||
|
EOR;
|
||||||
|
EOB;
|
||||||
|
EOA; // end of alt
|
||||||
|
ID;
|
||||||
|
ARG;
|
||||||
|
ARGLIST;
|
||||||
|
RET;
|
||||||
|
LEXER_GRAMMAR;
|
||||||
|
PARSER_GRAMMAR;
|
||||||
|
TREE_GRAMMAR;
|
||||||
|
COMBINED_GRAMMAR;
|
||||||
|
INITACTION;
|
||||||
|
LABEL; // $x used in rewrite rules
|
||||||
|
TEMPLATE;
|
||||||
|
SCOPE='scope';
|
||||||
|
SEMPRED;
|
||||||
|
GATED_SEMPRED; // {p}? =>
|
||||||
|
SYN_SEMPRED; // (...) => it's a manually-specified synpred converted to sempred
|
||||||
|
BACKTRACK_SEMPRED; // auto backtracking mode syn pred converted to sempred
|
||||||
|
FRAGMENT='fragment';
|
||||||
|
TREE_BEGIN='^(';
|
||||||
|
ROOT='^';
|
||||||
|
BANG='!';
|
||||||
|
RANGE='..';
|
||||||
|
REWRITE='->';
|
||||||
|
}
|
||||||
|
|
||||||
|
@members {
|
||||||
|
int gtype;
|
||||||
|
public List<String> rules;
|
||||||
|
}
|
||||||
|
|
||||||
|
@header {
|
||||||
|
package org.antlr.gunit.swingui.parsers;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
}
|
||||||
|
|
||||||
|
@lexer::header {
|
||||||
|
package org.antlr.gunit.swingui.parsers;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
grammarDef
|
||||||
|
: DOC_COMMENT?
|
||||||
|
( 'lexer' {gtype=LEXER_GRAMMAR;} // pure lexer
|
||||||
|
| 'parser' {gtype=PARSER_GRAMMAR;} // pure parser
|
||||||
|
| 'tree' {gtype=TREE_GRAMMAR;} // a tree parser
|
||||||
|
| {gtype=COMBINED_GRAMMAR;} // merged parser/lexer
|
||||||
|
)
|
||||||
|
g='grammar' id ';' optionsSpec? tokensSpec? attrScope* action*
|
||||||
|
rule+
|
||||||
|
EOF
|
||||||
|
-> ^( {adaptor.create(gtype,$g)}
|
||||||
|
id DOC_COMMENT? optionsSpec? tokensSpec? attrScope* action* rule+
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
tokensSpec
|
||||||
|
: TOKENS tokenSpec+ '}' -> ^(TOKENS tokenSpec+)
|
||||||
|
;
|
||||||
|
|
||||||
|
tokenSpec
|
||||||
|
: TOKEN_REF
|
||||||
|
( '=' (lit=STRING_LITERAL|lit=CHAR_LITERAL) -> ^('=' TOKEN_REF $lit)
|
||||||
|
| -> TOKEN_REF
|
||||||
|
)
|
||||||
|
';'
|
||||||
|
;
|
||||||
|
|
||||||
|
attrScope
|
||||||
|
: 'scope' id ACTION -> ^('scope' id ACTION)
|
||||||
|
;
|
||||||
|
|
||||||
|
/** Match stuff like @parser::members {int i;} */
|
||||||
|
action
|
||||||
|
: '@' (actionScopeName '::')? id ACTION -> ^('@' actionScopeName? id ACTION)
|
||||||
|
;
|
||||||
|
|
||||||
|
/** Sometimes the scope names will collide with keywords; allow them as
|
||||||
|
* ids for action scopes.
|
||||||
|
*/
|
||||||
|
actionScopeName
|
||||||
|
: id
|
||||||
|
| l='lexer' -> ID[$l]
|
||||||
|
| p='parser' -> ID[$p]
|
||||||
|
;
|
||||||
|
|
||||||
|
optionsSpec
|
||||||
|
: OPTIONS (option ';')+ '}' -> ^(OPTIONS option+)
|
||||||
|
;
|
||||||
|
|
||||||
|
option
|
||||||
|
: id '=' optionValue -> ^('=' id optionValue)
|
||||||
|
;
|
||||||
|
|
||||||
|
optionValue
|
||||||
|
: id
|
||||||
|
| STRING_LITERAL
|
||||||
|
| CHAR_LITERAL
|
||||||
|
| INT
|
||||||
|
| s='*' -> STRING_LITERAL[$s] // used for k=*
|
||||||
|
;
|
||||||
|
|
||||||
|
rule
|
||||||
|
scope {
|
||||||
|
String name;
|
||||||
|
}
|
||||||
|
@after{
|
||||||
|
this.rules.add($rule::name);
|
||||||
|
}
|
||||||
|
: DOC_COMMENT?
|
||||||
|
( modifier=('protected'|'public'|'private'|'fragment') )?
|
||||||
|
id {$rule::name = $id.text;}
|
||||||
|
'!'?
|
||||||
|
( arg=ARG_ACTION )?
|
||||||
|
( 'returns' rt=ARG_ACTION )?
|
||||||
|
throwsSpec? optionsSpec? ruleScopeSpec? ruleAction*
|
||||||
|
':' altList ';'
|
||||||
|
exceptionGroup?
|
||||||
|
-> ^( RULE id {modifier!=null?adaptor.create(modifier):null} ^(ARG $arg)? ^(RET $rt)?
|
||||||
|
optionsSpec? ruleScopeSpec? ruleAction*
|
||||||
|
altList
|
||||||
|
exceptionGroup?
|
||||||
|
EOR["EOR"]
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
/** Match stuff like @init {int i;} */
|
||||||
|
ruleAction
|
||||||
|
: '@' id ACTION -> ^('@' id ACTION)
|
||||||
|
;
|
||||||
|
|
||||||
|
throwsSpec
|
||||||
|
: 'throws' id ( ',' id )* -> ^('throws' id+)
|
||||||
|
;
|
||||||
|
|
||||||
|
ruleScopeSpec
|
||||||
|
: 'scope' ACTION -> ^('scope' ACTION)
|
||||||
|
| 'scope' id (',' id)* ';' -> ^('scope' id+)
|
||||||
|
| 'scope' ACTION
|
||||||
|
'scope' id (',' id)* ';'
|
||||||
|
-> ^('scope' ACTION id+ )
|
||||||
|
;
|
||||||
|
|
||||||
|
block
|
||||||
|
: lp='('
|
||||||
|
( (opts=optionsSpec)? ':' )?
|
||||||
|
a1=alternative rewrite ( '|' a2=alternative rewrite )*
|
||||||
|
rp=')'
|
||||||
|
-> ^( BLOCK[$lp,"BLOCK"] optionsSpec? (alternative rewrite?)+ EOB[$rp,"EOB"] )
|
||||||
|
;
|
||||||
|
|
||||||
|
altList
|
||||||
|
@init {
|
||||||
|
// must create root manually as it's used by invoked rules in real antlr tool.
|
||||||
|
// leave here to demonstrate use of {...} in rewrite rule
|
||||||
|
// it's really BLOCK[firstToken,"BLOCK"]; set line/col to previous ( or : token.
|
||||||
|
CommonTree blkRoot = (CommonTree)adaptor.create(BLOCK,input.LT(-1),"BLOCK");
|
||||||
|
}
|
||||||
|
: a1=alternative rewrite ( '|' a2=alternative rewrite )*
|
||||||
|
-> ^( {blkRoot} (alternative rewrite?)+ EOB["EOB"] )
|
||||||
|
;
|
||||||
|
|
||||||
|
alternative
|
||||||
|
@init {
|
||||||
|
Token firstToken = input.LT(1);
|
||||||
|
Token prevToken = input.LT(-1); // either : or | I think
|
||||||
|
}
|
||||||
|
: element+ -> ^(ALT[firstToken,"ALT"] element+ EOA["EOA"])
|
||||||
|
| -> ^(ALT[prevToken,"ALT"] EPSILON[prevToken,"EPSILON"] EOA["EOA"])
|
||||||
|
;
|
||||||
|
|
||||||
|
exceptionGroup
|
||||||
|
: ( exceptionHandler )+ ( finallyClause )?
|
||||||
|
| finallyClause
|
||||||
|
;
|
||||||
|
|
||||||
|
exceptionHandler
|
||||||
|
: 'catch' ARG_ACTION ACTION -> ^('catch' ARG_ACTION ACTION)
|
||||||
|
;
|
||||||
|
|
||||||
|
finallyClause
|
||||||
|
: 'finally' ACTION -> ^('finally' ACTION)
|
||||||
|
;
|
||||||
|
|
||||||
|
element
|
||||||
|
: elementNoOptionSpec
|
||||||
|
;
|
||||||
|
|
||||||
|
elementNoOptionSpec
|
||||||
|
: id (labelOp='='|labelOp='+=') atom
|
||||||
|
( ebnfSuffix -> ^( ebnfSuffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] ^($labelOp id atom) EOA["EOA"]) EOB["EOB"]))
|
||||||
|
| -> ^($labelOp id atom)
|
||||||
|
)
|
||||||
|
| id (labelOp='='|labelOp='+=') block
|
||||||
|
( ebnfSuffix -> ^( ebnfSuffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] ^($labelOp id block) EOA["EOA"]) EOB["EOB"]))
|
||||||
|
| -> ^($labelOp id block)
|
||||||
|
)
|
||||||
|
| atom
|
||||||
|
( ebnfSuffix -> ^( ebnfSuffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] atom EOA["EOA"]) EOB["EOB"]) )
|
||||||
|
| -> atom
|
||||||
|
)
|
||||||
|
| ebnf
|
||||||
|
| ACTION
|
||||||
|
| SEMPRED ( '=>' -> GATED_SEMPRED | -> SEMPRED )
|
||||||
|
| treeSpec
|
||||||
|
( ebnfSuffix -> ^( ebnfSuffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] treeSpec EOA["EOA"]) EOB["EOB"]) )
|
||||||
|
| -> treeSpec
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
atom: range ( (op='^'|op='!') -> ^($op range) | -> range )
|
||||||
|
| terminal
|
||||||
|
| notSet ( (op='^'|op='!') -> ^($op notSet) | -> notSet )
|
||||||
|
| RULE_REF ( arg=ARG_ACTION )? ( (op='^'|op='!') )?
|
||||||
|
-> {$arg!=null&&op!=null}? ^($op RULE_REF $arg)
|
||||||
|
-> {$arg!=null}? ^(RULE_REF $arg)
|
||||||
|
-> {$op!=null}? ^($op RULE_REF)
|
||||||
|
-> RULE_REF
|
||||||
|
;
|
||||||
|
|
||||||
|
notSet
|
||||||
|
: '~'
|
||||||
|
( notTerminal -> ^('~' notTerminal)
|
||||||
|
| block -> ^('~' block)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
treeSpec
|
||||||
|
: '^(' element ( element )+ ')' -> ^(TREE_BEGIN element+)
|
||||||
|
;
|
||||||
|
|
||||||
|
/** Matches ENBF blocks (and token sets via block rule) */
|
||||||
|
ebnf
|
||||||
|
@init {
|
||||||
|
Token firstToken = input.LT(1);
|
||||||
|
}
|
||||||
|
@after {
|
||||||
|
$ebnf.tree.getToken().setLine(firstToken.getLine());
|
||||||
|
$ebnf.tree.getToken().setCharPositionInLine(firstToken.getCharPositionInLine());
|
||||||
|
}
|
||||||
|
: block
|
||||||
|
( op='?' -> ^(OPTIONAL[op] block)
|
||||||
|
| op='*' -> ^(CLOSURE[op] block)
|
||||||
|
| op='+' -> ^(POSITIVE_CLOSURE[op] block)
|
||||||
|
| '=>' // syntactic predicate
|
||||||
|
-> {gtype==COMBINED_GRAMMAR &&
|
||||||
|
Character.isUpperCase($rule::name.charAt(0))}?
|
||||||
|
// if lexer rule in combined, leave as pred for lexer
|
||||||
|
^(SYNPRED["=>"] block)
|
||||||
|
// in real antlr tool, text for SYN_SEMPRED is predname
|
||||||
|
-> SYN_SEMPRED
|
||||||
|
| -> block
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
range!
|
||||||
|
: c1=CHAR_LITERAL RANGE c2=CHAR_LITERAL -> ^(CHAR_RANGE[$c1,".."] $c1 $c2)
|
||||||
|
;
|
||||||
|
|
||||||
|
terminal
|
||||||
|
: ( CHAR_LITERAL -> CHAR_LITERAL
|
||||||
|
// Args are only valid for lexer rules
|
||||||
|
| TOKEN_REF
|
||||||
|
( ARG_ACTION -> ^(TOKEN_REF ARG_ACTION)
|
||||||
|
| -> TOKEN_REF
|
||||||
|
)
|
||||||
|
| STRING_LITERAL -> STRING_LITERAL
|
||||||
|
| '.' -> '.'
|
||||||
|
)
|
||||||
|
( '^' -> ^('^' $terminal)
|
||||||
|
| '!' -> ^('!' $terminal)
|
||||||
|
)?
|
||||||
|
;
|
||||||
|
|
||||||
|
notTerminal
|
||||||
|
: CHAR_LITERAL
|
||||||
|
| TOKEN_REF
|
||||||
|
| STRING_LITERAL
|
||||||
|
;
|
||||||
|
|
||||||
|
ebnfSuffix
|
||||||
|
@init {
|
||||||
|
Token op = input.LT(1);
|
||||||
|
}
|
||||||
|
: '?' -> OPTIONAL[op]
|
||||||
|
| '*' -> CLOSURE[op]
|
||||||
|
| '+' -> POSITIVE_CLOSURE[op]
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// R E W R I T E S Y N T A X
|
||||||
|
|
||||||
|
rewrite
|
||||||
|
@init {
|
||||||
|
Token firstToken = input.LT(1);
|
||||||
|
}
|
||||||
|
: (rew+='->' preds+=SEMPRED predicated+=rewrite_alternative)*
|
||||||
|
rew2='->' last=rewrite_alternative
|
||||||
|
-> ^($rew $preds $predicated)* ^($rew2 $last)
|
||||||
|
|
|
||||||
|
;
|
||||||
|
|
||||||
|
rewrite_alternative
|
||||||
|
options {backtrack=true;}
|
||||||
|
: rewrite_template
|
||||||
|
| rewrite_tree_alternative
|
||||||
|
| /* empty rewrite */ -> ^(ALT["ALT"] EPSILON["EPSILON"] EOA["EOA"])
|
||||||
|
;
|
||||||
|
|
||||||
|
rewrite_tree_block
|
||||||
|
: lp='(' rewrite_tree_alternative ')'
|
||||||
|
-> ^(BLOCK[$lp,"BLOCK"] rewrite_tree_alternative EOB[$lp,"EOB"])
|
||||||
|
;
|
||||||
|
|
||||||
|
rewrite_tree_alternative
|
||||||
|
: rewrite_tree_element+ -> ^(ALT["ALT"] rewrite_tree_element+ EOA["EOA"])
|
||||||
|
;
|
||||||
|
|
||||||
|
rewrite_tree_element
|
||||||
|
: rewrite_tree_atom
|
||||||
|
| rewrite_tree_atom ebnfSuffix
|
||||||
|
-> ^( ebnfSuffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] rewrite_tree_atom EOA["EOA"]) EOB["EOB"]))
|
||||||
|
| rewrite_tree
|
||||||
|
( ebnfSuffix
|
||||||
|
-> ^(ebnfSuffix ^(BLOCK["BLOCK"] ^(ALT["ALT"] rewrite_tree EOA["EOA"]) EOB["EOB"]))
|
||||||
|
| -> rewrite_tree
|
||||||
|
)
|
||||||
|
| rewrite_tree_ebnf
|
||||||
|
;
|
||||||
|
|
||||||
|
rewrite_tree_atom
|
||||||
|
: CHAR_LITERAL
|
||||||
|
| TOKEN_REF ARG_ACTION? -> ^(TOKEN_REF ARG_ACTION?) // for imaginary nodes
|
||||||
|
| RULE_REF
|
||||||
|
| STRING_LITERAL
|
||||||
|
| d='$' id -> LABEL[$d,$id.text] // reference to a label in a rewrite rule
|
||||||
|
| ACTION
|
||||||
|
;
|
||||||
|
|
||||||
|
rewrite_tree_ebnf
|
||||||
|
@init {
|
||||||
|
Token firstToken = input.LT(1);
|
||||||
|
}
|
||||||
|
@after {
|
||||||
|
$rewrite_tree_ebnf.tree.getToken().setLine(firstToken.getLine());
|
||||||
|
$rewrite_tree_ebnf.tree.getToken().setCharPositionInLine(firstToken.getCharPositionInLine());
|
||||||
|
}
|
||||||
|
: rewrite_tree_block ebnfSuffix -> ^(ebnfSuffix rewrite_tree_block)
|
||||||
|
;
|
||||||
|
|
||||||
|
rewrite_tree
|
||||||
|
: '^(' rewrite_tree_atom rewrite_tree_element* ')'
|
||||||
|
-> ^(TREE_BEGIN rewrite_tree_atom rewrite_tree_element* )
|
||||||
|
;
|
||||||
|
|
||||||
|
/** Build a tree for a template rewrite:
|
||||||
|
^(TEMPLATE (ID|ACTION) ^(ARGLIST ^(ARG ID ACTION) ...) )
|
||||||
|
where ARGLIST is always there even if no args exist.
|
||||||
|
ID can be "template" keyword. If first child is ACTION then it's
|
||||||
|
an indirect template ref
|
||||||
|
|
||||||
|
-> foo(a={...}, b={...})
|
||||||
|
-> ({string-e})(a={...}, b={...}) // e evaluates to template name
|
||||||
|
-> {%{$ID.text}} // create literal template from string (done in ActionTranslator)
|
||||||
|
-> {st-expr} // st-expr evaluates to ST
|
||||||
|
*/
|
||||||
|
rewrite_template
|
||||||
|
: // -> template(a={...},...) "..." inline template
|
||||||
|
id lp='(' rewrite_template_args ')'
|
||||||
|
( str=DOUBLE_QUOTE_STRING_LITERAL | str=DOUBLE_ANGLE_STRING_LITERAL )
|
||||||
|
-> ^(TEMPLATE[$lp,"TEMPLATE"] id rewrite_template_args $str)
|
||||||
|
|
||||||
|
| // -> foo(a={...}, ...)
|
||||||
|
rewrite_template_ref
|
||||||
|
|
||||||
|
| // -> ({expr})(a={...}, ...)
|
||||||
|
rewrite_indirect_template_head
|
||||||
|
|
||||||
|
| // -> {...}
|
||||||
|
ACTION
|
||||||
|
;
|
||||||
|
|
||||||
|
/** -> foo(a={...}, ...) */
|
||||||
|
rewrite_template_ref
|
||||||
|
: id lp='(' rewrite_template_args ')'
|
||||||
|
-> ^(TEMPLATE[$lp,"TEMPLATE"] id rewrite_template_args)
|
||||||
|
;
|
||||||
|
|
||||||
|
/** -> ({expr})(a={...}, ...) */
|
||||||
|
rewrite_indirect_template_head
|
||||||
|
: lp='(' ACTION ')' '(' rewrite_template_args ')'
|
||||||
|
-> ^(TEMPLATE[$lp,"TEMPLATE"] ACTION rewrite_template_args)
|
||||||
|
;
|
||||||
|
|
||||||
|
rewrite_template_args
|
||||||
|
: rewrite_template_arg (',' rewrite_template_arg)*
|
||||||
|
-> ^(ARGLIST rewrite_template_arg+)
|
||||||
|
| -> ARGLIST
|
||||||
|
;
|
||||||
|
|
||||||
|
rewrite_template_arg
|
||||||
|
: id '=' ACTION -> ^(ARG[$id.start] id ACTION)
|
||||||
|
;
|
||||||
|
|
||||||
|
id : TOKEN_REF -> ID[$TOKEN_REF]
|
||||||
|
| RULE_REF -> ID[$RULE_REF]
|
||||||
|
;
|
||||||
|
|
||||||
|
// L E X I C A L R U L E S
|
||||||
|
|
||||||
|
SL_COMMENT
|
||||||
|
: '//'
|
||||||
|
( ' $ANTLR ' SRC // src directive
|
||||||
|
| ~('\r'|'\n')*
|
||||||
|
)
|
||||||
|
'\r'? '\n'
|
||||||
|
{$channel=HIDDEN;}
|
||||||
|
;
|
||||||
|
|
||||||
|
ML_COMMENT
|
||||||
|
: '/*' {if (input.LA(1)=='*') $type=DOC_COMMENT; else $channel=HIDDEN;} .* '*/'
|
||||||
|
;
|
||||||
|
|
||||||
|
CHAR_LITERAL
|
||||||
|
: '\'' LITERAL_CHAR '\''
|
||||||
|
;
|
||||||
|
|
||||||
|
STRING_LITERAL
|
||||||
|
: '\'' LITERAL_CHAR LITERAL_CHAR* '\''
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
LITERAL_CHAR
|
||||||
|
: ESC
|
||||||
|
| ~('\''|'\\')
|
||||||
|
;
|
||||||
|
|
||||||
|
DOUBLE_QUOTE_STRING_LITERAL
|
||||||
|
: '"' (ESC | ~('\\'|'"'))* '"'
|
||||||
|
;
|
||||||
|
|
||||||
|
DOUBLE_ANGLE_STRING_LITERAL
|
||||||
|
: '<<' .* '>>'
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
ESC : '\\'
|
||||||
|
( 'n'
|
||||||
|
| 'r'
|
||||||
|
| 't'
|
||||||
|
| 'b'
|
||||||
|
| 'f'
|
||||||
|
| '"'
|
||||||
|
| '\''
|
||||||
|
| '\\'
|
||||||
|
| '>'
|
||||||
|
| 'u' XDIGIT XDIGIT XDIGIT XDIGIT
|
||||||
|
| . // unknown, leave as it is
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
XDIGIT :
|
||||||
|
'0' .. '9'
|
||||||
|
| 'a' .. 'f'
|
||||||
|
| 'A' .. 'F'
|
||||||
|
;
|
||||||
|
|
||||||
|
INT : '0'..'9'+
|
||||||
|
;
|
||||||
|
|
||||||
|
ARG_ACTION
|
||||||
|
: NESTED_ARG_ACTION
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
NESTED_ARG_ACTION :
|
||||||
|
'['
|
||||||
|
( options {greedy=false; k=1;}
|
||||||
|
: NESTED_ARG_ACTION
|
||||||
|
| ACTION_STRING_LITERAL
|
||||||
|
| ACTION_CHAR_LITERAL
|
||||||
|
| .
|
||||||
|
)*
|
||||||
|
']'
|
||||||
|
{setText(getText().substring(1, getText().length()-1));}
|
||||||
|
;
|
||||||
|
|
||||||
|
ACTION
|
||||||
|
: NESTED_ACTION ( '?' {$type = SEMPRED;} )?
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
NESTED_ACTION :
|
||||||
|
'{'
|
||||||
|
( options {greedy=false; k=2;}
|
||||||
|
: NESTED_ACTION
|
||||||
|
| SL_COMMENT
|
||||||
|
| ML_COMMENT
|
||||||
|
| ACTION_STRING_LITERAL
|
||||||
|
| ACTION_CHAR_LITERAL
|
||||||
|
| .
|
||||||
|
)*
|
||||||
|
'}'
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
ACTION_CHAR_LITERAL
|
||||||
|
: '\'' (ACTION_ESC|~('\\'|'\'')) '\''
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
ACTION_STRING_LITERAL
|
||||||
|
: '"' (ACTION_ESC|~('\\'|'"'))* '"'
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
ACTION_ESC
|
||||||
|
: '\\\''
|
||||||
|
| '\\' '"' // ANTLR doesn't like: '\\"'
|
||||||
|
| '\\' ~('\''|'"')
|
||||||
|
;
|
||||||
|
|
||||||
|
TOKEN_REF
|
||||||
|
: 'A'..'Z' ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
|
||||||
|
;
|
||||||
|
|
||||||
|
RULE_REF
|
||||||
|
: 'a'..'z' ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
|
||||||
|
;
|
||||||
|
|
||||||
|
/** Match the start of an options section. Don't allow normal
|
||||||
|
* action processing on the {...} as it's not a action.
|
||||||
|
*/
|
||||||
|
OPTIONS
|
||||||
|
: 'options' WS_LOOP '{'
|
||||||
|
;
|
||||||
|
|
||||||
|
TOKENS
|
||||||
|
: 'tokens' WS_LOOP '{'
|
||||||
|
;
|
||||||
|
|
||||||
|
/** Reset the file and line information; useful when the grammar
|
||||||
|
* has been generated so that errors are shown relative to the
|
||||||
|
* original file like the old C preprocessor used to do.
|
||||||
|
*/
|
||||||
|
fragment
|
||||||
|
SRC : 'src' ' ' file=ACTION_STRING_LITERAL ' ' line=INT
|
||||||
|
;
|
||||||
|
|
||||||
|
WS : ( ' '
|
||||||
|
| '\t'
|
||||||
|
| '\r'? '\n'
|
||||||
|
)+
|
||||||
|
{$channel=HIDDEN;}
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
WS_LOOP
|
||||||
|
: ( WS
|
||||||
|
| SL_COMMENT
|
||||||
|
| ML_COMMENT
|
||||||
|
)*
|
||||||
|
;
|
||||||
|
|
||||||
|
|
@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon Jen-Yuan Su
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
grammar StGUnit;
|
||||||
|
|
||||||
|
options {language=Java;}
|
||||||
|
|
||||||
|
tokens {
|
||||||
|
OK = 'OK';
|
||||||
|
FAIL = 'FAIL';
|
||||||
|
DOC_COMMENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
@header {
|
||||||
|
package org.antlr.gunit.swingui.parsers;
|
||||||
|
import org.antlr.gunit.swingui.model.*;
|
||||||
|
import org.antlr.gunit.swingui.runner.*;
|
||||||
|
}
|
||||||
|
|
||||||
|
@lexer::header {package org.antlr.gunit.swingui.parsers;}
|
||||||
|
|
||||||
|
@members {
|
||||||
|
public TestSuiteAdapter adapter ;;
|
||||||
|
}
|
||||||
|
|
||||||
|
gUnitDef
|
||||||
|
: 'gunit' name=id {adapter.setGrammarName($name.text);}
|
||||||
|
('walks' id)? ';'
|
||||||
|
header? suite*
|
||||||
|
;
|
||||||
|
|
||||||
|
header
|
||||||
|
: '@header' ACTION
|
||||||
|
;
|
||||||
|
|
||||||
|
suite
|
||||||
|
: ( parserRule=RULE_REF ('walks' RULE_REF)?
|
||||||
|
{adapter.startRule($parserRule.text);}
|
||||||
|
| lexerRule=TOKEN_REF
|
||||||
|
{adapter.startRule($lexerRule.text);}
|
||||||
|
)
|
||||||
|
':'
|
||||||
|
test+
|
||||||
|
{adapter.endRule();}
|
||||||
|
;
|
||||||
|
|
||||||
|
test
|
||||||
|
: input expect
|
||||||
|
{adapter.addTestCase($input.in, $expect.out);}
|
||||||
|
;
|
||||||
|
|
||||||
|
expect returns [ITestCaseOutput out]
|
||||||
|
: OK {$out = TestSuiteAdapter.createBoolOutput(true);}
|
||||||
|
| FAIL {$out = TestSuiteAdapter.createBoolOutput(false);}
|
||||||
|
| 'returns' RETVAL {$out = TestSuiteAdapter.createReturnOutput($RETVAL.text);}
|
||||||
|
| '->' output {$out = TestSuiteAdapter.createStdOutput($output.text);}
|
||||||
|
| '->' AST {$out = TestSuiteAdapter.createAstOutput($AST.text);}
|
||||||
|
;
|
||||||
|
|
||||||
|
input returns [ITestCaseInput in]
|
||||||
|
: STRING {$in = TestSuiteAdapter.createStringInput($STRING.text);}
|
||||||
|
| ML_STRING {$in = TestSuiteAdapter.createMultiInput($ML_STRING.text);}
|
||||||
|
| fileInput {$in = TestSuiteAdapter.createFileInput($fileInput.path);}
|
||||||
|
;
|
||||||
|
|
||||||
|
output
|
||||||
|
: STRING
|
||||||
|
| ML_STRING
|
||||||
|
| ACTION
|
||||||
|
;
|
||||||
|
|
||||||
|
fileInput returns [String path]
|
||||||
|
: id {$path = $id.text;} (EXT {$path += $EXT.text;})?
|
||||||
|
;
|
||||||
|
|
||||||
|
id : TOKEN_REF
|
||||||
|
| RULE_REF
|
||||||
|
;
|
||||||
|
|
||||||
|
// L E X I C A L R U L E S
|
||||||
|
|
||||||
|
SL_COMMENT
|
||||||
|
: '//' ~('\r'|'\n')* '\r'? '\n' {$channel=HIDDEN;}
|
||||||
|
;
|
||||||
|
|
||||||
|
ML_COMMENT
|
||||||
|
: '/*' {$channel=HIDDEN;} .* '*/'
|
||||||
|
;
|
||||||
|
|
||||||
|
STRING
|
||||||
|
: '"' ( ESC | ~('\\'|'"') )* '"'
|
||||||
|
;
|
||||||
|
|
||||||
|
ML_STRING
|
||||||
|
: '<<' .* '>>'
|
||||||
|
;
|
||||||
|
|
||||||
|
TOKEN_REF
|
||||||
|
: 'A'..'Z' ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
|
||||||
|
;
|
||||||
|
|
||||||
|
RULE_REF
|
||||||
|
: 'a'..'z' ('a'..'z'|'A'..'Z'|'_'|'0'..'9')*
|
||||||
|
;
|
||||||
|
|
||||||
|
EXT : '.'('a'..'z'|'A'..'Z'|'0'..'9')+;
|
||||||
|
|
||||||
|
RETVAL : NESTED_RETVAL
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
NESTED_RETVAL :
|
||||||
|
'['
|
||||||
|
( options {greedy=false;}
|
||||||
|
: NESTED_RETVAL
|
||||||
|
| .
|
||||||
|
)*
|
||||||
|
']'
|
||||||
|
;
|
||||||
|
|
||||||
|
AST : NESTED_AST (' '? NESTED_AST)*;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
NESTED_AST :
|
||||||
|
'('
|
||||||
|
( options {greedy=false;}
|
||||||
|
: NESTED_AST
|
||||||
|
| .
|
||||||
|
)*
|
||||||
|
')'
|
||||||
|
;
|
||||||
|
|
||||||
|
ACTION
|
||||||
|
: NESTED_ACTION
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
NESTED_ACTION :
|
||||||
|
'{'
|
||||||
|
( options {greedy=false; k=3;}
|
||||||
|
: NESTED_ACTION
|
||||||
|
| STRING_LITERAL
|
||||||
|
| CHAR_LITERAL
|
||||||
|
| .
|
||||||
|
)*
|
||||||
|
'}'
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
CHAR_LITERAL
|
||||||
|
: '\'' ( ESC | ~('\''|'\\') ) '\''
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
STRING_LITERAL
|
||||||
|
: '"' ( ESC | ~('\\'|'"') )* '"'
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
ESC : '\\'
|
||||||
|
( 'n'
|
||||||
|
| 'r'
|
||||||
|
| 't'
|
||||||
|
| 'b'
|
||||||
|
| 'f'
|
||||||
|
| '"'
|
||||||
|
| '\''
|
||||||
|
| '\\'
|
||||||
|
| '>'
|
||||||
|
| 'u' XDIGIT XDIGIT XDIGIT XDIGIT
|
||||||
|
| . // unknown, leave as it is
|
||||||
|
)
|
||||||
|
;
|
||||||
|
|
||||||
|
fragment
|
||||||
|
XDIGIT :
|
||||||
|
'0' .. '9'
|
||||||
|
| 'a' .. 'f'
|
||||||
|
| 'A' .. 'F'
|
||||||
|
;
|
||||||
|
|
||||||
|
WS : ( ' '
|
||||||
|
| '\t'
|
||||||
|
| '\r'? '\n'
|
||||||
|
)+
|
||||||
|
{$channel=HIDDEN;}
|
||||||
|
;
|
@ -0,0 +1,86 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD license"]
|
||||||
|
Copyright (c) 2007 Kenny MacDermid
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
public abstract class AbstractTest implements ITestCase {
|
||||||
|
// store essential individual test result for string template
|
||||||
|
protected String header;
|
||||||
|
protected String actual;
|
||||||
|
|
||||||
|
protected boolean hasErrorMsg;
|
||||||
|
|
||||||
|
private String testedRuleName;
|
||||||
|
private int testCaseIndex;
|
||||||
|
|
||||||
|
// TODO: remove these. They're only used as part of a refactor to keep the
|
||||||
|
// code cleaner. It is a mock-instanceOf() replacement.
|
||||||
|
public abstract int getType();
|
||||||
|
public abstract String getText();
|
||||||
|
|
||||||
|
public abstract String getExpected();
|
||||||
|
// return an escaped string of the expected result
|
||||||
|
public String getExpectedResult() {
|
||||||
|
String expected = getExpected();
|
||||||
|
if ( expected!=null ) expected = JUnitCodeGen.escapeForJava(expected);
|
||||||
|
return expected;
|
||||||
|
}
|
||||||
|
public abstract String getResult(gUnitTestResult testResult);
|
||||||
|
public String getHeader() { return this.header; }
|
||||||
|
public String getActual() { return this.actual; }
|
||||||
|
// return an escaped string of the actual result
|
||||||
|
public String getActualResult() {
|
||||||
|
String actual = getActual();
|
||||||
|
// there is no need to escape the error message from ANTLR
|
||||||
|
if ( actual!=null && !hasErrorMsg ) actual = JUnitCodeGen.escapeForJava(actual);
|
||||||
|
return actual;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTestedRuleName() { return this.testedRuleName; }
|
||||||
|
public int getTestCaseIndex() { return this.testCaseIndex; }
|
||||||
|
|
||||||
|
public void setHeader(String rule, String lexicalRule, String treeRule, int numOfTest, int line, String input) {
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
buf.append("test" + numOfTest + " (");
|
||||||
|
if ( treeRule!=null ) {
|
||||||
|
buf.append(treeRule+" walks ");
|
||||||
|
}
|
||||||
|
if ( lexicalRule!=null ) {
|
||||||
|
buf.append(lexicalRule + ", line"+line+")" + " - ");
|
||||||
|
}
|
||||||
|
else buf.append(rule + ", line"+line+")" + " - ");
|
||||||
|
buf.append( "\"" );
|
||||||
|
buf.append( input );
|
||||||
|
buf.append( "\"" );
|
||||||
|
this.header = buf.toString();
|
||||||
|
}
|
||||||
|
public void setActual(String actual) { this.actual = actual; }
|
||||||
|
|
||||||
|
public void setTestedRuleName(String testedRuleName) { this.testedRuleName = testedRuleName; }
|
||||||
|
public void setTestCaseIndex(int testCaseIndex) { this.testCaseIndex = testCaseIndex; }
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD license"]
|
||||||
|
Copyright (c) 2007 Kenny MacDermid
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
public class BooleanTest extends AbstractTest {
|
||||||
|
private boolean ok;
|
||||||
|
|
||||||
|
public BooleanTest(boolean ok) {
|
||||||
|
this.ok = ok;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText() {
|
||||||
|
return (ok)? "OK" : "FAIL";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getType() {
|
||||||
|
return (ok)? gUnitParser.OK : gUnitParser.FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getResult(gUnitTestResult testResult) {
|
||||||
|
if ( testResult.isLexerTest() ) {
|
||||||
|
if ( testResult.isSuccess() ) return "OK";
|
||||||
|
else {
|
||||||
|
hasErrorMsg = true; // return error message for boolean test of lexer
|
||||||
|
return testResult.getError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return (testResult.isSuccess())? "OK" : "FAIL";
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExpected() {
|
||||||
|
return (ok)? "OK" : "FAIL";
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon, Jen-Yuan Su
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class GrammarInfo {
|
||||||
|
|
||||||
|
private String grammarName; // targeted grammar for unit test
|
||||||
|
private String treeGrammarName = null; // optional, required for testing tree grammar
|
||||||
|
private String grammarPackage = null; // optional, package parser lives in
|
||||||
|
private String testPackage = null; // optional, package of junit code
|
||||||
|
private String adaptor = null; // optional, required if using customized tree adaptor
|
||||||
|
private List<gUnitTestSuite> ruleTestSuites = new ArrayList<gUnitTestSuite>(); // testsuites for each testing rule
|
||||||
|
private StringBuffer unitTestResult = new StringBuffer();
|
||||||
|
|
||||||
|
public String getGrammarName() {
|
||||||
|
return grammarName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrammarName(String grammarName) {
|
||||||
|
this.grammarName = grammarName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTreeGrammarName() {
|
||||||
|
return treeGrammarName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTreeGrammarName(String treeGrammarName) {
|
||||||
|
this.treeGrammarName = treeGrammarName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getTestPackage() {
|
||||||
|
return testPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setTestPackage(String testPackage) {
|
||||||
|
this.testPackage = testPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getGrammarPackage() {
|
||||||
|
return grammarPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrammarPackage(String grammarPackage) {
|
||||||
|
this.grammarPackage = grammarPackage;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getAdaptor() {
|
||||||
|
return adaptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setAdaptor(String adaptor) {
|
||||||
|
this.adaptor = adaptor;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<gUnitTestSuite> getRuleTestSuites() {
|
||||||
|
// Make this list unmodifiable so that we can refactor knowing it's not changed.
|
||||||
|
return Collections.unmodifiableList(ruleTestSuites);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRuleTestSuite(gUnitTestSuite testSuite) {
|
||||||
|
this.ruleTestSuites.add(testSuite);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendUnitTestResult(String result) {
|
||||||
|
this.unitTestResult.append(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
// We don't want people messing with the string buffer here, so don't return it.
|
||||||
|
public String getUnitTestResult() {
|
||||||
|
return unitTestResult.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setUnitTestResult(StringBuffer unitTestResult) {
|
||||||
|
this.unitTestResult = unitTestResult;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD license"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ITestCase object locates one test case in a gUnit script by specifying the
|
||||||
|
* tested rule and the index number of the test case in that group.
|
||||||
|
*
|
||||||
|
* For example:
|
||||||
|
* ----------------------
|
||||||
|
* ...
|
||||||
|
* varDef:
|
||||||
|
* "int i;" OK
|
||||||
|
* "float 2f;" FAIL
|
||||||
|
* ...
|
||||||
|
* ----------------------
|
||||||
|
* The "testedRuleName" for these two test cases will be "varDef".
|
||||||
|
* The "index" for the "int"-test will be 0.
|
||||||
|
* The "index" for the "float"-test will be 1. And so on.
|
||||||
|
*
|
||||||
|
* @see ITestSuite
|
||||||
|
*/
|
||||||
|
public interface ITestCase {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the name of the rule that is tested by this test case.
|
||||||
|
* @return name of the tested rule.
|
||||||
|
*/
|
||||||
|
public String getTestedRuleName();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the index of the test case in the test group for a rule. Starting
|
||||||
|
* from 0.
|
||||||
|
* @return index number of the test case.
|
||||||
|
*/
|
||||||
|
public int getTestCaseIndex();
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,45 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD license"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A gUnit script file is an Antlr "test suite". The interface is defined to
|
||||||
|
* allow the Swing GUI test runner be notified when gUnit interpreter runner
|
||||||
|
* runs a passed/failed test case.
|
||||||
|
*
|
||||||
|
* CHANGES:
|
||||||
|
* 2009-03-01: SHAOTING
|
||||||
|
* - change method return void, parameter test object.
|
||||||
|
*/
|
||||||
|
public interface ITestSuite {
|
||||||
|
|
||||||
|
public void onPass(ITestCase passTest);
|
||||||
|
|
||||||
|
public void onFail(ITestCase failTest);
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,113 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon Jen-Yuan Su
|
||||||
|
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.gunit;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.antlr.runtime.*;
|
||||||
|
|
||||||
|
/** The main gUnit interpreter entry point.
|
||||||
|
* Read a gUnit script, run unit tests or generate a junit file.
|
||||||
|
*/
|
||||||
|
public class Interp {
|
||||||
|
static String testPackage;
|
||||||
|
static boolean genJUnit;
|
||||||
|
static String gunitFile;
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException, ClassNotFoundException, RecognitionException {
|
||||||
|
/** Pull char from where? */
|
||||||
|
CharStream input = null;
|
||||||
|
/** If the input source is a testsuite file, where is it? */
|
||||||
|
String testsuiteDir = System.getProperty("user.dir");
|
||||||
|
|
||||||
|
processArgs(args);
|
||||||
|
|
||||||
|
if ( genJUnit ) {
|
||||||
|
if ( gunitFile!=null ) {
|
||||||
|
input = new ANTLRFileStream(gunitFile);
|
||||||
|
File f = new File(gunitFile);
|
||||||
|
testsuiteDir = getTestsuiteDir(f.getCanonicalPath(), f.getName());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
input = new ANTLRInputStream(System.in);
|
||||||
|
}
|
||||||
|
GrammarInfo grammarInfo = parse(input);
|
||||||
|
grammarInfo.setTestPackage(testPackage);
|
||||||
|
JUnitCodeGen generater = new JUnitCodeGen(grammarInfo, testsuiteDir);
|
||||||
|
generater.compile();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( gunitFile!=null ) {
|
||||||
|
input = new ANTLRFileStream(gunitFile);
|
||||||
|
File f = new File(gunitFile);
|
||||||
|
testsuiteDir = getTestsuiteDir(f.getCanonicalPath(), f.getName());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
input = new ANTLRInputStream(System.in);
|
||||||
|
|
||||||
|
gUnitExecutor executer = new gUnitExecutor(parse(input), testsuiteDir);
|
||||||
|
|
||||||
|
System.out.print(executer.execTest()); // unit test result
|
||||||
|
|
||||||
|
//return an error code of the number of failures
|
||||||
|
System.exit(executer.failures.size() + executer.invalids.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void processArgs(String[] args) {
|
||||||
|
if (args == null || args.length == 0) return;
|
||||||
|
for (int i = 0; i < args.length; i++) {
|
||||||
|
if (args[i].equals("-p")) {
|
||||||
|
if (i + 1 >= args.length) {
|
||||||
|
System.err.println("missing library directory with -lib option; ignoring");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
i++;
|
||||||
|
testPackage = args[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (args[i].equals("-o")) genJUnit = true;
|
||||||
|
else gunitFile = args[i]; // Must be the gunit file
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static GrammarInfo parse(CharStream input) throws RecognitionException {
|
||||||
|
gUnitLexer lexer = new gUnitLexer(input);
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
|
||||||
|
GrammarInfo grammarInfo = new GrammarInfo();
|
||||||
|
gUnitParser parser = new gUnitParser(tokens, grammarInfo);
|
||||||
|
parser.gUnitDef(); // parse gunit script and save elements to grammarInfo
|
||||||
|
return grammarInfo;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String getTestsuiteDir(String fullPath, String fileName) {
|
||||||
|
return fullPath.substring(0, fullPath.length()-fileName.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD license"]
|
||||||
|
Copyright (c) 2007 Kenny MacDermid
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
public class InvalidInputException extends Exception {
|
||||||
|
|
||||||
|
private static final long serialVersionUID = 1L;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,407 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon Jen-Yuan Su
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
import org.antlr.stringtemplate.StringTemplate;
|
||||||
|
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||||
|
import org.antlr.stringtemplate.StringTemplateGroupLoader;
|
||||||
|
import org.antlr.stringtemplate.CommonGroupLoader;
|
||||||
|
import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.logging.ConsoleHandler;
|
||||||
|
import java.util.logging.Handler;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
|
public class JUnitCodeGen {
|
||||||
|
public GrammarInfo grammarInfo;
|
||||||
|
public Map<String, String> ruleWithReturn;
|
||||||
|
private final String testsuiteDir;
|
||||||
|
private String outputDirectoryPath = ".";
|
||||||
|
|
||||||
|
private final static Handler console = new ConsoleHandler();
|
||||||
|
private static final Logger logger = Logger.getLogger(JUnitCodeGen.class.getName());
|
||||||
|
static {
|
||||||
|
logger.addHandler(console);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JUnitCodeGen(GrammarInfo grammarInfo, String testsuiteDir) throws ClassNotFoundException {
|
||||||
|
this( grammarInfo, determineClassLoader(), testsuiteDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ClassLoader determineClassLoader() {
|
||||||
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
if ( classLoader == null ) {
|
||||||
|
classLoader = JUnitCodeGen.class.getClassLoader();
|
||||||
|
}
|
||||||
|
return classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public JUnitCodeGen(GrammarInfo grammarInfo, ClassLoader classLoader, String testsuiteDir) throws ClassNotFoundException {
|
||||||
|
this.grammarInfo = grammarInfo;
|
||||||
|
this.testsuiteDir = testsuiteDir;
|
||||||
|
/** Map the name of rules having return value to its return type */
|
||||||
|
ruleWithReturn = new HashMap<String, String>();
|
||||||
|
Class<?> parserClass = locateParserClass( grammarInfo, classLoader );
|
||||||
|
Method[] methods = parserClass.getDeclaredMethods();
|
||||||
|
for(Method method : methods) {
|
||||||
|
if ( !method.getReturnType().getName().equals("void") ) {
|
||||||
|
ruleWithReturn.put(method.getName(), method.getReturnType().getName().replace('$', '.'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Class<?> locateParserClass(GrammarInfo grammarInfo, ClassLoader classLoader) throws ClassNotFoundException {
|
||||||
|
String parserClassName = grammarInfo.getGrammarName() + "Parser";
|
||||||
|
if ( grammarInfo.getGrammarPackage() != null ) {
|
||||||
|
parserClassName = grammarInfo.getGrammarPackage()+ "." + parserClassName;
|
||||||
|
}
|
||||||
|
return classLoader.loadClass( parserClassName );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOutputDirectoryPath() {
|
||||||
|
return outputDirectoryPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutputDirectoryPath(String outputDirectoryPath) {
|
||||||
|
this.outputDirectoryPath = outputDirectoryPath;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void compile() throws IOException{
|
||||||
|
String junitFileName;
|
||||||
|
if ( grammarInfo.getTreeGrammarName()!=null ) {
|
||||||
|
junitFileName = "Test"+grammarInfo.getTreeGrammarName();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
junitFileName = "Test"+grammarInfo.getGrammarName();
|
||||||
|
}
|
||||||
|
String lexerName = grammarInfo.getGrammarName()+"Lexer";
|
||||||
|
String parserName = grammarInfo.getGrammarName()+"Parser";
|
||||||
|
|
||||||
|
StringTemplateGroupLoader loader = new CommonGroupLoader("org/antlr/gunit", null);
|
||||||
|
StringTemplateGroup.registerGroupLoader(loader);
|
||||||
|
StringTemplateGroup.registerDefaultLexer(AngleBracketTemplateLexer.class);
|
||||||
|
StringBuffer buf = compileToBuffer(junitFileName, lexerName, parserName);
|
||||||
|
writeTestFile(".", junitFileName+".java", buf.toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
public StringBuffer compileToBuffer(String className, String lexerName, String parserName) {
|
||||||
|
StringTemplateGroup group = StringTemplateGroup.loadGroup("junit");
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
buf.append(genClassHeader(group, className, lexerName, parserName));
|
||||||
|
buf.append(genTestRuleMethods(group));
|
||||||
|
buf.append("\n\n}");
|
||||||
|
return buf;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String genClassHeader(StringTemplateGroup group, String junitFileName, String lexerName, String parserName) {
|
||||||
|
StringTemplate classHeaderST = group.getInstanceOf("classHeader");
|
||||||
|
if ( grammarInfo.getTestPackage()!=null ) { // Set up class package if there is
|
||||||
|
classHeaderST.setAttribute("header", "package "+grammarInfo.getTestPackage()+";");
|
||||||
|
}
|
||||||
|
classHeaderST.setAttribute("junitFileName", junitFileName);
|
||||||
|
|
||||||
|
String lexerPath = null;
|
||||||
|
String parserPath = null;
|
||||||
|
String treeParserPath = null;
|
||||||
|
String packagePath = null;
|
||||||
|
boolean isTreeGrammar = false;
|
||||||
|
boolean hasPackage = false;
|
||||||
|
/** Set up appropriate class path for parser/tree parser if using package */
|
||||||
|
if ( grammarInfo.getGrammarPackage()!=null ) {
|
||||||
|
hasPackage = true;
|
||||||
|
packagePath = "./"+grammarInfo.getGrammarPackage().replace('.', '/');
|
||||||
|
lexerPath = grammarInfo.getGrammarPackage()+"."+lexerName;
|
||||||
|
parserPath = grammarInfo.getGrammarPackage()+"."+parserName;
|
||||||
|
if ( grammarInfo.getTreeGrammarName()!=null ) {
|
||||||
|
treeParserPath = grammarInfo.getGrammarPackage()+"."+grammarInfo.getTreeGrammarName();
|
||||||
|
isTreeGrammar = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
lexerPath = lexerName;
|
||||||
|
parserPath = parserName;
|
||||||
|
if ( grammarInfo.getTreeGrammarName()!=null ) {
|
||||||
|
treeParserPath = grammarInfo.getTreeGrammarName();
|
||||||
|
isTreeGrammar = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// also set up custom tree adaptor if necessary
|
||||||
|
String treeAdaptorPath = null;
|
||||||
|
boolean hasTreeAdaptor = false;
|
||||||
|
if ( grammarInfo.getAdaptor()!=null ) {
|
||||||
|
hasTreeAdaptor = true;
|
||||||
|
treeAdaptorPath = grammarInfo.getAdaptor();
|
||||||
|
}
|
||||||
|
classHeaderST.setAttribute("hasTreeAdaptor", hasTreeAdaptor);
|
||||||
|
classHeaderST.setAttribute("treeAdaptorPath", treeAdaptorPath);
|
||||||
|
classHeaderST.setAttribute("hasPackage", hasPackage);
|
||||||
|
classHeaderST.setAttribute("packagePath", packagePath);
|
||||||
|
classHeaderST.setAttribute("lexerPath", lexerPath);
|
||||||
|
classHeaderST.setAttribute("parserPath", parserPath);
|
||||||
|
classHeaderST.setAttribute("treeParserPath", treeParserPath);
|
||||||
|
classHeaderST.setAttribute("isTreeGrammar", isTreeGrammar);
|
||||||
|
return classHeaderST.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String genTestRuleMethods(StringTemplateGroup group) {
|
||||||
|
StringBuffer buf = new StringBuffer();
|
||||||
|
if ( grammarInfo.getTreeGrammarName()!=null ) { // Generate junit codes of for tree grammar rule
|
||||||
|
genTreeMethods(group, buf);
|
||||||
|
}
|
||||||
|
else { // Generate junit codes of for grammar rule
|
||||||
|
genParserMethods(group, buf);
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void genParserMethods(StringTemplateGroup group, StringBuffer buf) {
|
||||||
|
for ( gUnitTestSuite ts: grammarInfo.getRuleTestSuites() ) {
|
||||||
|
int i = 0;
|
||||||
|
for ( Map.Entry<gUnitTestInput, AbstractTest> entry : ts.testSuites.entrySet() ) { // each rule may contain multiple tests
|
||||||
|
gUnitTestInput input = entry.getKey();
|
||||||
|
i++;
|
||||||
|
StringTemplate testRuleMethodST;
|
||||||
|
/** If rule has multiple return values or ast*/
|
||||||
|
if ( entry.getValue().getType()== gUnitParser.ACTION && ruleWithReturn.containsKey(ts.getRuleName()) ) {
|
||||||
|
testRuleMethodST = group.getInstanceOf("testRuleMethod2");
|
||||||
|
String outputString = entry.getValue().getText();
|
||||||
|
testRuleMethodST.setAttribute("methodName", "test"+changeFirstCapital(ts.getRuleName())+i);
|
||||||
|
testRuleMethodST.setAttribute("testRuleName", '"'+ts.getRuleName()+'"');
|
||||||
|
testRuleMethodST.setAttribute("test", input);
|
||||||
|
testRuleMethodST.setAttribute("returnType", ruleWithReturn.get(ts.getRuleName()));
|
||||||
|
testRuleMethodST.setAttribute("expecting", outputString);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
String testRuleName;
|
||||||
|
// need to determine whether it's a test for parser rule or lexer rule
|
||||||
|
if ( ts.isLexicalRule() ) testRuleName = ts.getLexicalRuleName();
|
||||||
|
else testRuleName = ts.getRuleName();
|
||||||
|
testRuleMethodST = group.getInstanceOf("testRuleMethod");
|
||||||
|
String outputString = entry.getValue().getText();
|
||||||
|
testRuleMethodST.setAttribute("isLexicalRule", ts.isLexicalRule());
|
||||||
|
testRuleMethodST.setAttribute("methodName", "test"+changeFirstCapital(testRuleName)+i);
|
||||||
|
testRuleMethodST.setAttribute("testRuleName", '"'+testRuleName+'"');
|
||||||
|
testRuleMethodST.setAttribute("test", input);
|
||||||
|
testRuleMethodST.setAttribute("tokenType", getTypeString(entry.getValue().getType()));
|
||||||
|
|
||||||
|
// normalize whitespace
|
||||||
|
outputString = normalizeTreeSpec(outputString);
|
||||||
|
|
||||||
|
if ( entry.getValue().getType()==gUnitParser.ACTION ) { // trim ';' at the end of ACTION if there is...
|
||||||
|
//testRuleMethodST.setAttribute("expecting", outputString.substring(0, outputString.length()-1));
|
||||||
|
testRuleMethodST.setAttribute("expecting", outputString);
|
||||||
|
}
|
||||||
|
else if ( entry.getValue().getType()==gUnitParser.RETVAL ) { // Expected: RETVAL
|
||||||
|
testRuleMethodST.setAttribute("expecting", outputString);
|
||||||
|
}
|
||||||
|
else { // Attach "" to expected STRING or AST
|
||||||
|
// strip newlines for (...) tree stuff
|
||||||
|
outputString = outputString.replaceAll("\n", "");
|
||||||
|
testRuleMethodST.setAttribute("expecting", '"'+escapeForJava(outputString)+'"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.append(testRuleMethodST.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void genTreeMethods(StringTemplateGroup group, StringBuffer buf) {
|
||||||
|
for ( gUnitTestSuite ts: grammarInfo.getRuleTestSuites() ) {
|
||||||
|
int i = 0;
|
||||||
|
for ( Map.Entry<gUnitTestInput, AbstractTest> entry : ts.testSuites.entrySet() ) { // each rule may contain multiple tests
|
||||||
|
gUnitTestInput input = entry.getKey();
|
||||||
|
i++;
|
||||||
|
StringTemplate testRuleMethodST;
|
||||||
|
/** If rule has multiple return values or ast*/
|
||||||
|
if ( entry.getValue().getType()== gUnitParser.ACTION && ruleWithReturn.containsKey(ts.getTreeRuleName()) ) {
|
||||||
|
testRuleMethodST = group.getInstanceOf("testTreeRuleMethod2");
|
||||||
|
String outputString = entry.getValue().getText();
|
||||||
|
testRuleMethodST.setAttribute("methodName", "test"+changeFirstCapital(ts.getTreeRuleName())+"_walks_"+
|
||||||
|
changeFirstCapital(ts.getRuleName())+i);
|
||||||
|
testRuleMethodST.setAttribute("testTreeRuleName", '"'+ts.getTreeRuleName()+'"');
|
||||||
|
testRuleMethodST.setAttribute("testRuleName", '"'+ts.getRuleName()+'"');
|
||||||
|
testRuleMethodST.setAttribute("test", input);
|
||||||
|
testRuleMethodST.setAttribute("returnType", ruleWithReturn.get(ts.getTreeRuleName()));
|
||||||
|
testRuleMethodST.setAttribute("expecting", outputString);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
testRuleMethodST = group.getInstanceOf("testTreeRuleMethod");
|
||||||
|
String outputString = entry.getValue().getText();
|
||||||
|
testRuleMethodST.setAttribute("methodName", "test"+changeFirstCapital(ts.getTreeRuleName())+"_walks_"+
|
||||||
|
changeFirstCapital(ts.getRuleName())+i);
|
||||||
|
testRuleMethodST.setAttribute("testTreeRuleName", '"'+ts.getTreeRuleName()+'"');
|
||||||
|
testRuleMethodST.setAttribute("testRuleName", '"'+ts.getRuleName()+'"');
|
||||||
|
testRuleMethodST.setAttribute("test", input);
|
||||||
|
testRuleMethodST.setAttribute("tokenType", getTypeString(entry.getValue().getType()));
|
||||||
|
|
||||||
|
if ( entry.getValue().getType()==gUnitParser.ACTION ) { // trim ';' at the end of ACTION if there is...
|
||||||
|
//testRuleMethodST.setAttribute("expecting", outputString.substring(0, outputString.length()-1));
|
||||||
|
testRuleMethodST.setAttribute("expecting", outputString);
|
||||||
|
}
|
||||||
|
else if ( entry.getValue().getType()==gUnitParser.RETVAL ) { // Expected: RETVAL
|
||||||
|
testRuleMethodST.setAttribute("expecting", outputString);
|
||||||
|
}
|
||||||
|
else { // Attach "" to expected STRING or AST
|
||||||
|
testRuleMethodST.setAttribute("expecting", '"'+escapeForJava(outputString)+'"');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
buf.append(testRuleMethodST.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// return a meaningful gUnit token type name instead of using the magic number
|
||||||
|
public String getTypeString(int type) {
|
||||||
|
String typeText;
|
||||||
|
switch (type) {
|
||||||
|
case gUnitParser.OK :
|
||||||
|
typeText = "org.antlr.gunit.gUnitParser.OK";
|
||||||
|
break;
|
||||||
|
case gUnitParser.FAIL :
|
||||||
|
typeText = "org.antlr.gunit.gUnitParser.FAIL";
|
||||||
|
break;
|
||||||
|
case gUnitParser.STRING :
|
||||||
|
typeText = "org.antlr.gunit.gUnitParser.STRING";
|
||||||
|
break;
|
||||||
|
case gUnitParser.ML_STRING :
|
||||||
|
typeText = "org.antlr.gunit.gUnitParser.ML_STRING";
|
||||||
|
break;
|
||||||
|
case gUnitParser.RETVAL :
|
||||||
|
typeText = "org.antlr.gunit.gUnitParser.RETVAL";
|
||||||
|
break;
|
||||||
|
case gUnitParser.AST :
|
||||||
|
typeText = "org.antlr.gunit.gUnitParser.AST";
|
||||||
|
break;
|
||||||
|
default :
|
||||||
|
typeText = "org.antlr.gunit.gUnitParser.EOF";
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return typeText;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void writeTestFile(String dir, String fileName, String content) {
|
||||||
|
try {
|
||||||
|
File f = new File(dir, fileName);
|
||||||
|
FileWriter w = new FileWriter(f);
|
||||||
|
BufferedWriter bw = new BufferedWriter(w);
|
||||||
|
bw.write(content);
|
||||||
|
bw.close();
|
||||||
|
w.close();
|
||||||
|
}
|
||||||
|
catch (IOException ioe) {
|
||||||
|
logger.log(Level.SEVERE, "can't write file", ioe);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String escapeForJava(String inputString) {
|
||||||
|
// Gotta escape literal backslash before putting in specials that use escape.
|
||||||
|
inputString = inputString.replace("\\", "\\\\");
|
||||||
|
// Then double quotes need escaping (singles are OK of course).
|
||||||
|
inputString = inputString.replace("\"", "\\\"");
|
||||||
|
// note: replace newline to String ".\n", replace tab to String ".\t"
|
||||||
|
inputString = inputString.replace("\n", "\\n").replace("\t", "\\t").replace("\r", "\\r").replace("\b", "\\b").replace("\f", "\\f");
|
||||||
|
|
||||||
|
return inputString;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected String changeFirstCapital(String ruleName) {
|
||||||
|
String firstChar = String.valueOf(ruleName.charAt(0));
|
||||||
|
return firstChar.toUpperCase()+ruleName.substring(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String normalizeTreeSpec(String t) {
|
||||||
|
List<String> words = new ArrayList<String>();
|
||||||
|
int i = 0;
|
||||||
|
StringBuilder word = new StringBuilder();
|
||||||
|
while ( i<t.length() ) {
|
||||||
|
if ( t.charAt(i)=='(' || t.charAt(i)==')' ) {
|
||||||
|
if ( word.length()>0 ) {
|
||||||
|
words.add(word.toString());
|
||||||
|
word.setLength(0);
|
||||||
|
}
|
||||||
|
words.add(String.valueOf(t.charAt(i)));
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if ( Character.isWhitespace(t.charAt(i)) ) {
|
||||||
|
// upon WS, save word
|
||||||
|
if ( word.length()>0 ) {
|
||||||
|
words.add(word.toString());
|
||||||
|
word.setLength(0);
|
||||||
|
}
|
||||||
|
i++;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ... "x" or ...("x"
|
||||||
|
if ( t.charAt(i)=='"' && (i-1)>=0 &&
|
||||||
|
(t.charAt(i-1)=='(' || Character.isWhitespace(t.charAt(i-1))) )
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
while ( i<t.length() && t.charAt(i)!='"' ) {
|
||||||
|
if ( t.charAt(i)=='\\' &&
|
||||||
|
(i+1)<t.length() && t.charAt(i+1)=='"' ) // handle \"
|
||||||
|
{
|
||||||
|
word.append('"');
|
||||||
|
i+=2;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
word.append(t.charAt(i));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
i++; // skip final "
|
||||||
|
words.add(word.toString());
|
||||||
|
word.setLength(0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
word.append(t.charAt(i));
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
if ( word.length()>0 ) {
|
||||||
|
words.add(word.toString());
|
||||||
|
}
|
||||||
|
//System.out.println("words="+words);
|
||||||
|
StringBuilder buf = new StringBuilder();
|
||||||
|
for (int j=0; j<words.size(); j++) {
|
||||||
|
if ( j>0 && !words.get(j).equals(")") &&
|
||||||
|
!words.get(j-1).equals("(") ) {
|
||||||
|
buf.append(' ');
|
||||||
|
}
|
||||||
|
buf.append(words.get(j));
|
||||||
|
}
|
||||||
|
return buf.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,67 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD license"]
|
||||||
|
Copyright (c) 2007 Kenny MacDermid
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
|
/** OutputTest represents a test for not only standard output string,
|
||||||
|
* but also AST output which is actually a return value from a parser.
|
||||||
|
*/
|
||||||
|
public class OutputTest extends AbstractTest {
|
||||||
|
private final Token token;
|
||||||
|
|
||||||
|
public OutputTest(Token token) {
|
||||||
|
this.token = token;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText() {
|
||||||
|
return token.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getType() {
|
||||||
|
return token.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// return ANTLR error msg if test failed
|
||||||
|
public String getResult(gUnitTestResult testResult) {
|
||||||
|
// Note: we treat the standard output string as a return value also
|
||||||
|
if ( testResult.isSuccess() ) return testResult.getReturned();
|
||||||
|
else {
|
||||||
|
hasErrorMsg = true;
|
||||||
|
return testResult.getError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExpected() {
|
||||||
|
return token.getText();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD license"]
|
||||||
|
Copyright (c) 2007 Kenny MacDermid
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
import org.antlr.runtime.Token;
|
||||||
|
|
||||||
|
public class ReturnTest extends AbstractTest {
|
||||||
|
private final Token retval;
|
||||||
|
|
||||||
|
public ReturnTest(Token retval) {
|
||||||
|
this.retval = retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getText() {
|
||||||
|
return retval.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getType() {
|
||||||
|
return retval.getType();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
// return ANTLR error msg if test failed
|
||||||
|
public String getResult(gUnitTestResult testResult) {
|
||||||
|
if ( testResult.isSuccess() ) return testResult.getReturned();
|
||||||
|
else {
|
||||||
|
hasErrorMsg = true;
|
||||||
|
return testResult.getError();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getExpected() {
|
||||||
|
String expect = retval.getText();
|
||||||
|
|
||||||
|
if ( expect.charAt(0)=='"' && expect.charAt(expect.length()-1)=='"' ) {
|
||||||
|
expect = expect.substring(1, expect.length()-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
return expect;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,475 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon, Jen-Yuan Su
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
import org.antlr.runtime.*;
|
||||||
|
import org.antlr.runtime.tree.*;
|
||||||
|
import org.antlr.stringtemplate.StringTemplate;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.lang.reflect.*;
|
||||||
|
|
||||||
|
/** All gUnit-generated JUnit class should extend this class
|
||||||
|
* which implements the essential methods for triggering
|
||||||
|
* ANTLR parser/tree walker
|
||||||
|
*/
|
||||||
|
public abstract class gUnitBaseTest extends TestCase {
|
||||||
|
|
||||||
|
public String treeAdaptorPath;
|
||||||
|
public String packagePath;
|
||||||
|
public String lexerPath;
|
||||||
|
public String parserPath;
|
||||||
|
public String treeParserPath;
|
||||||
|
|
||||||
|
protected String stdout;
|
||||||
|
protected String stderr;
|
||||||
|
|
||||||
|
private PrintStream console = System.out;
|
||||||
|
private PrintStream consoleErr = System.err;
|
||||||
|
|
||||||
|
// Invoke target lexer.rule
|
||||||
|
public String execLexer(String testRuleName, int line, String testInput, boolean isFile) throws Exception {
|
||||||
|
CharStream input;
|
||||||
|
/** Set up ANTLR input stream based on input source, file or String */
|
||||||
|
if ( isFile ) {
|
||||||
|
String filePath = testInput;
|
||||||
|
File testInputFile = new File(filePath);
|
||||||
|
// if input test file is not found under the current dir, also try to look for it under the package dir
|
||||||
|
if ( !testInputFile.exists() && packagePath!=null ) {
|
||||||
|
testInputFile = new File(packagePath, filePath);
|
||||||
|
if ( testInputFile.exists() ) filePath = testInputFile.getCanonicalPath();
|
||||||
|
}
|
||||||
|
input = new ANTLRFileStream(filePath);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
input = new ANTLRStringStream(testInput);
|
||||||
|
}
|
||||||
|
Class<? extends Lexer> lexer;
|
||||||
|
PrintStream ps = null; // for redirecting stdout later
|
||||||
|
PrintStream ps2 = null; // for redirecting stderr later
|
||||||
|
try {
|
||||||
|
/** Use Reflection to create instances of lexer and parser */
|
||||||
|
lexer = Class.forName(lexerPath).asSubclass(Lexer.class);
|
||||||
|
Constructor<? extends Lexer> lexConstructor = lexer.getConstructor(CharStream.class);
|
||||||
|
Lexer lexObj = lexConstructor.newInstance(input); // makes new instance of lexer
|
||||||
|
input.setLine(line);
|
||||||
|
|
||||||
|
Method ruleName = lexer.getMethod("m"+testRuleName);
|
||||||
|
|
||||||
|
/** Start of I/O Redirecting */
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ByteArrayOutputStream err = new ByteArrayOutputStream();
|
||||||
|
ps = new PrintStream(out);
|
||||||
|
ps2 = new PrintStream(err);
|
||||||
|
System.setOut(ps);
|
||||||
|
System.setErr(ps2);
|
||||||
|
/** End of redirecting */
|
||||||
|
|
||||||
|
/** Invoke lexer rule, and get the current index in CharStream */
|
||||||
|
ruleName.invoke(lexObj, new Object[0]);
|
||||||
|
Method ruleName2 = lexer.getMethod("getCharIndex");
|
||||||
|
int currentIndex = (Integer) ruleName2.invoke(lexObj, new Object[0]);
|
||||||
|
if ( currentIndex!=input.size() ) {
|
||||||
|
ps2.println("extra text found, '"+input.substring(currentIndex, input.size()-1)+"'");
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stdout = null;
|
||||||
|
this.stderr = null;
|
||||||
|
|
||||||
|
if ( err.toString().length()>0 ) {
|
||||||
|
this.stderr = err.toString();
|
||||||
|
return this.stderr;
|
||||||
|
}
|
||||||
|
if ( out.toString().length()>0 ) {
|
||||||
|
this.stdout = out.toString();
|
||||||
|
}
|
||||||
|
if ( err.toString().length()==0 && out.toString().length()==0 ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
} catch (InvocationTargetException e) { // This exception could be caused from ANTLR Runtime Exception, e.g. MismatchedTokenException
|
||||||
|
if ( e.getCause()!=null ) this.stderr = e.getCause().toString();
|
||||||
|
else this.stderr = e.toString();
|
||||||
|
return this.stderr;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if ( ps!=null ) ps.close();
|
||||||
|
if ( ps2!=null ) ps2.close();
|
||||||
|
System.setOut(console); // Reset standard output
|
||||||
|
System.setErr(consoleErr); // Reset standard err out
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke target parser.rule
|
||||||
|
|
||||||
|
public Object execParser(String testRuleName, int line, String testInput, boolean isFile) throws Exception {
|
||||||
|
CharStream input;
|
||||||
|
/** Set up ANTLR input stream based on input source, file or String */
|
||||||
|
if ( isFile ) {
|
||||||
|
String filePath = testInput;
|
||||||
|
File testInputFile = new File(filePath);
|
||||||
|
// if input test file is not found under the current dir, also try to look for it under the package dir
|
||||||
|
if ( !testInputFile.exists() && packagePath!=null ) {
|
||||||
|
testInputFile = new File(packagePath, filePath);
|
||||||
|
if ( testInputFile.exists() ) filePath = testInputFile.getCanonicalPath();
|
||||||
|
}
|
||||||
|
input = new ANTLRFileStream(filePath);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
input = new ANTLRStringStream(testInput);
|
||||||
|
}
|
||||||
|
Class<? extends Lexer> lexer;
|
||||||
|
Class<? extends Parser> parser;
|
||||||
|
PrintStream ps = null; // for redirecting stdout later
|
||||||
|
PrintStream ps2 = null; // for redirecting stderr later
|
||||||
|
ByteArrayOutputStream out = null;
|
||||||
|
ByteArrayOutputStream err = null;
|
||||||
|
try {
|
||||||
|
/** Use Reflection to create instances of lexer and parser */
|
||||||
|
lexer = Class.forName(lexerPath).asSubclass(Lexer.class);
|
||||||
|
Constructor<? extends Lexer> lexConstructor = lexer.getConstructor(CharStream.class);
|
||||||
|
Lexer lexObj = lexConstructor.newInstance(input); // makes new instance of lexer
|
||||||
|
input.setLine(line);
|
||||||
|
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexObj);
|
||||||
|
parser = Class.forName(parserPath).asSubclass(Parser.class);
|
||||||
|
Constructor<? extends Parser> parConstructor = parser.getConstructor(TokenStream.class);
|
||||||
|
Parser parObj = parConstructor.newInstance(tokens); // makes new instance of parser
|
||||||
|
|
||||||
|
// set up customized tree adaptor if necessary
|
||||||
|
if ( treeAdaptorPath!=null ) {
|
||||||
|
Method _setTreeAdaptor = parser.getMethod("setTreeAdaptor", TreeAdaptor.class);
|
||||||
|
Class<? extends TreeAdaptor> _treeAdaptor = Class.forName(treeAdaptorPath).asSubclass(TreeAdaptor.class);
|
||||||
|
_setTreeAdaptor.invoke(parObj, _treeAdaptor.newInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
Method ruleName = parser.getMethod(testRuleName);
|
||||||
|
|
||||||
|
/** Start of I/O Redirecting */
|
||||||
|
out = new ByteArrayOutputStream();
|
||||||
|
err = new ByteArrayOutputStream();
|
||||||
|
ps = new PrintStream(out);
|
||||||
|
ps2 = new PrintStream(err);
|
||||||
|
System.setOut(ps);
|
||||||
|
System.setErr(ps2);
|
||||||
|
/** End of redirecting */
|
||||||
|
|
||||||
|
/** Invoke grammar rule, and store if there is a return value */
|
||||||
|
Object ruleReturn = ruleName.invoke(parObj);
|
||||||
|
String astString = null;
|
||||||
|
String stString = null;
|
||||||
|
/** If rule has return value, determine if it contains an AST or a ST */
|
||||||
|
if ( ruleReturn!=null ) {
|
||||||
|
if ( ruleReturn.getClass().toString().indexOf(testRuleName+"_return")>0 ) {
|
||||||
|
try { // NullPointerException may happen here...
|
||||||
|
Class<?> _return = Class.forName(parserPath+"$"+testRuleName+"_return");
|
||||||
|
Method[] methods = _return.getDeclaredMethods();
|
||||||
|
for(Method method : methods) {
|
||||||
|
if ( method.getName().equals("getTree") ) {
|
||||||
|
Method returnName = _return.getMethod("getTree");
|
||||||
|
CommonTree tree = (CommonTree) returnName.invoke(ruleReturn);
|
||||||
|
astString = tree.toStringTree();
|
||||||
|
}
|
||||||
|
else if ( method.getName().equals("getTemplate") ) {
|
||||||
|
Method returnName = _return.getMethod("getTemplate");
|
||||||
|
StringTemplate st = (StringTemplate) returnName.invoke(ruleReturn);
|
||||||
|
stString = st.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
System.err.println(e); // Note: If any exception occurs, the test is viewed as failed.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stdout = "";
|
||||||
|
this.stderr = "";
|
||||||
|
|
||||||
|
/** Invalid input */
|
||||||
|
if ( tokens.index()!=tokens.size()-1 ) {
|
||||||
|
//throw new InvalidInputException();
|
||||||
|
this.stderr += "Stopped parsing at token index "+tokens.index()+": ";
|
||||||
|
}
|
||||||
|
|
||||||
|
// retVal could be actual return object from rule, stderr or stdout
|
||||||
|
this.stdout += out.toString();
|
||||||
|
this.stderr += err.toString();
|
||||||
|
|
||||||
|
if ( err.toString().length()>0 ) return this.stderr;
|
||||||
|
if ( out.toString().length()>0 ) return this.stdout;
|
||||||
|
if ( astString!=null ) { // Return toStringTree of AST
|
||||||
|
return astString;
|
||||||
|
}
|
||||||
|
else if ( stString!=null ) {// Return toString of ST
|
||||||
|
return stString;
|
||||||
|
}
|
||||||
|
if ( ruleReturn!=null ) {
|
||||||
|
return ruleReturn;
|
||||||
|
}
|
||||||
|
if ( err.toString().length()==0 && out.toString().length()==0 ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (ClassNotFoundException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
}
|
||||||
|
catch (SecurityException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
}
|
||||||
|
catch (NoSuchMethodException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
}
|
||||||
|
catch (IllegalAccessException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
}
|
||||||
|
catch (InvocationTargetException e) {
|
||||||
|
this.stdout = out.toString();
|
||||||
|
this.stderr = err.toString();
|
||||||
|
|
||||||
|
if ( e.getCause()!=null ) this.stderr += e.getCause().toString();
|
||||||
|
else this.stderr += e.toString();
|
||||||
|
return this.stderr;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if ( ps!=null ) ps.close();
|
||||||
|
if ( ps2!=null ) ps2.close();
|
||||||
|
System.setOut(console); // Reset standard output
|
||||||
|
System.setErr(consoleErr); // Reset standard err out
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return this.stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Invoke target parser.rule
|
||||||
|
public Object execTreeParser(String testTreeRuleName, String testRuleName, String testInput, boolean isFile) throws Exception {
|
||||||
|
CharStream input;
|
||||||
|
if ( isFile ) {
|
||||||
|
String filePath = testInput;
|
||||||
|
File testInputFile = new File(filePath);
|
||||||
|
// if input test file is not found under the current dir, also try to look for it under the package dir
|
||||||
|
if ( !testInputFile.exists() && packagePath!=null ) {
|
||||||
|
testInputFile = new File(packagePath, filePath);
|
||||||
|
if ( testInputFile.exists() ) filePath = testInputFile.getCanonicalPath();
|
||||||
|
}
|
||||||
|
input = new ANTLRFileStream(filePath);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
input = new ANTLRStringStream(testInput);
|
||||||
|
}
|
||||||
|
Class<? extends Lexer> lexer;
|
||||||
|
Class<? extends Parser> parser;
|
||||||
|
Class<? extends TreeParser> treeParser;
|
||||||
|
PrintStream ps = null; // for redirecting stdout later
|
||||||
|
PrintStream ps2 = null; // for redirecting stderr later
|
||||||
|
try {
|
||||||
|
/** Use Reflection to create instances of lexer and parser */
|
||||||
|
lexer = Class.forName(lexerPath).asSubclass(Lexer.class);
|
||||||
|
Constructor<? extends Lexer> lexConstructor = lexer.getConstructor(CharStream.class);
|
||||||
|
Lexer lexObj = lexConstructor.newInstance(input); // makes new instance of lexer
|
||||||
|
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexObj);
|
||||||
|
|
||||||
|
parser = Class.forName(parserPath).asSubclass(Parser.class);
|
||||||
|
Constructor<? extends Parser> parConstructor = parser.getConstructor(TokenStream.class);
|
||||||
|
Parser parObj = parConstructor.newInstance(tokens); // makes new instance of parser
|
||||||
|
|
||||||
|
// set up customized tree adaptor if necessary
|
||||||
|
TreeAdaptor customTreeAdaptor = null;
|
||||||
|
if ( treeAdaptorPath!=null ) {
|
||||||
|
Method _setTreeAdaptor = parser.getMethod("setTreeAdaptor", TreeAdaptor.class);
|
||||||
|
Class<? extends TreeAdaptor> _treeAdaptor = Class.forName(treeAdaptorPath).asSubclass(TreeAdaptor.class);
|
||||||
|
customTreeAdaptor = _treeAdaptor.newInstance();
|
||||||
|
_setTreeAdaptor.invoke(parObj, customTreeAdaptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
Method ruleName = parser.getMethod(testRuleName);
|
||||||
|
|
||||||
|
/** Start of I/O Redirecting */
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ByteArrayOutputStream err = new ByteArrayOutputStream();
|
||||||
|
ps = new PrintStream(out);
|
||||||
|
ps2 = new PrintStream(err);
|
||||||
|
System.setOut(ps);
|
||||||
|
System.setErr(ps2);
|
||||||
|
/** End of redirecting */
|
||||||
|
|
||||||
|
/** Invoke grammar rule, and get the return value */
|
||||||
|
Object ruleReturn = ruleName.invoke(parObj);
|
||||||
|
|
||||||
|
Class<?> _return = Class.forName(parserPath+"$"+testRuleName+"_return");
|
||||||
|
Method returnName = _return.getMethod("getTree");
|
||||||
|
CommonTree tree = (CommonTree) returnName.invoke(ruleReturn);
|
||||||
|
|
||||||
|
// Walk resulting tree; create tree nodes stream first
|
||||||
|
CommonTreeNodeStream nodes;
|
||||||
|
if ( customTreeAdaptor!=null ) {
|
||||||
|
nodes = new CommonTreeNodeStream(customTreeAdaptor, tree);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nodes = new CommonTreeNodeStream(tree);
|
||||||
|
}
|
||||||
|
// AST nodes have payload that point into token stream
|
||||||
|
nodes.setTokenStream(tokens);
|
||||||
|
// Create a tree walker attached to the nodes stream
|
||||||
|
treeParser = Class.forName(treeParserPath).asSubclass(TreeParser.class);
|
||||||
|
Constructor<? extends TreeParser> treeParConstructor = treeParser.getConstructor(TreeNodeStream.class);
|
||||||
|
TreeParser treeParObj = treeParConstructor.newInstance(nodes); // makes new instance of tree parser
|
||||||
|
// Invoke the tree rule, and store the return value if there is
|
||||||
|
Method treeRuleName = treeParser.getMethod(testTreeRuleName);
|
||||||
|
Object treeRuleReturn = treeRuleName.invoke(treeParObj);
|
||||||
|
|
||||||
|
String astString = null;
|
||||||
|
String stString = null;
|
||||||
|
/** If tree rule has return value, determine if it contains an AST or a ST */
|
||||||
|
if ( treeRuleReturn!=null ) {
|
||||||
|
if ( treeRuleReturn.getClass().toString().indexOf(testTreeRuleName+"_return")>0 ) {
|
||||||
|
try { // NullPointerException may happen here...
|
||||||
|
Class<?> _treeReturn = Class.forName(treeParserPath+"$"+testTreeRuleName+"_return");
|
||||||
|
Method[] methods = _treeReturn.getDeclaredMethods();
|
||||||
|
for(Method method : methods) {
|
||||||
|
if ( method.getName().equals("getTree") ) {
|
||||||
|
Method treeReturnName = _treeReturn.getMethod("getTree");
|
||||||
|
CommonTree returnTree = (CommonTree) treeReturnName.invoke(treeRuleReturn);
|
||||||
|
astString = returnTree.toStringTree();
|
||||||
|
}
|
||||||
|
else if ( method.getName().equals("getTemplate") ) {
|
||||||
|
Method treeReturnName = _return.getMethod("getTemplate");
|
||||||
|
StringTemplate st = (StringTemplate) treeReturnName.invoke(treeRuleReturn);
|
||||||
|
stString = st.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
System.err.println(e); // Note: If any exception occurs, the test is viewed as failed.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
this.stdout = null;
|
||||||
|
this.stderr = null;
|
||||||
|
|
||||||
|
/** Invalid input */
|
||||||
|
if ( tokens.index()!=tokens.size()-1 ) {
|
||||||
|
throw new InvalidInputException();
|
||||||
|
}
|
||||||
|
|
||||||
|
// retVal could be actual return object from rule, stderr or stdout
|
||||||
|
if ( err.toString().length()>0 ) {
|
||||||
|
this.stderr = err.toString();
|
||||||
|
return this.stderr;
|
||||||
|
}
|
||||||
|
if ( out.toString().length()>0 ) {
|
||||||
|
this.stdout = out.toString();
|
||||||
|
}
|
||||||
|
if ( astString!=null ) { // Return toStringTree of AST
|
||||||
|
return astString;
|
||||||
|
}
|
||||||
|
else if ( stString!=null ) {// Return toString of ST
|
||||||
|
return stString;
|
||||||
|
}
|
||||||
|
if ( treeRuleReturn!=null ) {
|
||||||
|
return treeRuleReturn;
|
||||||
|
}
|
||||||
|
if ( err.toString().length()==0 && out.toString().length()==0 ) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
if ( e.getCause()!=null ) this.stderr = e.getCause().toString();
|
||||||
|
else this.stderr = e.toString();
|
||||||
|
return this.stderr;
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if ( ps!=null ) ps.close();
|
||||||
|
if ( ps2!=null ) ps2.close();
|
||||||
|
System.setOut(console); // Reset standard output
|
||||||
|
System.setErr(consoleErr); // Reset standard err out
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stdout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Modify the return value if the expected token type is OK or FAIL
|
||||||
|
public Object examineExecResult(int tokenType, Object retVal) {
|
||||||
|
System.out.println("expect "+(tokenType==gUnitParser.OK?"OK":"FAIL")+
|
||||||
|
"stderr=="+stderr);
|
||||||
|
if ( tokenType==gUnitParser.OK ) { // expected Token: OK
|
||||||
|
if ( this.stderr==null || this.stderr.length()==0 ) {
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "FAIL, "+this.stderr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ( tokenType==gUnitParser.FAIL ) { // expected Token: FAIL
|
||||||
|
if ( this.stderr!=null && this.stderr.length()>0 ) {
|
||||||
|
return "FAIL";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return "OK";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { // return the same object for the other token types
|
||||||
|
return retVal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleUnexpectedException(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,655 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon Jen-Yuan Su
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
import org.antlr.runtime.*;
|
||||||
|
import org.antlr.runtime.tree.CommonTree;
|
||||||
|
import org.antlr.runtime.tree.CommonTreeNodeStream;
|
||||||
|
import org.antlr.runtime.tree.TreeAdaptor;
|
||||||
|
import org.antlr.runtime.tree.TreeNodeStream;
|
||||||
|
import org.antlr.stringtemplate.CommonGroupLoader;
|
||||||
|
import org.antlr.stringtemplate.StringTemplate;
|
||||||
|
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||||
|
import org.antlr.stringtemplate.StringTemplateGroupLoader;
|
||||||
|
import org.antlr.stringtemplate.language.AngleBracketTemplateLexer;
|
||||||
|
|
||||||
|
import java.io.ByteArrayOutputStream;
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.PrintStream;
|
||||||
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
import org.antlr.runtime.tree.TreeParser;
|
||||||
|
|
||||||
|
public class gUnitExecutor implements ITestSuite {
|
||||||
|
public GrammarInfo grammarInfo;
|
||||||
|
|
||||||
|
private final ClassLoader grammarClassLoader;
|
||||||
|
|
||||||
|
private final String testsuiteDir;
|
||||||
|
|
||||||
|
public int numOfTest;
|
||||||
|
|
||||||
|
public int numOfSuccess;
|
||||||
|
|
||||||
|
public int numOfFailure;
|
||||||
|
|
||||||
|
private String title;
|
||||||
|
|
||||||
|
public int numOfInvalidInput;
|
||||||
|
|
||||||
|
private String parserName;
|
||||||
|
|
||||||
|
private String lexerName;
|
||||||
|
|
||||||
|
public List<AbstractTest> failures;
|
||||||
|
public List<AbstractTest> invalids;
|
||||||
|
|
||||||
|
private PrintStream console = System.out;
|
||||||
|
private PrintStream consoleErr = System.err;
|
||||||
|
|
||||||
|
public gUnitExecutor(GrammarInfo grammarInfo, String testsuiteDir) {
|
||||||
|
this( grammarInfo, determineClassLoader(), testsuiteDir);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static ClassLoader determineClassLoader() {
|
||||||
|
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||||
|
if ( classLoader == null ) {
|
||||||
|
classLoader = gUnitExecutor.class.getClassLoader();
|
||||||
|
}
|
||||||
|
return classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public gUnitExecutor(GrammarInfo grammarInfo, ClassLoader grammarClassLoader, String testsuiteDir) {
|
||||||
|
this.grammarInfo = grammarInfo;
|
||||||
|
this.grammarClassLoader = grammarClassLoader;
|
||||||
|
this.testsuiteDir = testsuiteDir;
|
||||||
|
numOfTest = 0;
|
||||||
|
numOfSuccess = 0;
|
||||||
|
numOfFailure = 0;
|
||||||
|
numOfInvalidInput = 0;
|
||||||
|
failures = new ArrayList<AbstractTest>();
|
||||||
|
invalids = new ArrayList<AbstractTest>();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected ClassLoader getGrammarClassLoader() {
|
||||||
|
return grammarClassLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected final Class<?> classForName(String name) throws ClassNotFoundException {
|
||||||
|
return getGrammarClassLoader().loadClass( name );
|
||||||
|
}
|
||||||
|
|
||||||
|
public String execTest() throws IOException{
|
||||||
|
// Set up string template for testing result
|
||||||
|
StringTemplate testResultST = getTemplateGroup().getInstanceOf("testResult");
|
||||||
|
try {
|
||||||
|
/** Set up appropriate path for parser/lexer if using package */
|
||||||
|
if (grammarInfo.getGrammarPackage()!=null ) {
|
||||||
|
parserName = grammarInfo.getGrammarPackage()+"."+grammarInfo.getGrammarName()+"Parser";
|
||||||
|
lexerName = grammarInfo.getGrammarPackage()+"."+grammarInfo.getGrammarName()+"Lexer";
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
parserName = grammarInfo.getGrammarName()+"Parser";
|
||||||
|
lexerName = grammarInfo.getGrammarName()+"Lexer";
|
||||||
|
}
|
||||||
|
|
||||||
|
/*** Start Unit/Functional Testing ***/
|
||||||
|
// Execute unit test of for parser, lexer and tree grammar
|
||||||
|
if ( grammarInfo.getTreeGrammarName()!=null ) {
|
||||||
|
title = "executing testsuite for tree grammar:"+grammarInfo.getTreeGrammarName()+" walks "+parserName;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
title = "executing testsuite for grammar:"+grammarInfo.getGrammarName();
|
||||||
|
}
|
||||||
|
executeTests();
|
||||||
|
// End of exection of unit testing
|
||||||
|
|
||||||
|
// Fill in the template holes with the test results
|
||||||
|
testResultST.setAttribute("title", title);
|
||||||
|
testResultST.setAttribute("num_of_test", numOfTest);
|
||||||
|
testResultST.setAttribute("num_of_failure", numOfFailure);
|
||||||
|
if ( numOfFailure>0 ) {
|
||||||
|
testResultST.setAttribute("failure", failures);
|
||||||
|
}
|
||||||
|
if ( numOfInvalidInput>0 ) {
|
||||||
|
testResultST.setAttribute("has_invalid", true);
|
||||||
|
testResultST.setAttribute("num_of_invalid", numOfInvalidInput);
|
||||||
|
testResultST.setAttribute("invalid", invalids);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception e) {
|
||||||
|
handleUnexpectedException(e);
|
||||||
|
}
|
||||||
|
return testResultST.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
private StringTemplateGroup getTemplateGroup() {
|
||||||
|
StringTemplateGroupLoader loader = new CommonGroupLoader("org/antlr/gunit", null);
|
||||||
|
StringTemplateGroup.registerGroupLoader(loader);
|
||||||
|
StringTemplateGroup.registerDefaultLexer(AngleBracketTemplateLexer.class);
|
||||||
|
StringTemplateGroup group = StringTemplateGroup.loadGroup("gUnitTestResult");
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: throw more specific exceptions
|
||||||
|
private gUnitTestResult runCorrectParser(String parserName, String lexerName, String rule, String lexicalRule, String treeRule, gUnitTestInput input) throws Exception
|
||||||
|
{
|
||||||
|
if ( lexicalRule!=null ) return runLexer(lexerName, lexicalRule, input);
|
||||||
|
else if ( treeRule!=null ) return runTreeParser(parserName, lexerName, rule, treeRule, input);
|
||||||
|
else return runParser(parserName, lexerName, rule, input);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void executeTests() throws Exception {
|
||||||
|
for ( gUnitTestSuite ts: grammarInfo.getRuleTestSuites() ) {
|
||||||
|
String rule = ts.getRuleName();
|
||||||
|
String lexicalRule = ts.getLexicalRuleName();
|
||||||
|
String treeRule = ts.getTreeRuleName();
|
||||||
|
for ( Map.Entry<gUnitTestInput, AbstractTest> entry : ts.testSuites.entrySet() ) { // each rule may contain multiple tests
|
||||||
|
gUnitTestInput input = entry.getKey();
|
||||||
|
numOfTest++;
|
||||||
|
// Run parser, and get the return value or stdout or stderr if there is
|
||||||
|
gUnitTestResult result = null;
|
||||||
|
AbstractTest test = entry.getValue();
|
||||||
|
try {
|
||||||
|
// TODO: create a -debug option to turn on logging, which shows progress of running tests
|
||||||
|
//System.out.print(numOfTest + ". Running rule: " + rule + "; input: '" + input.testInput + "'");
|
||||||
|
result = runCorrectParser(parserName, lexerName, rule, lexicalRule, treeRule, input);
|
||||||
|
// TODO: create a -debug option to turn on logging, which shows progress of running tests
|
||||||
|
//System.out.println("; Expecting " + test.getExpected() + "; Success?: " + test.getExpected().equals(test.getResult(result)));
|
||||||
|
} catch ( InvalidInputException e) {
|
||||||
|
numOfInvalidInput++;
|
||||||
|
test.setHeader(rule, lexicalRule, treeRule, numOfTest, input.line, input.input);
|
||||||
|
test.setActual(input.input);
|
||||||
|
invalids.add(test);
|
||||||
|
continue;
|
||||||
|
} // TODO: ensure there's no other exceptions required to be handled here...
|
||||||
|
|
||||||
|
String expected = test.getExpected();
|
||||||
|
String actual = test.getResult(result);
|
||||||
|
test.setActual(actual);
|
||||||
|
|
||||||
|
if (actual == null) {
|
||||||
|
numOfFailure++;
|
||||||
|
test.setHeader(rule, lexicalRule, treeRule, numOfTest, input.line, input.input);
|
||||||
|
test.setActual("null");
|
||||||
|
failures.add(test);
|
||||||
|
onFail(test);
|
||||||
|
}
|
||||||
|
// the 2nd condition is used for the assertFAIL test of lexer rule because BooleanTest return err msg instead of 'FAIL' if isLexerTest
|
||||||
|
else if ( expected.equals(actual) || (expected.equals("FAIL")&&!actual.equals("OK") ) ) {
|
||||||
|
numOfSuccess++;
|
||||||
|
onPass(test);
|
||||||
|
}
|
||||||
|
// TODO: something with ACTIONS - at least create action test type and throw exception.
|
||||||
|
else if ( ts.testSuites.get(input).getType()==gUnitParser.ACTION ) { // expected Token: ACTION
|
||||||
|
numOfFailure++;
|
||||||
|
test.setHeader(rule, lexicalRule, treeRule, numOfTest, input.line, input.input);
|
||||||
|
test.setActual("\t"+"{ACTION} is not supported in the grammarInfo yet...");
|
||||||
|
failures.add(test);
|
||||||
|
onFail(test);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
numOfFailure++;
|
||||||
|
test.setHeader(rule, lexicalRule, treeRule, numOfTest, input.line, input.input);
|
||||||
|
failures.add(test);
|
||||||
|
onFail(test);
|
||||||
|
}
|
||||||
|
} // end of 2nd for-loop: tests for individual rule
|
||||||
|
} // end of 1st for-loop: testsuites for grammar
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: throw proper exceptions
|
||||||
|
protected gUnitTestResult runLexer(String lexerName, String testRuleName, gUnitTestInput testInput) throws Exception {
|
||||||
|
CharStream input;
|
||||||
|
Class<? extends Lexer> lexer;
|
||||||
|
PrintStream ps = null; // for redirecting stdout later
|
||||||
|
PrintStream ps2 = null; // for redirecting stderr later
|
||||||
|
try {
|
||||||
|
/** Set up ANTLR input stream based on input source, file or String */
|
||||||
|
input = getANTLRInputStream(testInput);
|
||||||
|
|
||||||
|
/** Use Reflection to create instances of lexer and parser */
|
||||||
|
lexer = classForName(lexerName).asSubclass(Lexer.class);
|
||||||
|
Constructor<? extends Lexer> lexConstructor = lexer.getConstructor(CharStream.class);
|
||||||
|
Lexer lexObj = lexConstructor.newInstance(input); // makes new instance of lexer
|
||||||
|
|
||||||
|
Method ruleName = lexer.getMethod("m"+testRuleName);
|
||||||
|
|
||||||
|
/** Start of I/O Redirecting */
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ByteArrayOutputStream err = new ByteArrayOutputStream();
|
||||||
|
ps = new PrintStream(out);
|
||||||
|
ps2 = new PrintStream(err);
|
||||||
|
System.setOut(ps);
|
||||||
|
System.setErr(ps2);
|
||||||
|
/** End of redirecting */
|
||||||
|
|
||||||
|
/** Invoke lexer rule, and get the current index in CharStream */
|
||||||
|
ruleName.invoke(lexObj);
|
||||||
|
Method ruleName2 = lexer.getMethod("getCharIndex");
|
||||||
|
int currentIndex = (Integer) ruleName2.invoke(lexObj);
|
||||||
|
if ( currentIndex!=input.size() ) {
|
||||||
|
ps2.print("extra text found, '"+input.substring(currentIndex, input.size()-1)+"'");
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( err.toString().length()>0 ) {
|
||||||
|
gUnitTestResult testResult = new gUnitTestResult(false, err.toString(), true);
|
||||||
|
testResult.setError(err.toString());
|
||||||
|
return testResult;
|
||||||
|
}
|
||||||
|
String stdout = null;
|
||||||
|
if ( out.toString().length()>0 ) {
|
||||||
|
stdout = out.toString();
|
||||||
|
}
|
||||||
|
return new gUnitTestResult(true, stdout, true);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return getTestExceptionResult(e);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (InvocationTargetException e) { // This exception could be caused from ANTLR Runtime Exception, e.g. MismatchedTokenException
|
||||||
|
return getTestExceptionResult(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if ( ps!=null ) ps.close();
|
||||||
|
if ( ps2!=null ) ps2.close();
|
||||||
|
System.setOut(console); // Reset standard output
|
||||||
|
System.setErr(consoleErr); // Reset standard err out
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: verify this:
|
||||||
|
throw new Exception("This should be unreachable?");
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: throw proper exceptions
|
||||||
|
protected gUnitTestResult runParser(String parserName, String lexerName, String testRuleName, gUnitTestInput testInput) throws Exception {
|
||||||
|
CharStream input;
|
||||||
|
Class<? extends Lexer> lexer;
|
||||||
|
Class<? extends Parser> parser;
|
||||||
|
PrintStream ps = null; // for redirecting stdout later
|
||||||
|
PrintStream ps2 = null; // for redirecting stderr later
|
||||||
|
try {
|
||||||
|
/** Set up ANTLR input stream based on input source, file or String */
|
||||||
|
input = getANTLRInputStream(testInput);
|
||||||
|
|
||||||
|
/** Use Reflection to create instances of lexer and parser */
|
||||||
|
lexer = classForName(lexerName).asSubclass(Lexer.class);
|
||||||
|
Constructor<? extends Lexer> lexConstructor = lexer.getConstructor(CharStream.class);
|
||||||
|
Lexer lexObj = lexConstructor.newInstance(input); // makes new instance of lexer
|
||||||
|
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexObj);
|
||||||
|
|
||||||
|
parser = classForName(parserName).asSubclass(Parser.class);
|
||||||
|
Constructor<? extends Parser> parConstructor = parser.getConstructor(TokenStream.class);
|
||||||
|
Parser parObj = parConstructor.newInstance(tokens); // makes new instance of parser
|
||||||
|
|
||||||
|
// set up customized tree adaptor if necessary
|
||||||
|
if ( grammarInfo.getAdaptor()!=null ) {
|
||||||
|
Method _setTreeAdaptor = parser.getMethod("setTreeAdaptor", TreeAdaptor.class);
|
||||||
|
Class<? extends TreeAdaptor> _treeAdaptor = classForName(grammarInfo.getAdaptor()).asSubclass(TreeAdaptor.class);
|
||||||
|
_setTreeAdaptor.invoke(parObj, _treeAdaptor.newInstance());
|
||||||
|
}
|
||||||
|
|
||||||
|
Method ruleName = parser.getMethod(testRuleName);
|
||||||
|
|
||||||
|
/** Start of I/O Redirecting */
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ByteArrayOutputStream err = new ByteArrayOutputStream();
|
||||||
|
ps = new PrintStream(out);
|
||||||
|
ps2 = new PrintStream(err);
|
||||||
|
System.setOut(ps);
|
||||||
|
System.setErr(ps2);
|
||||||
|
/** End of redirecting */
|
||||||
|
|
||||||
|
/** Invoke grammar rule, and store if there is a return value */
|
||||||
|
Object ruleReturn = ruleName.invoke(parObj);
|
||||||
|
String astString = null;
|
||||||
|
String stString = null;
|
||||||
|
/** If rule has return value, determine if it contains an AST or a ST */
|
||||||
|
if ( ruleReturn!=null ) {
|
||||||
|
if ( ruleReturn.getClass().toString().indexOf(testRuleName+"_return")>0 ) {
|
||||||
|
try { // NullPointerException may happen here...
|
||||||
|
Class<?> _return = classForName(parserName+"$"+testRuleName+"_return");
|
||||||
|
Method[] methods = _return.getDeclaredMethods();
|
||||||
|
for(Method method : methods) {
|
||||||
|
if ( method.getName().equals("getTree") ) {
|
||||||
|
Method returnName = _return.getMethod("getTree");
|
||||||
|
CommonTree tree = (CommonTree) returnName.invoke(ruleReturn);
|
||||||
|
astString = tree.toStringTree();
|
||||||
|
}
|
||||||
|
else if ( method.getName().equals("getTemplate") ) {
|
||||||
|
Method returnName = _return.getMethod("getTemplate");
|
||||||
|
StringTemplate st = (StringTemplate) returnName.invoke(ruleReturn);
|
||||||
|
stString = st.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
System.err.println(e); // Note: If any exception occurs, the test is viewed as failed.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkForValidInput(tokens, ps2);
|
||||||
|
|
||||||
|
if ( err.toString().length()>0 ) {
|
||||||
|
gUnitTestResult testResult = new gUnitTestResult(false, err.toString());
|
||||||
|
testResult.setError(err.toString());
|
||||||
|
return testResult;
|
||||||
|
}
|
||||||
|
String stdout = null;
|
||||||
|
// TODO: need to deal with the case which has both ST return value and stdout
|
||||||
|
if ( out.toString().length()>0 ) {
|
||||||
|
stdout = out.toString();
|
||||||
|
}
|
||||||
|
if ( astString!=null ) { // Return toStringTree of AST
|
||||||
|
return new gUnitTestResult(true, stdout, astString);
|
||||||
|
}
|
||||||
|
else if ( stString!=null ) {// Return toString of ST
|
||||||
|
return new gUnitTestResult(true, stdout, stString);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( ruleReturn!=null ) {
|
||||||
|
// TODO: currently only works for a single return with int or String value
|
||||||
|
return new gUnitTestResult(true, stdout, String.valueOf(ruleReturn));
|
||||||
|
}
|
||||||
|
return new gUnitTestResult(true, stdout, stdout);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return getTestExceptionResult(e);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (InvocationTargetException e) { // This exception could be caused from ANTLR Runtime Exception, e.g. MismatchedTokenException
|
||||||
|
return getTestExceptionResult(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if ( ps!=null ) ps.close();
|
||||||
|
if ( ps2!=null ) ps2.close();
|
||||||
|
System.setOut(console); // Reset standard output
|
||||||
|
System.setErr(consoleErr); // Reset standard err out
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: verify this:
|
||||||
|
throw new Exception("This should be unreachable?");
|
||||||
|
}
|
||||||
|
|
||||||
|
protected gUnitTestResult runTreeParser(String parserName, String lexerName, String testRuleName, String testTreeRuleName, gUnitTestInput testInput) throws Exception {
|
||||||
|
CharStream input;
|
||||||
|
String treeParserPath;
|
||||||
|
Class<? extends Lexer> lexer;
|
||||||
|
Class<? extends Parser> parser;
|
||||||
|
Class<? extends TreeParser> treeParser;
|
||||||
|
PrintStream ps = null; // for redirecting stdout later
|
||||||
|
PrintStream ps2 = null; // for redirecting stderr later
|
||||||
|
try {
|
||||||
|
/** Set up ANTLR input stream based on input source, file or String */
|
||||||
|
input = getANTLRInputStream(testInput);
|
||||||
|
|
||||||
|
/** Set up appropriate path for tree parser if using package */
|
||||||
|
if ( grammarInfo.getGrammarPackage()!=null ) {
|
||||||
|
treeParserPath = grammarInfo.getGrammarPackage()+"."+grammarInfo.getTreeGrammarName();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
treeParserPath = grammarInfo.getTreeGrammarName();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Use Reflection to create instances of lexer and parser */
|
||||||
|
lexer = classForName(lexerName).asSubclass(Lexer.class);
|
||||||
|
Constructor<? extends Lexer> lexConstructor = lexer.getConstructor(CharStream.class);
|
||||||
|
Lexer lexObj = lexConstructor.newInstance(input); // makes new instance of lexer
|
||||||
|
|
||||||
|
CommonTokenStream tokens = new CommonTokenStream(lexObj);
|
||||||
|
|
||||||
|
parser = classForName(parserName).asSubclass(Parser.class);
|
||||||
|
Constructor<? extends Parser> parConstructor = parser.getConstructor(TokenStream.class);
|
||||||
|
Parser parObj = parConstructor.newInstance(tokens); // makes new instance of parser
|
||||||
|
|
||||||
|
// set up customized tree adaptor if necessary
|
||||||
|
TreeAdaptor customTreeAdaptor = null;
|
||||||
|
if ( grammarInfo.getAdaptor()!=null ) {
|
||||||
|
Method _setTreeAdaptor = parser.getMethod("setTreeAdaptor", TreeAdaptor.class);
|
||||||
|
Class<? extends TreeAdaptor> _treeAdaptor = classForName(grammarInfo.getAdaptor()).asSubclass(TreeAdaptor.class);
|
||||||
|
customTreeAdaptor = _treeAdaptor.newInstance();
|
||||||
|
_setTreeAdaptor.invoke(parObj, customTreeAdaptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
Method ruleName = parser.getMethod(testRuleName);
|
||||||
|
|
||||||
|
/** Start of I/O Redirecting */
|
||||||
|
ByteArrayOutputStream out = new ByteArrayOutputStream();
|
||||||
|
ByteArrayOutputStream err = new ByteArrayOutputStream();
|
||||||
|
ps = new PrintStream(out);
|
||||||
|
ps2 = new PrintStream(err);
|
||||||
|
System.setOut(ps);
|
||||||
|
System.setErr(ps2);
|
||||||
|
/** End of redirecting */
|
||||||
|
|
||||||
|
/** Invoke grammar rule, and get the return value */
|
||||||
|
Object ruleReturn = ruleName.invoke(parObj);
|
||||||
|
|
||||||
|
Class<?> _return = classForName(parserName+"$"+testRuleName+"_return");
|
||||||
|
Method returnName = _return.getMethod("getTree");
|
||||||
|
CommonTree tree = (CommonTree) returnName.invoke(ruleReturn);
|
||||||
|
|
||||||
|
// Walk resulting tree; create tree nodes stream first
|
||||||
|
CommonTreeNodeStream nodes;
|
||||||
|
if ( customTreeAdaptor!=null ) {
|
||||||
|
nodes = new CommonTreeNodeStream(customTreeAdaptor, tree);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nodes = new CommonTreeNodeStream(tree);
|
||||||
|
}
|
||||||
|
// AST nodes have payload that point into token stream
|
||||||
|
nodes.setTokenStream(tokens);
|
||||||
|
// Create a tree walker attached to the nodes stream
|
||||||
|
treeParser = classForName(treeParserPath).asSubclass(TreeParser.class);
|
||||||
|
Constructor<? extends TreeParser> treeParConstructor = treeParser.getConstructor(TreeNodeStream.class);
|
||||||
|
TreeParser treeParObj = treeParConstructor.newInstance(nodes); // makes new instance of tree parser
|
||||||
|
// Invoke the tree rule, and store the return value if there is
|
||||||
|
Method treeRuleName = treeParser.getMethod(testTreeRuleName);
|
||||||
|
Object treeRuleReturn = treeRuleName.invoke(treeParObj);
|
||||||
|
|
||||||
|
String astString = null;
|
||||||
|
String stString = null;
|
||||||
|
/** If tree rule has return value, determine if it contains an AST or a ST */
|
||||||
|
if ( treeRuleReturn!=null ) {
|
||||||
|
if ( treeRuleReturn.getClass().toString().indexOf(testTreeRuleName+"_return")>0 ) {
|
||||||
|
try { // NullPointerException may happen here...
|
||||||
|
Class<?> _treeReturn = classForName(treeParserPath+"$"+testTreeRuleName+"_return");
|
||||||
|
Method[] methods = _treeReturn.getDeclaredMethods();
|
||||||
|
for(Method method : methods) {
|
||||||
|
if ( method.getName().equals("getTree") ) {
|
||||||
|
Method treeReturnName = _treeReturn.getMethod("getTree");
|
||||||
|
CommonTree returnTree = (CommonTree) treeReturnName.invoke(treeRuleReturn);
|
||||||
|
astString = returnTree.toStringTree();
|
||||||
|
}
|
||||||
|
else if ( method.getName().equals("getTemplate") ) {
|
||||||
|
Method treeReturnName = _return.getMethod("getTemplate");
|
||||||
|
StringTemplate st = (StringTemplate) treeReturnName.invoke(treeRuleReturn);
|
||||||
|
stString = st.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch(Exception e) {
|
||||||
|
System.err.println(e); // Note: If any exception occurs, the test is viewed as failed.
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
checkForValidInput( tokens, ps2 );
|
||||||
|
|
||||||
|
if ( err.toString().length()>0 ) {
|
||||||
|
gUnitTestResult testResult = new gUnitTestResult(false, err.toString());
|
||||||
|
testResult.setError(err.toString());
|
||||||
|
return testResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
String stdout = null;
|
||||||
|
// TODO: need to deal with the case which has both ST return value and stdout
|
||||||
|
if ( out.toString().length()>0 ) {
|
||||||
|
stdout = out.toString();
|
||||||
|
}
|
||||||
|
if ( astString!=null ) { // Return toStringTree of AST
|
||||||
|
return new gUnitTestResult(true, stdout, astString);
|
||||||
|
}
|
||||||
|
else if ( stString!=null ) {// Return toString of ST
|
||||||
|
return new gUnitTestResult(true, stdout, stString);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( treeRuleReturn!=null ) {
|
||||||
|
// TODO: again, currently only works for a single return with int or String value
|
||||||
|
return new gUnitTestResult(true, stdout, String.valueOf(treeRuleReturn));
|
||||||
|
}
|
||||||
|
return new gUnitTestResult(true, stdout, stdout);
|
||||||
|
} catch (IOException e) {
|
||||||
|
return getTestExceptionResult(e);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (SecurityException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
handleUnexpectedException( e );
|
||||||
|
} catch (InvocationTargetException e) { // note: This exception could be caused from ANTLR Runtime Exception...
|
||||||
|
return getTestExceptionResult(e);
|
||||||
|
} finally {
|
||||||
|
try {
|
||||||
|
if ( ps!=null ) ps.close();
|
||||||
|
if ( ps2!=null ) ps2.close();
|
||||||
|
System.setOut(console); // Reset standard output
|
||||||
|
System.setErr(consoleErr); // Reset standard err out
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// TODO: verify this:
|
||||||
|
throw new Exception("Should not be reachable?");
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create ANTLR input stream based on input source, file or String
|
||||||
|
private CharStream getANTLRInputStream(gUnitTestInput testInput) throws IOException {
|
||||||
|
CharStream input;
|
||||||
|
if ( testInput.isFile) {
|
||||||
|
String filePath = testInput.input;
|
||||||
|
File testInputFile = new File(filePath);
|
||||||
|
// if input test file is not found under the current dir, try to look for it from dir where the testsuite file locates
|
||||||
|
if ( !testInputFile.exists() ) {
|
||||||
|
testInputFile = new File(this.testsuiteDir, filePath);
|
||||||
|
if ( testInputFile.exists() ) filePath = testInputFile.getCanonicalPath();
|
||||||
|
// if still not found, also try to look for it under the package dir
|
||||||
|
else if ( grammarInfo.getGrammarPackage()!=null ) {
|
||||||
|
testInputFile = new File("."+File.separator+grammarInfo.getGrammarPackage().replace(".", File.separator), filePath);
|
||||||
|
if ( testInputFile.exists() ) filePath = testInputFile.getCanonicalPath();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
input = new ANTLRFileStream(filePath);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
input = new ANTLRStringStream(testInput.input);
|
||||||
|
}
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
// set up the cause of exception or the exception name into a gUnitTestResult instance
|
||||||
|
private gUnitTestResult getTestExceptionResult(Exception e) {
|
||||||
|
gUnitTestResult testResult;
|
||||||
|
if ( e.getCause()!=null ) {
|
||||||
|
testResult = new gUnitTestResult(false, e.getCause().toString(), true);
|
||||||
|
testResult.setError(e.getCause().toString());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
testResult = new gUnitTestResult(false, e.toString(), true);
|
||||||
|
testResult.setError(e.toString());
|
||||||
|
}
|
||||||
|
return testResult;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the input has been properly consumed
|
||||||
|
*/
|
||||||
|
protected void checkForValidInput(CommonTokenStream tokens, PrintStream ps2) {
|
||||||
|
if ( tokens.index() != tokens.size() - 1 ) {
|
||||||
|
//At this point we need to check for redundant EOF tokens
|
||||||
|
//which might have been added by the Parser:
|
||||||
|
List<? extends Token> endingTokens = tokens.getTokens(tokens.index(), tokens.size() -1);
|
||||||
|
for (Token endToken : endingTokens) {
|
||||||
|
if (! "<EOF>".equals(endToken.getText())) {
|
||||||
|
//writing to ps2 will mark the test as failed:
|
||||||
|
ps2.print( "Invalid input" );
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onPass(ITestCase passTest) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void onFail(ITestCase failTest) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void handleUnexpectedException(Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,46 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon, Jen-Yuan Su
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
/** A class which contains input information of an individual testuite */
|
||||||
|
public class gUnitTestInput {
|
||||||
|
public String input; // a test input string for a testsuite
|
||||||
|
public boolean isFile; // if true, the input represents a filename
|
||||||
|
public int line; // line number in the script
|
||||||
|
|
||||||
|
public gUnitTestInput(String input, boolean isFile, int line) {
|
||||||
|
this.input = input;
|
||||||
|
this.isFile = isFile;
|
||||||
|
this.line = line;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getInputEscaped() {
|
||||||
|
return JUnitCodeGen.escapeForJava(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD license"]
|
||||||
|
Copyright (c) 2007 Kenny MacDermid
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
public class gUnitTestResult {
|
||||||
|
|
||||||
|
private boolean success;
|
||||||
|
private String output; // stdout
|
||||||
|
private String error; // stderr
|
||||||
|
private String returned; // AST (toStringTree) or ST (toString)
|
||||||
|
private boolean isLexerTest;
|
||||||
|
|
||||||
|
public gUnitTestResult(boolean success, String output) {
|
||||||
|
this.success = success;
|
||||||
|
this.output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public gUnitTestResult(boolean success, String output, boolean isLexerTest) {
|
||||||
|
this(success, output);
|
||||||
|
this.isLexerTest = isLexerTest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public gUnitTestResult(boolean success, String output, String returned) {
|
||||||
|
this(success, output);
|
||||||
|
this.returned = returned;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSuccess() {
|
||||||
|
return success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOutput() {
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getError() {
|
||||||
|
return error;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getReturned() {
|
||||||
|
return returned;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isLexerTest() {
|
||||||
|
return isLexerTest;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setError(String error) {
|
||||||
|
this.error = error;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon Jen-Yuan Su
|
||||||
|
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.gunit;
|
||||||
|
|
||||||
|
/** A class which wraps all testsuites for an individual rule */
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.LinkedHashMap;
|
||||||
|
|
||||||
|
public class gUnitTestSuite {
|
||||||
|
protected String rule = null; // paeser rule name for unit testing
|
||||||
|
protected String lexicalRule = null; // lexical rule name
|
||||||
|
protected String treeRule = null; // optional, required for testing tree grammar rule
|
||||||
|
protected boolean isLexicalRule = false;
|
||||||
|
|
||||||
|
/** A map which stores input/output pairs (individual testsuites).
|
||||||
|
* In other words, it maps input data for unit test (gUnitTestInput object)
|
||||||
|
* to an expected output (Token object).
|
||||||
|
*/
|
||||||
|
protected Map<gUnitTestInput, AbstractTest> testSuites = new LinkedHashMap<gUnitTestInput, AbstractTest>();
|
||||||
|
|
||||||
|
public gUnitTestSuite() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public gUnitTestSuite(String rule) {
|
||||||
|
this.rule = rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public gUnitTestSuite(String treeRule, String rule) {
|
||||||
|
this.rule = rule;
|
||||||
|
this.treeRule = treeRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRuleName(String ruleName) { this.rule = ruleName; }
|
||||||
|
public void setLexicalRuleName(String lexicalRule) { this.lexicalRule = lexicalRule; this.isLexicalRule = true; }
|
||||||
|
public void setTreeRuleName(String treeRuleName) { this.treeRule = treeRuleName; }
|
||||||
|
|
||||||
|
public String getRuleName() { return this.rule; }
|
||||||
|
public String getLexicalRuleName() { return this.lexicalRule; }
|
||||||
|
public String getTreeRuleName() { return this.treeRule; }
|
||||||
|
public boolean isLexicalRule() { return this.isLexicalRule; }
|
||||||
|
|
||||||
|
public void addTestCase(gUnitTestInput input, AbstractTest expect) {
|
||||||
|
if ( input!=null && expect!=null ) {
|
||||||
|
/*
|
||||||
|
* modified by shaoting
|
||||||
|
* if rule is null, use lexRule name
|
||||||
|
*/
|
||||||
|
//expect.setTestedRuleName(this.rule);
|
||||||
|
expect.setTestedRuleName(this.rule ==null ? this.lexicalRule : this.rule);
|
||||||
|
expect.setTestCaseIndex(this.testSuites.size());
|
||||||
|
this.testSuites.put(input, expect);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,51 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui;
|
||||||
|
|
||||||
|
import org.antlr.gunit.swingui.model.ITestCaseInput;
|
||||||
|
import java.awt.event.ActionListener;
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public abstract class AbstractInputEditor {
|
||||||
|
|
||||||
|
protected ITestCaseInput input;
|
||||||
|
public void setInput(ITestCaseInput input) {
|
||||||
|
this.input = input;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected JComponent comp;
|
||||||
|
public JComponent getControl() { return comp; }
|
||||||
|
|
||||||
|
abstract public void addActionListener(ActionListener l) ;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,35 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui;
|
||||||
|
|
||||||
|
import java.awt.Component;
|
||||||
|
|
||||||
|
public interface IController {
|
||||||
|
public Object getModel() ;
|
||||||
|
public Component getView() ;
|
||||||
|
}
|
@ -0,0 +1,83 @@
|
|||||||
|
package org.antlr.gunit.swingui;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import javax.swing.ImageIcon;
|
||||||
|
|
||||||
|
public class ImageFactory {
|
||||||
|
|
||||||
|
private static ImageFactory singleton ;
|
||||||
|
|
||||||
|
public static ImageFactory getSingleton() {
|
||||||
|
if(singleton == null) singleton = new ImageFactory();
|
||||||
|
return singleton;
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImageFactory() {
|
||||||
|
ACCEPT = getImage("accept.png");
|
||||||
|
ADD = getImage("add.png");
|
||||||
|
DELETE = getImage("delete24.png");
|
||||||
|
TEXTFILE = getImage("textfile24.png");
|
||||||
|
TEXTFILE16 = getImage("textfile16.png");
|
||||||
|
ADDFILE = getImage("addfile24.png");
|
||||||
|
WINDOW16 = getImage("windowb16.png");
|
||||||
|
FAV16 = getImage("favb16.png");
|
||||||
|
SAVE = getImage("floppy24.png");
|
||||||
|
OPEN = getImage("folder24.png");
|
||||||
|
EDIT16 = getImage("edit16.png");
|
||||||
|
FILE16 = getImage("file16.png");
|
||||||
|
RUN_PASS = getImage("runpass.png");
|
||||||
|
RUN_FAIL = getImage("runfail.png");
|
||||||
|
TESTSUITE = getImage("testsuite.png");
|
||||||
|
TESTGROUP = getImage("testgroup.png");
|
||||||
|
TESTGROUPX = getImage("testgroupx.png");
|
||||||
|
NEXT = getImage("next24.png");
|
||||||
|
}
|
||||||
|
|
||||||
|
private ImageIcon getImage(String name) {
|
||||||
|
name = IMG_DIR + name;
|
||||||
|
try {
|
||||||
|
final ClassLoader loader = ImageFactory.class.getClassLoader();
|
||||||
|
final InputStream in = loader.getResourceAsStream(name);
|
||||||
|
final byte[] data = new byte[in.available()];
|
||||||
|
in.read(data);
|
||||||
|
in.close();
|
||||||
|
return new ImageIcon(data);
|
||||||
|
} catch (IOException ex) {
|
||||||
|
System.err.println("Can't load image file: " + name);
|
||||||
|
System.exit(1);
|
||||||
|
} catch(RuntimeException e) {
|
||||||
|
System.err.println("Can't load image file: " + name);
|
||||||
|
System.exit(1);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static final String IMG_DIR = "org/antlr/gunit/swingui/images/";
|
||||||
|
|
||||||
|
public ImageIcon ACCEPT;
|
||||||
|
public ImageIcon ADD;
|
||||||
|
public ImageIcon DELETE;
|
||||||
|
public ImageIcon TEXTFILE ;
|
||||||
|
public ImageIcon ADDFILE;
|
||||||
|
|
||||||
|
public ImageIcon TEXTFILE16 ;
|
||||||
|
public ImageIcon WINDOW16;
|
||||||
|
public ImageIcon FAV16;
|
||||||
|
public ImageIcon SAVE ;
|
||||||
|
|
||||||
|
public ImageIcon OPEN ;
|
||||||
|
public ImageIcon EDIT16;
|
||||||
|
public ImageIcon FILE16;
|
||||||
|
public ImageIcon NEXT;
|
||||||
|
|
||||||
|
public ImageIcon RUN_PASS;
|
||||||
|
public ImageIcon RUN_FAIL;
|
||||||
|
public ImageIcon TESTSUITE;
|
||||||
|
public ImageIcon TESTGROUP ;
|
||||||
|
public ImageIcon TESTGROUPX;
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,160 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui;
|
||||||
|
|
||||||
|
import javax.swing.event.ListDataListener;
|
||||||
|
import org.antlr.gunit.swingui.model.Rule;
|
||||||
|
import org.antlr.gunit.swingui.ImageFactory;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.event.MouseAdapter;
|
||||||
|
import java.awt.event.MouseEvent;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.DefaultListModel;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JList;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.ListCellRenderer;
|
||||||
|
import javax.swing.ListModel;
|
||||||
|
import javax.swing.ListSelectionModel;
|
||||||
|
import javax.swing.event.ListSelectionListener;
|
||||||
|
import org.antlr.gunit.swingui.model.TestSuite;
|
||||||
|
|
||||||
|
public class RuleListController implements IController {
|
||||||
|
|
||||||
|
/* Sub-controls */
|
||||||
|
private final JList list = new JList();
|
||||||
|
private final JScrollPane scroll = new JScrollPane( list,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||||
|
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||||
|
|
||||||
|
/* Model */
|
||||||
|
private ListModel model = null;
|
||||||
|
private TestSuite testSuite = null;
|
||||||
|
|
||||||
|
public RuleListController() {
|
||||||
|
this.initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JScrollPane getView() {
|
||||||
|
return scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setTestSuite(TestSuite newTestSuite) {
|
||||||
|
testSuite = newTestSuite;
|
||||||
|
model = new RuleListModel();
|
||||||
|
list.setModel(model);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void initialize(TestSuite ts) {
|
||||||
|
setTestSuite(ts);
|
||||||
|
if(model.getSize() > 0) list.setSelectedIndex(0);
|
||||||
|
list.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize view.
|
||||||
|
*/
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
scroll.setViewportBorder(BorderFactory.createEtchedBorder());
|
||||||
|
scroll.setBorder(BorderFactory.createTitledBorder(
|
||||||
|
BorderFactory.createEmptyBorder(), "Rules"));
|
||||||
|
scroll.setOpaque(false);
|
||||||
|
|
||||||
|
list.setOpaque(false);
|
||||||
|
list.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);
|
||||||
|
list.setLayoutOrientation(JList.VERTICAL);
|
||||||
|
list.setCellRenderer(new RuleListItemRenderer());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListSelectionListener(ListSelectionListener l) {
|
||||||
|
this.list.addListSelectionListener(l);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getModel() {
|
||||||
|
return model;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ITEM RENDERER */
|
||||||
|
|
||||||
|
private class RuleListItemRenderer extends JLabel implements ListCellRenderer{
|
||||||
|
|
||||||
|
public RuleListItemRenderer() {
|
||||||
|
this.setPreferredSize(new Dimension(50, 18));
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getListCellRendererComponent(
|
||||||
|
JList list, Object value, int index,
|
||||||
|
boolean isSelected, boolean hasFocus) {
|
||||||
|
|
||||||
|
if(value instanceof Rule) {
|
||||||
|
final Rule item = (Rule) value;
|
||||||
|
setText(item.toString());
|
||||||
|
setForeground(list.getForeground());
|
||||||
|
|
||||||
|
setIcon(item.getNotEmpty() ? ImageFactory.getSingleton().FAV16 : null);
|
||||||
|
|
||||||
|
if(list.getSelectedValue() == item ) {
|
||||||
|
setBackground(Color.LIGHT_GRAY);
|
||||||
|
setOpaque(true);
|
||||||
|
} else {
|
||||||
|
setOpaque(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
this.setText("Error!");
|
||||||
|
}
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RuleListModel implements ListModel {
|
||||||
|
|
||||||
|
public RuleListModel() {
|
||||||
|
if(testSuite == null)
|
||||||
|
throw new NullPointerException("Null test suite");
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getSize() {
|
||||||
|
return testSuite.getRuleCount();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getElementAt(int index) {
|
||||||
|
return testSuite.getRule(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addListDataListener(ListDataListener l) {}
|
||||||
|
public void removeListDataListener(ListDataListener l) {}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,240 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui;
|
||||||
|
|
||||||
|
import java.awt.BorderLayout;
|
||||||
|
import java.awt.Color;
|
||||||
|
import java.awt.Component;
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import javax.swing.BorderFactory;
|
||||||
|
import javax.swing.BoxLayout;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JScrollPane;
|
||||||
|
import javax.swing.JTextArea;
|
||||||
|
import javax.swing.JTree;
|
||||||
|
import javax.swing.event.TreeModelListener;
|
||||||
|
import javax.swing.tree.DefaultMutableTreeNode;
|
||||||
|
import javax.swing.tree.DefaultTreeModel;
|
||||||
|
import javax.swing.tree.TreeCellRenderer;
|
||||||
|
import javax.swing.tree.TreeModel;
|
||||||
|
import javax.swing.tree.TreePath;
|
||||||
|
import org.antlr.gunit.swingui.ImageFactory;
|
||||||
|
import org.antlr.gunit.swingui.model.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class RunnerController implements IController {
|
||||||
|
|
||||||
|
/* MODEL */
|
||||||
|
//private TestSuite testSuite;
|
||||||
|
|
||||||
|
/* VIEW */
|
||||||
|
private RunnerView view = new RunnerView();
|
||||||
|
public class RunnerView extends JPanel {
|
||||||
|
|
||||||
|
private JTextArea textArea = new JTextArea();
|
||||||
|
|
||||||
|
private JTree tree = new JTree();
|
||||||
|
|
||||||
|
private JScrollPane scroll = new JScrollPane(tree,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||||
|
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||||
|
|
||||||
|
public void initComponents() {
|
||||||
|
//textArea.setOpaque(false);
|
||||||
|
tree.setOpaque(false);
|
||||||
|
scroll.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
|
||||||
|
scroll.setOpaque(false);
|
||||||
|
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
|
this.add(scroll);
|
||||||
|
this.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
this.setOpaque(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
public RunnerController() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getModel() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getView() {
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void update() {
|
||||||
|
view.initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnShowSuiteResult(TestSuite suite) {
|
||||||
|
update();
|
||||||
|
view.tree.setModel(new RunnerTreeModel(suite));
|
||||||
|
view.tree.setCellRenderer(new RunnerTreeRenderer());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnShowRuleResult(Rule rule) {
|
||||||
|
update();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
StringBuffer result = new StringBuffer();
|
||||||
|
|
||||||
|
result.append("Testing result for rule: " + rule.getName());
|
||||||
|
result.append("\n--------------------\n\n");
|
||||||
|
|
||||||
|
for(TestCase testCase: rule.getTestCases()){
|
||||||
|
result.append(testCase.isPass() ? "PASS" : "FAIL");
|
||||||
|
result.append("\n");
|
||||||
|
}
|
||||||
|
result.append("\n--------------------\n");
|
||||||
|
view.textArea.setText(result.toString());
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private class TestSuiteTreeNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
|
private TestSuite data ;
|
||||||
|
|
||||||
|
public TestSuiteTreeNode(TestSuite suite) {
|
||||||
|
super(suite.getGrammarName());
|
||||||
|
for(int i=0; i<suite.getRuleCount(); ++i) {
|
||||||
|
final Rule rule = suite.getRule(i);
|
||||||
|
if(rule.getNotEmpty()) this.add(new TestGroupTreeNode(rule));
|
||||||
|
}
|
||||||
|
data = suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("%s (%d test groups)",
|
||||||
|
data.getGrammarName(),
|
||||||
|
this.getChildCount());
|
||||||
|
}
|
||||||
|
|
||||||
|
} ;
|
||||||
|
|
||||||
|
private class TestGroupTreeNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
|
private Rule data;
|
||||||
|
private boolean hasFail = false;
|
||||||
|
|
||||||
|
private TestGroupTreeNode(Rule rule) {
|
||||||
|
super(rule.getName());
|
||||||
|
for(TestCase tc: rule.getTestCases()) {
|
||||||
|
this.add(new TestCaseTreeNode(tc));
|
||||||
|
}
|
||||||
|
|
||||||
|
data = rule;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
int iPass = 0;
|
||||||
|
int iFail = 0;
|
||||||
|
for(TestCase tc: data.getTestCases()) {
|
||||||
|
if(tc.isPass())
|
||||||
|
++iPass;
|
||||||
|
else
|
||||||
|
++iFail;
|
||||||
|
}
|
||||||
|
|
||||||
|
hasFail = iFail > 0;
|
||||||
|
|
||||||
|
return String.format("%s (pass %d, fail %d)",
|
||||||
|
data.getName(), iPass, iFail);
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
private class TestCaseTreeNode extends DefaultMutableTreeNode {
|
||||||
|
|
||||||
|
private TestCase data;
|
||||||
|
|
||||||
|
private TestCaseTreeNode(TestCase tc) {
|
||||||
|
super(tc.toString());
|
||||||
|
data = tc;
|
||||||
|
}
|
||||||
|
} ;
|
||||||
|
|
||||||
|
private class RunnerTreeModel extends DefaultTreeModel {
|
||||||
|
|
||||||
|
public RunnerTreeModel(TestSuite testSuite) {
|
||||||
|
super(new TestSuiteTreeNode(testSuite));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RunnerTreeRenderer implements TreeCellRenderer {
|
||||||
|
|
||||||
|
public Component getTreeCellRendererComponent(JTree tree, Object value,
|
||||||
|
boolean selected, boolean expanded, boolean leaf, int row,
|
||||||
|
boolean hasFocus) {
|
||||||
|
|
||||||
|
JLabel label = new JLabel();
|
||||||
|
|
||||||
|
if(value instanceof TestSuiteTreeNode) {
|
||||||
|
|
||||||
|
label.setText(value.toString());
|
||||||
|
label.setIcon(ImageFactory.getSingleton().TESTSUITE);
|
||||||
|
|
||||||
|
} else if(value instanceof TestGroupTreeNode) {
|
||||||
|
|
||||||
|
TestGroupTreeNode node = (TestGroupTreeNode) value;
|
||||||
|
label.setText(value.toString());
|
||||||
|
label.setIcon( node.hasFail ?
|
||||||
|
ImageFactory.getSingleton().TESTGROUPX :
|
||||||
|
ImageFactory.getSingleton().TESTGROUP);
|
||||||
|
|
||||||
|
} else if(value instanceof TestCaseTreeNode) {
|
||||||
|
|
||||||
|
TestCaseTreeNode node = (TestCaseTreeNode) value;
|
||||||
|
label.setIcon( (node.data.isPass())?
|
||||||
|
ImageFactory.getSingleton().RUN_PASS :
|
||||||
|
ImageFactory.getSingleton().RUN_FAIL);
|
||||||
|
label.setText(value.toString());
|
||||||
|
|
||||||
|
} else {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"Invalide tree node type + " + value.getClass().getName());
|
||||||
|
}
|
||||||
|
|
||||||
|
return label;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,93 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui;
|
||||||
|
|
||||||
|
import java.awt.Dimension;
|
||||||
|
import java.awt.FlowLayout;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
import javax.swing.JPanel;
|
||||||
|
import javax.swing.JProgressBar;
|
||||||
|
|
||||||
|
public class StatusBarController implements IController {
|
||||||
|
|
||||||
|
private final JPanel panel = new JPanel();
|
||||||
|
|
||||||
|
private final JLabel labelText = new JLabel("Ready");
|
||||||
|
private final JLabel labelRuleName = new JLabel("");
|
||||||
|
private final JProgressBar progress = new JProgressBar();
|
||||||
|
|
||||||
|
public StatusBarController() {
|
||||||
|
initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initComponents() {
|
||||||
|
labelText.setPreferredSize(new Dimension(300, 20));
|
||||||
|
labelText.setHorizontalTextPosition(JLabel.LEFT);
|
||||||
|
progress.setPreferredSize(new Dimension(100, 15));
|
||||||
|
|
||||||
|
final JLabel labRuleHint = new JLabel("Rule: ");
|
||||||
|
|
||||||
|
FlowLayout layout = new FlowLayout();
|
||||||
|
layout.setAlignment(FlowLayout.LEFT);
|
||||||
|
panel.setLayout(layout);
|
||||||
|
panel.add(labelText);
|
||||||
|
panel.add(progress);
|
||||||
|
panel.add(labRuleHint);
|
||||||
|
panel.add(labelRuleName);
|
||||||
|
panel.setOpaque(false);
|
||||||
|
panel.setBorder(javax.swing.BorderFactory.createEmptyBorder());
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(String text) {
|
||||||
|
labelText.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRule(String name) {
|
||||||
|
this.labelRuleName.setText(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getModel() {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public JPanel getView() {
|
||||||
|
return panel;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProgressIndetermined(boolean value) {
|
||||||
|
this.progress.setIndeterminate(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setProgress(int value) {
|
||||||
|
this.progress.setIndeterminate(false);
|
||||||
|
this.progress.setValue(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,633 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui;
|
||||||
|
|
||||||
|
import org.antlr.gunit.swingui.model.*;
|
||||||
|
import org.antlr.gunit.swingui.ImageFactory;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class TestCaseEditController implements IController {
|
||||||
|
|
||||||
|
private JPanel view = new JPanel();
|
||||||
|
|
||||||
|
private JScrollPane scroll;
|
||||||
|
private JPanel paneDetail;
|
||||||
|
private AbstractEditorPane paneDetailInput, paneDetailOutput;
|
||||||
|
private JToolBar toolbar;
|
||||||
|
private JList listCases;
|
||||||
|
private ListModel listModel ;
|
||||||
|
|
||||||
|
public ActionListener onTestCaseNumberChange;
|
||||||
|
|
||||||
|
/* EDITORS */
|
||||||
|
private InputFileEditor editInputFile;
|
||||||
|
private InputStringEditor editInputString;
|
||||||
|
private InputMultiEditor editInputMulti;
|
||||||
|
private OutputResultEditor editOutputResult;
|
||||||
|
private OutputAstEditor editOutputAST;
|
||||||
|
private OutputStdEditor editOutputStd;
|
||||||
|
private OutputReturnEditor editOutputReturn;
|
||||||
|
|
||||||
|
private JComboBox comboInputType, comboOutputType;
|
||||||
|
|
||||||
|
/* TYPE NAME */
|
||||||
|
private static final String IN_TYPE_STRING = "Single-line Text";
|
||||||
|
private static final String IN_TYPE_MULTI = "Multi-line Text";
|
||||||
|
private static final String IN_TYPE_FILE = "Disk File";
|
||||||
|
private static final String OUT_TYPE_BOOL = "OK or Fail";
|
||||||
|
private static final String OUT_TYPE_AST = "AST";
|
||||||
|
private static final String OUT_TYPE_STD = "Standard Output";
|
||||||
|
private static final String OUT_TYPE_RET = "Return Value";
|
||||||
|
|
||||||
|
private static final String DEFAULT_IN_SCRIPT = "";
|
||||||
|
private static final String DEFAULT_OUT_SCRIPT = "";
|
||||||
|
|
||||||
|
private static final Object[] INPUT_TYPE = {
|
||||||
|
IN_TYPE_STRING, IN_TYPE_MULTI, IN_TYPE_FILE
|
||||||
|
};
|
||||||
|
|
||||||
|
private static final Object[] OUTPUT_TYPE = {
|
||||||
|
OUT_TYPE_BOOL, OUT_TYPE_AST, OUT_TYPE_STD, OUT_TYPE_RET
|
||||||
|
};
|
||||||
|
|
||||||
|
/* SIZE */
|
||||||
|
private static final int TEST_CASE_DETAIL_WIDTH = 300;
|
||||||
|
private static final int TEST_EDITOR_WIDTH = 280;
|
||||||
|
private static final int TEST_CASE_DETAIL_HEIGHT = 250;
|
||||||
|
private static final int TEST_EDITOR_HEIGHT = 120;
|
||||||
|
|
||||||
|
/* MODEL */
|
||||||
|
private Rule currentRule = null;
|
||||||
|
private TestCase currentTestCase = null;
|
||||||
|
|
||||||
|
/* END OF MODEL*/
|
||||||
|
|
||||||
|
private static final HashMap<Class<?>, String> TypeNameTable;
|
||||||
|
static {
|
||||||
|
TypeNameTable = new HashMap<Class<?>, String> ();
|
||||||
|
TypeNameTable.put(TestCaseInputString.class, IN_TYPE_STRING);
|
||||||
|
TypeNameTable.put(TestCaseInputMultiString.class, IN_TYPE_MULTI);
|
||||||
|
TypeNameTable.put(TestCaseInputFile.class, IN_TYPE_FILE);
|
||||||
|
|
||||||
|
TypeNameTable.put(TestCaseOutputResult.class, OUT_TYPE_BOOL);
|
||||||
|
TypeNameTable.put(TestCaseOutputAST.class, OUT_TYPE_AST);
|
||||||
|
TypeNameTable.put(TestCaseOutputStdOut.class, OUT_TYPE_STD);
|
||||||
|
TypeNameTable.put(TestCaseOutputReturn.class, OUT_TYPE_RET);
|
||||||
|
}
|
||||||
|
|
||||||
|
//private WorkSpaceView owner;
|
||||||
|
|
||||||
|
public TestCaseEditController(WorkSpaceView workspace) {
|
||||||
|
//this.owner = workspace;
|
||||||
|
initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestCaseEditController() {
|
||||||
|
initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void OnLoadRule(Rule rule) {
|
||||||
|
if(rule == null) throw new IllegalArgumentException("Null");
|
||||||
|
this.currentRule = rule;
|
||||||
|
this.currentTestCase = null;
|
||||||
|
this.listModel = rule;
|
||||||
|
this.listCases.setModel(this.listModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setCurrentTestCase(TestCase testCase) {
|
||||||
|
if(testCase == null) throw new IllegalArgumentException("Null");
|
||||||
|
this.listCases.setSelectedValue(testCase, true);
|
||||||
|
this.currentTestCase = testCase;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Rule getCurrentRule() {
|
||||||
|
return this.currentRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initComponents() {
|
||||||
|
|
||||||
|
/* CASE LIST */
|
||||||
|
listCases = new JList();
|
||||||
|
listCases.addListSelectionListener(new TestCaseListSelectionListener());
|
||||||
|
listCases.setCellRenderer(listRenderer);
|
||||||
|
listCases.setOpaque(false);
|
||||||
|
|
||||||
|
scroll = new JScrollPane(listCases);
|
||||||
|
scroll.setBorder(BorderFactory.createTitledBorder(
|
||||||
|
BorderFactory.createEmptyBorder(), "Test Cases"));
|
||||||
|
scroll.setOpaque(false);
|
||||||
|
scroll.setViewportBorder(BorderFactory.createEtchedBorder());
|
||||||
|
|
||||||
|
/* CASE DETAIL */
|
||||||
|
|
||||||
|
editInputString = new InputStringEditor();
|
||||||
|
editInputMulti = new InputMultiEditor();
|
||||||
|
editInputFile = new InputFileEditor();
|
||||||
|
|
||||||
|
editOutputResult = new OutputResultEditor();
|
||||||
|
editOutputAST = new OutputAstEditor();
|
||||||
|
editOutputStd = new OutputStdEditor();
|
||||||
|
editOutputReturn = new OutputReturnEditor();
|
||||||
|
|
||||||
|
paneDetail = new JPanel();
|
||||||
|
paneDetail.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
paneDetail.setOpaque(false);
|
||||||
|
|
||||||
|
comboInputType = new JComboBox(INPUT_TYPE);
|
||||||
|
comboInputType.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent event) {
|
||||||
|
OnInputTestCaseTypeChanged(comboInputType.getSelectedItem());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
comboOutputType = new JComboBox(OUTPUT_TYPE);
|
||||||
|
comboOutputType.addActionListener(new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent event) {
|
||||||
|
OnOutputTestCaseTypeChanged(comboOutputType.getSelectedItem());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
paneDetailInput = new InputEditorPane(comboInputType);
|
||||||
|
paneDetailOutput = new OutputEditorPane(comboOutputType);
|
||||||
|
|
||||||
|
BoxLayout layout = new BoxLayout(paneDetail, BoxLayout.PAGE_AXIS);
|
||||||
|
paneDetail.setLayout(layout);
|
||||||
|
|
||||||
|
paneDetail.add(this.paneDetailInput);
|
||||||
|
paneDetail.add(this.paneDetailOutput);
|
||||||
|
|
||||||
|
/* TOOLBAR */
|
||||||
|
toolbar = new JToolBar("Edit TestCases", JToolBar.VERTICAL);
|
||||||
|
toolbar.setFloatable(false);
|
||||||
|
toolbar.add(new AddTestCaseAction());
|
||||||
|
toolbar.add(new RemoveTestCaseAction());
|
||||||
|
|
||||||
|
/* COMPOSITE */
|
||||||
|
view.setLayout(new BorderLayout());
|
||||||
|
view.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
view.setOpaque(false);
|
||||||
|
view.add(toolbar, BorderLayout.WEST);
|
||||||
|
view.add(scroll, BorderLayout.CENTER);
|
||||||
|
view.add(paneDetail, BorderLayout.EAST);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateInputEditor() {
|
||||||
|
JComponent editor = null;
|
||||||
|
|
||||||
|
if(currentTestCase != null ) {
|
||||||
|
ITestCaseInput input = this.currentTestCase.getInput();
|
||||||
|
if(input instanceof TestCaseInputString) {
|
||||||
|
this.editInputString.setText(input.getScript());
|
||||||
|
editor = this.editInputString;
|
||||||
|
comboInputType.setSelectedItem(IN_TYPE_STRING);
|
||||||
|
} else if(input instanceof TestCaseInputMultiString) {
|
||||||
|
this.editInputMulti.setText(input.getScript());
|
||||||
|
editor = this.editInputMulti.getView();
|
||||||
|
comboInputType.setSelectedItem(IN_TYPE_MULTI);
|
||||||
|
} else if(input instanceof TestCaseInputFile) {
|
||||||
|
this.editInputFile.setText(input.getScript());
|
||||||
|
editor = this.editInputFile;
|
||||||
|
comboInputType.setSelectedItem(IN_TYPE_FILE);
|
||||||
|
} else {
|
||||||
|
throw new Error("Wrong type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
paneDetailInput.setEditor(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void updateOutputEditor() {
|
||||||
|
JComponent editor = null;
|
||||||
|
|
||||||
|
if(currentTestCase != null) {
|
||||||
|
|
||||||
|
ITestCaseOutput output = this.currentTestCase.getOutput();
|
||||||
|
|
||||||
|
if(output instanceof TestCaseOutputAST) {
|
||||||
|
|
||||||
|
this.editOutputAST.setText(output.getScript());
|
||||||
|
editor = this.editOutputAST.getView();
|
||||||
|
comboOutputType.setSelectedItem(OUT_TYPE_AST);
|
||||||
|
|
||||||
|
} else if(output instanceof TestCaseOutputResult) {
|
||||||
|
|
||||||
|
this.editOutputResult.setValue(output.getScript());
|
||||||
|
editor = this.editOutputResult;
|
||||||
|
comboOutputType.setSelectedItem(OUT_TYPE_BOOL);
|
||||||
|
|
||||||
|
} else if(output instanceof TestCaseOutputStdOut) {
|
||||||
|
|
||||||
|
this.editOutputStd.setText(output.getScript());
|
||||||
|
editor = this.editOutputStd.getView();
|
||||||
|
comboOutputType.setSelectedItem(OUT_TYPE_STD);
|
||||||
|
|
||||||
|
} else if(output instanceof TestCaseOutputReturn) {
|
||||||
|
|
||||||
|
this.editOutputReturn.setText(output.getScript());
|
||||||
|
editor = this.editOutputReturn.getView();
|
||||||
|
comboOutputType.setSelectedItem(OUT_TYPE_RET);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
throw new Error("Wrong type");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
this.paneDetailOutput.setEditor(editor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnInputTestCaseTypeChanged(Object inputTypeStr) {
|
||||||
|
if(this.currentTestCase != null) {
|
||||||
|
ITestCaseInput input ;
|
||||||
|
if(inputTypeStr == IN_TYPE_STRING) {
|
||||||
|
input = new TestCaseInputString(DEFAULT_IN_SCRIPT);
|
||||||
|
} else if(inputTypeStr == IN_TYPE_MULTI) {
|
||||||
|
input = new TestCaseInputMultiString(DEFAULT_IN_SCRIPT);
|
||||||
|
} else if(inputTypeStr == IN_TYPE_FILE) {
|
||||||
|
input = new TestCaseInputFile(DEFAULT_IN_SCRIPT);
|
||||||
|
} else {
|
||||||
|
throw new Error("Wrong Type");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(input.getClass().equals(this.currentTestCase.getInput().getClass()))
|
||||||
|
return ;
|
||||||
|
|
||||||
|
this.currentTestCase.setInput(input);
|
||||||
|
}
|
||||||
|
this.updateInputEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnOutputTestCaseTypeChanged(Object outputTypeStr) {
|
||||||
|
if(this.currentTestCase != null) {
|
||||||
|
|
||||||
|
ITestCaseOutput output ;
|
||||||
|
if(outputTypeStr == OUT_TYPE_AST) {
|
||||||
|
output = new TestCaseOutputAST(DEFAULT_OUT_SCRIPT);
|
||||||
|
} else if(outputTypeStr == OUT_TYPE_BOOL) {
|
||||||
|
output = new TestCaseOutputResult(false);
|
||||||
|
} else if(outputTypeStr == OUT_TYPE_STD) {
|
||||||
|
output = new TestCaseOutputStdOut(DEFAULT_OUT_SCRIPT);
|
||||||
|
} else if(outputTypeStr == OUT_TYPE_RET) {
|
||||||
|
output = new TestCaseOutputReturn(DEFAULT_OUT_SCRIPT);
|
||||||
|
} else {
|
||||||
|
throw new Error("Wrong Type");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(output.getClass().equals(this.currentTestCase.getOutput().getClass()))
|
||||||
|
return ;
|
||||||
|
|
||||||
|
this.currentTestCase.setOutput(output);
|
||||||
|
}
|
||||||
|
this.updateOutputEditor();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private void OnTestCaseSelected(TestCase testCase) {
|
||||||
|
//if(testCase == null) throw new RuntimeException("Null TestCase");
|
||||||
|
this.currentTestCase = testCase;
|
||||||
|
updateInputEditor();
|
||||||
|
updateOutputEditor();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnAddTestCase() {
|
||||||
|
if(currentRule == null) return;
|
||||||
|
|
||||||
|
final TestCase newCase = new TestCase(
|
||||||
|
new TestCaseInputString(""),
|
||||||
|
new TestCaseOutputResult(true));
|
||||||
|
this.currentRule.addTestCase(newCase);
|
||||||
|
setCurrentTestCase(newCase);
|
||||||
|
|
||||||
|
this.listCases.setSelectedValue(newCase, true);
|
||||||
|
this.listCases.updateUI();
|
||||||
|
this.OnTestCaseSelected(newCase);
|
||||||
|
this.onTestCaseNumberChange.actionPerformed(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRemoveTestCase() {
|
||||||
|
if(currentTestCase == null) return;
|
||||||
|
currentRule.removeElement(currentTestCase);
|
||||||
|
listCases.updateUI();
|
||||||
|
|
||||||
|
final TestCase nextActiveCase = listCases.isSelectionEmpty() ?
|
||||||
|
null : (TestCase) listCases.getSelectedValue() ;
|
||||||
|
OnTestCaseSelected(nextActiveCase);
|
||||||
|
this.onTestCaseNumberChange.actionPerformed(null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getModel() {
|
||||||
|
return currentRule;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getView() {
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EDITOR CONTAINER */
|
||||||
|
|
||||||
|
abstract public class AbstractEditorPane extends JPanel {
|
||||||
|
|
||||||
|
private JComboBox combo;
|
||||||
|
private JComponent editor;
|
||||||
|
private String title;
|
||||||
|
private JLabel placeHolder = new JLabel();
|
||||||
|
|
||||||
|
public AbstractEditorPane(JComboBox comboBox, String title) {
|
||||||
|
this.combo = comboBox;
|
||||||
|
this.editor = placeHolder;
|
||||||
|
this.title = title;
|
||||||
|
this.initComponents();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initComponents() {
|
||||||
|
placeHolder.setPreferredSize(new Dimension(
|
||||||
|
TEST_CASE_DETAIL_WIDTH, TEST_CASE_DETAIL_HEIGHT));
|
||||||
|
this.setLayout(new BoxLayout(this, BoxLayout.Y_AXIS));
|
||||||
|
this.add(combo, BorderLayout.NORTH);
|
||||||
|
this.add(editor, BorderLayout.CENTER);
|
||||||
|
this.setOpaque(false);
|
||||||
|
this.setBorder(BorderFactory.createTitledBorder(title));
|
||||||
|
this.setPreferredSize(new Dimension(
|
||||||
|
TEST_CASE_DETAIL_WIDTH, TEST_CASE_DETAIL_HEIGHT));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setEditor(JComponent newEditor) {
|
||||||
|
if(newEditor == null) newEditor = placeHolder;
|
||||||
|
this.remove(editor);
|
||||||
|
this.add(newEditor);
|
||||||
|
this.editor = newEditor;
|
||||||
|
this.updateUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InputEditorPane extends AbstractEditorPane {
|
||||||
|
public InputEditorPane(JComboBox comboBox) {
|
||||||
|
super(comboBox, "Input");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class OutputEditorPane extends AbstractEditorPane {
|
||||||
|
public OutputEditorPane(JComboBox comboBox) {
|
||||||
|
super(comboBox, "Output");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* INPUT EDITORS */
|
||||||
|
|
||||||
|
public class InputStringEditor extends JTextField implements CaretListener {
|
||||||
|
public InputStringEditor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
|
||||||
|
this.addCaretListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void caretUpdate(CaretEvent arg0) {
|
||||||
|
currentTestCase.getInput().setScript(getText());
|
||||||
|
listCases.updateUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InputMultiEditor implements CaretListener {
|
||||||
|
private JTextArea textArea = new JTextArea(20, 30);
|
||||||
|
private JScrollPane scroll = new JScrollPane(textArea,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||||
|
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
|
||||||
|
|
||||||
|
public InputMultiEditor() {
|
||||||
|
super();
|
||||||
|
scroll.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
|
||||||
|
textArea.addCaretListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void caretUpdate(CaretEvent arg0) {
|
||||||
|
currentTestCase.getInput().setScript(getText());
|
||||||
|
listCases.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return textArea.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(String text) {
|
||||||
|
textArea.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public JComponent getView() {
|
||||||
|
return scroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class InputFileEditor extends InputStringEditor {};
|
||||||
|
|
||||||
|
public class OutputResultEditor extends JPanel implements ActionListener {
|
||||||
|
|
||||||
|
private JToggleButton tbFail, tbOk;
|
||||||
|
|
||||||
|
public OutputResultEditor() {
|
||||||
|
super();
|
||||||
|
|
||||||
|
tbFail = new JToggleButton("Fail");
|
||||||
|
tbOk = new JToggleButton("OK");
|
||||||
|
ButtonGroup group = new ButtonGroup();
|
||||||
|
group.add(tbFail);
|
||||||
|
group.add(tbOk);
|
||||||
|
|
||||||
|
this.add(tbFail);
|
||||||
|
this.add(tbOk);
|
||||||
|
|
||||||
|
this.tbFail.addActionListener(this);
|
||||||
|
this.tbOk.addActionListener(this);
|
||||||
|
|
||||||
|
this.setPreferredSize(
|
||||||
|
new Dimension(TEST_EDITOR_WIDTH, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
TestCaseOutputResult output =
|
||||||
|
(TestCaseOutputResult) currentTestCase.getOutput();
|
||||||
|
|
||||||
|
if(e.getSource() == tbFail) {
|
||||||
|
output.setScript(false);
|
||||||
|
} else {
|
||||||
|
output.setScript(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
listCases.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setValue(String value) {
|
||||||
|
if(TestCaseOutputResult.OK.equals(value)) {
|
||||||
|
this.tbOk.setSelected(true);
|
||||||
|
} else {
|
||||||
|
this.tbFail.setSelected(true);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class OutputAstEditor implements CaretListener {
|
||||||
|
private JTextArea textArea = new JTextArea(20, 30);
|
||||||
|
private JScrollPane scroll = new JScrollPane(textArea,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||||
|
JScrollPane.HORIZONTAL_SCROLLBAR_ALWAYS);
|
||||||
|
|
||||||
|
public OutputAstEditor() {
|
||||||
|
super();
|
||||||
|
scroll.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
|
||||||
|
textArea.addCaretListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void caretUpdate(CaretEvent arg0) {
|
||||||
|
currentTestCase.getOutput().setScript(getText());
|
||||||
|
listCases.updateUI();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setText(String text) {
|
||||||
|
this.textArea.setText(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getText() {
|
||||||
|
return this.textArea.getText();
|
||||||
|
}
|
||||||
|
|
||||||
|
public JScrollPane getView() {
|
||||||
|
return this.scroll;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public class OutputStdEditor extends OutputAstEditor {}
|
||||||
|
public class OutputReturnEditor extends OutputAstEditor {}
|
||||||
|
|
||||||
|
/* EVENT HANDLERS */
|
||||||
|
|
||||||
|
private class TestCaseListSelectionListener implements ListSelectionListener {
|
||||||
|
|
||||||
|
public void valueChanged(ListSelectionEvent e) {
|
||||||
|
|
||||||
|
if(e.getValueIsAdjusting()) return;
|
||||||
|
final JList list = (JList) e.getSource();
|
||||||
|
final TestCase value = (TestCase) list.getSelectedValue();
|
||||||
|
if(value != null) OnTestCaseSelected(value);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ACTIONS */
|
||||||
|
|
||||||
|
private class AddTestCaseAction extends AbstractAction {
|
||||||
|
public AddTestCaseAction() {
|
||||||
|
super("Add", ImageFactory.getSingleton().ADD);
|
||||||
|
putValue(SHORT_DESCRIPTION, "Add a gUnit test case.");
|
||||||
|
}
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
OnAddTestCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class RemoveTestCaseAction extends AbstractAction {
|
||||||
|
public RemoveTestCaseAction() {
|
||||||
|
super("Remove", ImageFactory.getSingleton().DELETE);
|
||||||
|
putValue(SHORT_DESCRIPTION, "Remove a gUnit test case.");
|
||||||
|
}
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
OnRemoveTestCase();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* CELL RENDERERS */
|
||||||
|
|
||||||
|
private static TestCaseListRenderer listRenderer
|
||||||
|
= new TestCaseListRenderer();
|
||||||
|
|
||||||
|
private static class TestCaseListRenderer implements ListCellRenderer {
|
||||||
|
|
||||||
|
private static Font IN_FONT = new Font("mono", Font.PLAIN, 12);
|
||||||
|
private static Font OUT_FONT = new Font("default", Font.BOLD, 12);
|
||||||
|
|
||||||
|
public static String clamp(String text, int len) {
|
||||||
|
if(text.length() > len) {
|
||||||
|
return text.substring(0, len - 3).concat("...");
|
||||||
|
} else {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String clampAtNewLine(String text) {
|
||||||
|
int pos = text.indexOf('\n');
|
||||||
|
if(pos >= 0) {
|
||||||
|
return text.substring(0, pos).concat("...");
|
||||||
|
} else {
|
||||||
|
return text;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getListCellRendererComponent(
|
||||||
|
JList list, Object value, int index,
|
||||||
|
boolean isSelected, boolean hasFocus) {
|
||||||
|
|
||||||
|
final JPanel pane = new JPanel();
|
||||||
|
|
||||||
|
if (value instanceof TestCase) {
|
||||||
|
final TestCase item = (TestCase) value;
|
||||||
|
|
||||||
|
// create components
|
||||||
|
final JLabel labIn = new JLabel(
|
||||||
|
clamp(clampAtNewLine(item.getInput().getScript()), 18));
|
||||||
|
final JLabel labOut = new JLabel(
|
||||||
|
clamp(clampAtNewLine(item.getOutput().getScript()), 18));
|
||||||
|
labOut.setFont(OUT_FONT);
|
||||||
|
labIn.setFont(IN_FONT);
|
||||||
|
|
||||||
|
labIn.setIcon(item.getInput() instanceof TestCaseInputFile ?
|
||||||
|
ImageFactory.getSingleton().FILE16 :
|
||||||
|
ImageFactory.getSingleton().EDIT16);
|
||||||
|
|
||||||
|
pane.setBorder(BorderFactory.createEtchedBorder());
|
||||||
|
pane.setLayout(new BoxLayout(pane, BoxLayout.Y_AXIS));
|
||||||
|
pane.add(labIn);
|
||||||
|
pane.add(labOut);
|
||||||
|
pane.setBackground(isSelected ? Color.LIGHT_GRAY : Color.WHITE);
|
||||||
|
}
|
||||||
|
|
||||||
|
return pane;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,61 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import javax.swing.SwingUtilities;
|
||||||
|
import javax.swing.UIManager;
|
||||||
|
|
||||||
|
public class Tool {
|
||||||
|
|
||||||
|
public static void main(String[] args) throws IOException {
|
||||||
|
|
||||||
|
if(args.length == 1 && "-version".equals(args[0])) {
|
||||||
|
System.out.println("gUnitEditor Swing GUI\nby Shaoting Cai\n");
|
||||||
|
} else {
|
||||||
|
showUI();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void showUI() {
|
||||||
|
try {
|
||||||
|
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
SwingUtilities.invokeLater(new Runnable() {
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
WorkSpaceController control = new WorkSpaceController();
|
||||||
|
control.show();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,288 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui;
|
||||||
|
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
import org.antlr.gunit.swingui.runner.gUnitAdapter;
|
||||||
|
import java.awt.*;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.antlr.gunit.swingui.model.*;
|
||||||
|
import org.antlr.gunit.swingui.ImageFactory;
|
||||||
|
import java.awt.event.*;
|
||||||
|
import java.io.File;
|
||||||
|
import javax.swing.*;
|
||||||
|
import javax.swing.event.*;
|
||||||
|
import javax.swing.filechooser.FileFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class WorkSpaceController implements IController{
|
||||||
|
|
||||||
|
/* MODEL */
|
||||||
|
private TestSuite currentTestSuite;
|
||||||
|
private String testSuiteFileName = null; // path + file
|
||||||
|
|
||||||
|
/* VIEW */
|
||||||
|
private final WorkSpaceView view = new WorkSpaceView();
|
||||||
|
|
||||||
|
/* SUB-CONTROL */
|
||||||
|
private final RunnerController runner = new RunnerController();
|
||||||
|
|
||||||
|
public WorkSpaceController() {
|
||||||
|
view.resultPane = (JPanel) runner.getView();
|
||||||
|
view.initComponents();
|
||||||
|
this.initEventHandlers();
|
||||||
|
this.initToolbar();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void show() {
|
||||||
|
this.view.setTitle("gUnitEditor");
|
||||||
|
this.view.setVisible(true);
|
||||||
|
this.view.pack();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getEmbeddedView() {
|
||||||
|
return view.paneEditor.getView();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initEventHandlers() {
|
||||||
|
this.view.tabEditors.addChangeListener(new TabChangeListener());
|
||||||
|
this.view.listRules.setListSelectionListener(new RuleListSelectionListener());
|
||||||
|
this.view.paneEditor.onTestCaseNumberChange = new ActionListener() {
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
view.listRules.getView().updateUI();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnCreateTest() {
|
||||||
|
JFileChooser jfc = new JFileChooser();
|
||||||
|
jfc.setDialogTitle("Create test suite from grammar");
|
||||||
|
jfc.setDialogType(JFileChooser.OPEN_DIALOG);
|
||||||
|
jfc.setFileFilter(new FileFilter() {
|
||||||
|
@Override
|
||||||
|
public boolean accept(File f) {
|
||||||
|
return f.isDirectory() || f.getName().toLowerCase().endsWith(TestSuiteFactory.GRAMMAR_EXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "ANTLR grammar file (*.g)";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if( jfc.showOpenDialog(view) != JFileChooser.APPROVE_OPTION ) return;
|
||||||
|
|
||||||
|
view.paneStatus.setProgressIndetermined(true);
|
||||||
|
final File grammarFile = jfc.getSelectedFile();
|
||||||
|
|
||||||
|
currentTestSuite = TestSuiteFactory.createTestSuite(grammarFile);
|
||||||
|
|
||||||
|
view.listRules.initialize(currentTestSuite);
|
||||||
|
view.tabEditors.setSelectedIndex(0);
|
||||||
|
view.paneStatus.setText("Grammar: " + currentTestSuite.getGrammarName());
|
||||||
|
view.paneStatus.setProgressIndetermined(false);
|
||||||
|
|
||||||
|
testSuiteFileName = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSaveTest() {
|
||||||
|
TestSuiteFactory.saveTestSuite(currentTestSuite);
|
||||||
|
JOptionPane.showMessageDialog(view, "Testsuite saved to:\n" + currentTestSuite.getTestSuiteFile().getAbsolutePath());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnOpenTest() {
|
||||||
|
|
||||||
|
JFileChooser jfc = new JFileChooser();
|
||||||
|
jfc.setDialogTitle("Open existing gUnit test suite");
|
||||||
|
jfc.setDialogType(JFileChooser.OPEN_DIALOG);
|
||||||
|
jfc.setFileFilter(new FileFilter() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean accept(File f) {
|
||||||
|
return f.isDirectory() || f.getName().toLowerCase().endsWith(TestSuiteFactory.TEST_SUITE_EXT);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getDescription() {
|
||||||
|
return "ANTLR unit test file (*.gunit)";
|
||||||
|
}
|
||||||
|
});
|
||||||
|
if( jfc.showOpenDialog(view) != JFileChooser.APPROVE_OPTION ) return;
|
||||||
|
|
||||||
|
final File testSuiteFile = jfc.getSelectedFile();
|
||||||
|
try {
|
||||||
|
testSuiteFileName = testSuiteFile.getCanonicalPath();
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
view.paneStatus.setProgressIndetermined(true);
|
||||||
|
|
||||||
|
currentTestSuite = TestSuiteFactory.loadTestSuite(testSuiteFile);
|
||||||
|
view.listRules.initialize(currentTestSuite);
|
||||||
|
view.paneStatus.setText(currentTestSuite.getGrammarName());
|
||||||
|
view.tabEditors.setSelectedIndex(0);
|
||||||
|
|
||||||
|
view.paneStatus.setProgressIndetermined(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSelectRule(Rule rule) {
|
||||||
|
if(rule == null) throw new IllegalArgumentException("Null");
|
||||||
|
this.view.paneEditor.OnLoadRule(rule);
|
||||||
|
this.view.paneStatus.setRule(rule.getName());
|
||||||
|
|
||||||
|
// run result
|
||||||
|
this.runner.OnShowRuleResult(rule);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnSelectTextPane() {
|
||||||
|
Thread worker = new Thread () {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
view.paneStatus.setProgressIndetermined(true);
|
||||||
|
view.txtEditor.setText(
|
||||||
|
TestSuiteFactory.getScript(currentTestSuite));
|
||||||
|
view.paneStatus.setProgressIndetermined(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
worker.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnRunTest() {
|
||||||
|
// save before run
|
||||||
|
TestSuiteFactory.saveTestSuite(currentTestSuite);
|
||||||
|
|
||||||
|
// run
|
||||||
|
try {
|
||||||
|
final gUnitAdapter adapter = new gUnitAdapter(currentTestSuite);
|
||||||
|
if(currentTestSuite == null) return;
|
||||||
|
adapter.run();
|
||||||
|
|
||||||
|
runner.OnShowSuiteResult(currentTestSuite);
|
||||||
|
view.tabEditors.addTab("Test Result", ImageFactory.getSingleton().FILE16, runner.getView());
|
||||||
|
view.tabEditors.setSelectedComponent(runner.getView());
|
||||||
|
} catch (Exception ex) {
|
||||||
|
JOptionPane.showMessageDialog(view, "Fail to run test:\n" + ex.getMessage(), "Error", JOptionPane.ERROR_MESSAGE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private void initToolbar() {
|
||||||
|
view.toolbar.add(new JButton(new CreateAction()));
|
||||||
|
view.toolbar.add(new JButton(new OpenAction()));
|
||||||
|
view.toolbar.add(new JButton(new SaveAction()));
|
||||||
|
view.toolbar.add(new JButton(new RunAction()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public Object getModel() {
|
||||||
|
throw new UnsupportedOperationException("Not supported yet.");
|
||||||
|
}
|
||||||
|
|
||||||
|
public Component getView() {
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Event handler for rule list selection. */
|
||||||
|
private class RuleListSelectionListener implements ListSelectionListener {
|
||||||
|
public void valueChanged(ListSelectionEvent event) {
|
||||||
|
if(event.getValueIsAdjusting()) return;
|
||||||
|
final JList list = (JList) event.getSource();
|
||||||
|
final Rule rule = (Rule) list.getSelectedValue();
|
||||||
|
if(rule != null) OnSelectRule(rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Event handler for switching between editor view and script view. */
|
||||||
|
public class TabChangeListener implements ChangeListener {
|
||||||
|
public void stateChanged(ChangeEvent evt) {
|
||||||
|
if(view.tabEditors.getSelectedIndex() == 1) {
|
||||||
|
OnSelectTextPane();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Create test suite action. */
|
||||||
|
private class CreateAction extends AbstractAction {
|
||||||
|
public CreateAction() {
|
||||||
|
super("Create", ImageFactory.getSingleton().ADDFILE);
|
||||||
|
putValue(SHORT_DESCRIPTION, "Create a test suite from an ANTLR grammar");
|
||||||
|
}
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
OnCreateTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Save test suite action. */
|
||||||
|
private class SaveAction extends AbstractAction {
|
||||||
|
public SaveAction() {
|
||||||
|
super("Save", ImageFactory.getSingleton().SAVE);
|
||||||
|
putValue(SHORT_DESCRIPTION, "Save the test suite");
|
||||||
|
}
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
OnSaveTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** Open test suite action. */
|
||||||
|
private class OpenAction extends AbstractAction {
|
||||||
|
public OpenAction() {
|
||||||
|
super("Open", ImageFactory.getSingleton().OPEN);
|
||||||
|
putValue(SHORT_DESCRIPTION, "Open an existing test suite");
|
||||||
|
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(
|
||||||
|
KeyEvent.VK_O, InputEvent.CTRL_MASK));
|
||||||
|
}
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
OnOpenTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Run test suite action. */
|
||||||
|
private class RunAction extends AbstractAction {
|
||||||
|
public RunAction() {
|
||||||
|
super("Run", ImageFactory.getSingleton().NEXT);
|
||||||
|
putValue(SHORT_DESCRIPTION, "Run the current test suite");
|
||||||
|
putValue(ACCELERATOR_KEY, KeyStroke.getKeyStroke(
|
||||||
|
KeyEvent.VK_R, InputEvent.CTRL_MASK));
|
||||||
|
}
|
||||||
|
public void actionPerformed(ActionEvent e) {
|
||||||
|
OnRunTest();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,103 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* To change this template, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.antlr.gunit.swingui;
|
||||||
|
|
||||||
|
import org.antlr.gunit.swingui.ImageFactory;
|
||||||
|
import java.awt.*;
|
||||||
|
import javax.swing.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class WorkSpaceView extends JFrame {
|
||||||
|
|
||||||
|
protected JSplitPane splitListClient ;
|
||||||
|
protected JTabbedPane tabEditors;
|
||||||
|
protected JPanel paneToolBar;
|
||||||
|
protected StatusBarController paneStatus;
|
||||||
|
protected TestCaseEditController paneEditor;
|
||||||
|
protected JToolBar toolbar;
|
||||||
|
protected JTextArea txtEditor;
|
||||||
|
protected RuleListController listRules;
|
||||||
|
protected JMenuBar menuBar;
|
||||||
|
protected JScrollPane scrollCode;
|
||||||
|
protected JPanel resultPane;
|
||||||
|
|
||||||
|
protected JButton btnOpenGrammar;
|
||||||
|
|
||||||
|
public WorkSpaceView() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void initComponents() {
|
||||||
|
|
||||||
|
this.paneEditor = new TestCaseEditController(this);
|
||||||
|
this.paneStatus = new StatusBarController();
|
||||||
|
|
||||||
|
this.toolbar = new JToolBar();
|
||||||
|
this.toolbar.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
this.toolbar.setFloatable(false);
|
||||||
|
this.toolbar.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
|
||||||
|
this.txtEditor = new JTextArea();
|
||||||
|
this.txtEditor.setLineWrap(false);
|
||||||
|
this.txtEditor.setFont(new Font("Courier New", Font.PLAIN, 13));
|
||||||
|
this.scrollCode = new JScrollPane(txtEditor,
|
||||||
|
JScrollPane.VERTICAL_SCROLLBAR_ALWAYS,
|
||||||
|
JScrollPane.HORIZONTAL_SCROLLBAR_AS_NEEDED);
|
||||||
|
this.scrollCode.setBorder(BorderFactory.createLineBorder(Color.LIGHT_GRAY));
|
||||||
|
|
||||||
|
this.tabEditors = new JTabbedPane();
|
||||||
|
this.tabEditors.addTab("Case Editor", ImageFactory.getSingleton().TEXTFILE16, this.paneEditor.getView());
|
||||||
|
this.tabEditors.addTab("Script Source", ImageFactory.getSingleton().WINDOW16, this.scrollCode);
|
||||||
|
|
||||||
|
this.listRules = new RuleListController();
|
||||||
|
|
||||||
|
this.splitListClient = new JSplitPane( JSplitPane.HORIZONTAL_SPLIT,
|
||||||
|
this.listRules.getView(), this.tabEditors);
|
||||||
|
this.splitListClient.setResizeWeight(0.4);
|
||||||
|
this.splitListClient.setBorder(BorderFactory.createEmptyBorder());
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
this.getContentPane().add(this.toolbar, BorderLayout.NORTH);
|
||||||
|
this.getContentPane().add(this.splitListClient, BorderLayout.CENTER);
|
||||||
|
this.getContentPane().add(this.paneStatus.getView(), BorderLayout.SOUTH);
|
||||||
|
|
||||||
|
// self
|
||||||
|
this.setPreferredSize(new Dimension(900, 500));
|
||||||
|
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
public interface ITestCaseInput {
|
||||||
|
|
||||||
|
public void setScript(String script);
|
||||||
|
public String getScript();
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
* To change this template, choose Tools | Templates
|
||||||
|
* and open the template in the editor.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.antlr.gunit.swingui.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public interface ITestCaseOutput {
|
||||||
|
public void setScript(String script);
|
||||||
|
public String getScript() ;
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.swing.DefaultListModel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* ANTLR v3 Rule Information.
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class Rule extends DefaultListModel {
|
||||||
|
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
public Rule(String name) {
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getName() { return name; }
|
||||||
|
|
||||||
|
public boolean getNotEmpty() {
|
||||||
|
return !this.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return this.name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTestCase(TestCase newItem) {
|
||||||
|
this.addElement(newItem);
|
||||||
|
}
|
||||||
|
|
||||||
|
// for string template
|
||||||
|
public List<TestCase> getTestCases() {
|
||||||
|
List<TestCase> result = new ArrayList<TestCase>();
|
||||||
|
for(int i=0; i<this.size(); i++) {
|
||||||
|
result.add((TestCase)this.getElementAt(i));
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
public class TestCase {
|
||||||
|
|
||||||
|
private ITestCaseInput input;
|
||||||
|
private ITestCaseOutput output;
|
||||||
|
private boolean pass;
|
||||||
|
|
||||||
|
public boolean isPass() {
|
||||||
|
return pass;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setPass(boolean value) {
|
||||||
|
pass = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITestCaseInput getInput() {
|
||||||
|
return this.input;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ITestCaseOutput getOutput() {
|
||||||
|
return this.output;
|
||||||
|
}
|
||||||
|
|
||||||
|
public TestCase(ITestCaseInput input, ITestCaseOutput output) {
|
||||||
|
this.input = input;
|
||||||
|
this.output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format("[%s]->[%s]", input.getScript(), output.getScript());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setInput(ITestCaseInput in) {
|
||||||
|
this.input = in;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setOutput(ITestCaseOutput out) {
|
||||||
|
this.output = out;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static String convertPreservedChars(String input) {
|
||||||
|
//return input.replace("\"", "\\\"");
|
||||||
|
return input;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,62 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
import javax.swing.JComponent;
|
||||||
|
import javax.swing.JLabel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class TestCaseInputFile implements ITestCaseInput {
|
||||||
|
|
||||||
|
private String fileName;
|
||||||
|
|
||||||
|
public TestCaseInputFile(String file) {
|
||||||
|
this.fileName = file;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getLabel() {
|
||||||
|
return "FILE:" + fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScript(String script) {
|
||||||
|
this.fileName = script;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScript() {
|
||||||
|
return this.fileName;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class TestCaseInputMultiString implements ITestCaseInput {
|
||||||
|
|
||||||
|
private String script;
|
||||||
|
|
||||||
|
public TestCaseInputMultiString(String text) {
|
||||||
|
this.script = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "<<" + TestCase.convertPreservedChars(script) + ">>";
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScript(String script) {
|
||||||
|
this.script = script;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScript() {
|
||||||
|
return this.script;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class TestCaseInputString implements ITestCaseInput {
|
||||||
|
|
||||||
|
private String script;
|
||||||
|
|
||||||
|
public TestCaseInputString(String text) {
|
||||||
|
this.script = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return '"' + TestCase.convertPreservedChars(script) + '"';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
public void setScript(String script) {
|
||||||
|
this.script = script;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScript() {
|
||||||
|
return this.script;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,57 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class TestCaseOutputAST implements ITestCaseOutput {
|
||||||
|
|
||||||
|
private String treeString;
|
||||||
|
|
||||||
|
public TestCaseOutputAST(String script) {
|
||||||
|
this.treeString = script;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScript(String script) {
|
||||||
|
this.treeString = script;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScript() {
|
||||||
|
return this.treeString;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format(" -> %s", treeString);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,63 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class TestCaseOutputResult implements ITestCaseOutput {
|
||||||
|
|
||||||
|
public static String OK = "OK";
|
||||||
|
public static String FAIL = "FAIL";
|
||||||
|
|
||||||
|
private boolean success ;
|
||||||
|
|
||||||
|
public TestCaseOutputResult(boolean result) {
|
||||||
|
this.success = result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getScript();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScript() {
|
||||||
|
return success ? OK : FAIL;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScript(boolean value) {
|
||||||
|
this.success = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScript(String script) {
|
||||||
|
success = Boolean.parseBoolean(script);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
public class TestCaseOutputReturn implements ITestCaseOutput {
|
||||||
|
private String script;
|
||||||
|
|
||||||
|
public TestCaseOutputReturn(String text) {
|
||||||
|
this.script = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format(" returns [%s]", script);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScript(String script) {
|
||||||
|
this.script = script;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScript() {
|
||||||
|
return this.script;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class TestCaseOutputStdOut implements ITestCaseOutput {
|
||||||
|
private String script;
|
||||||
|
|
||||||
|
public TestCaseOutputStdOut(String text) {
|
||||||
|
this.script = text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return String.format(" -> \"%s\"", script);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setScript(String script) {
|
||||||
|
this.script = script;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getScript() {
|
||||||
|
return this.script;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,100 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.*;
|
||||||
|
import org.antlr.runtime.*;
|
||||||
|
|
||||||
|
public class TestSuite {
|
||||||
|
|
||||||
|
protected List<Rule> rules ;
|
||||||
|
protected String grammarName ;
|
||||||
|
protected CommonTokenStream tokens;
|
||||||
|
protected File testSuiteFile;
|
||||||
|
|
||||||
|
protected TestSuite(String gname, File testFile) {
|
||||||
|
grammarName = gname;
|
||||||
|
testSuiteFile = testFile;
|
||||||
|
rules = new ArrayList<Rule>();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Get the gUnit test suite file name. */
|
||||||
|
public File getTestSuiteFile() {
|
||||||
|
return testSuiteFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRule(Rule currentRule) {
|
||||||
|
if(currentRule == null) throw new IllegalArgumentException("Null rule");
|
||||||
|
rules.add(currentRule);
|
||||||
|
}
|
||||||
|
|
||||||
|
// test rule name
|
||||||
|
public boolean hasRule(Rule rule) {
|
||||||
|
for(Rule r: rules) {
|
||||||
|
if(r.getName().equals(rule.getName())) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getRuleCount() {
|
||||||
|
return rules.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setRules(List<Rule> newRules) {
|
||||||
|
rules.clear();
|
||||||
|
rules.addAll(newRules);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* GETTERS AND SETTERS */
|
||||||
|
|
||||||
|
public void setGrammarName(String name) { grammarName = name;}
|
||||||
|
|
||||||
|
public String getGrammarName() { return grammarName; }
|
||||||
|
|
||||||
|
public Rule getRule(int index) { return rules.get(index); }
|
||||||
|
|
||||||
|
public CommonTokenStream getTokens() { return tokens; }
|
||||||
|
|
||||||
|
public void setTokens(CommonTokenStream ts) { tokens = ts; }
|
||||||
|
|
||||||
|
public Rule getRule(String name) {
|
||||||
|
for(Rule rule: rules) {
|
||||||
|
if(rule.getName().equals(name)) {
|
||||||
|
return rule;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
// only for stringtemplate use
|
||||||
|
public List<Rule> getRulesForStringTemplate() {return rules;}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,209 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.model;
|
||||||
|
|
||||||
|
import org.antlr.gunit.swingui.parsers.ANTLRv3Lexer;
|
||||||
|
import org.antlr.gunit.swingui.parsers.ANTLRv3Parser;
|
||||||
|
import org.antlr.gunit.swingui.parsers.StGUnitLexer;
|
||||||
|
import org.antlr.gunit.swingui.parsers.StGUnitParser;
|
||||||
|
import org.antlr.gunit.swingui.runner.TestSuiteAdapter;
|
||||||
|
import org.antlr.runtime.ANTLRReaderStream;
|
||||||
|
import org.antlr.runtime.CommonTokenStream;
|
||||||
|
import org.antlr.stringtemplate.StringTemplate;
|
||||||
|
import org.antlr.stringtemplate.StringTemplateGroup;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class TestSuiteFactory {
|
||||||
|
|
||||||
|
private static String TEMPLATE_FILE = "org/antlr/gunit/swingui/gunit.stg";
|
||||||
|
private static StringTemplateGroup templates;
|
||||||
|
public static final String TEST_SUITE_EXT = ".gunit";
|
||||||
|
public static final String GRAMMAR_EXT = ".g";
|
||||||
|
|
||||||
|
static {
|
||||||
|
ClassLoader loader = TestSuiteFactory.class.getClassLoader();
|
||||||
|
InputStream in = loader.getResourceAsStream(TEMPLATE_FILE);
|
||||||
|
if ( in == null ) {
|
||||||
|
throw new RuntimeException("internal error: Can't find templates "+TEMPLATE_FILE);
|
||||||
|
}
|
||||||
|
Reader rd = new InputStreamReader(in);
|
||||||
|
templates = new StringTemplateGroup(rd);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Factory method: create a testsuite from ANTLR grammar. Save the test
|
||||||
|
* suite file in the same directory of the grammar file.
|
||||||
|
* @param grammarFile ANTLRv3 grammar file.
|
||||||
|
* @return test suite object
|
||||||
|
*/
|
||||||
|
public static TestSuite createTestSuite(File grammarFile) {
|
||||||
|
if(grammarFile != null && grammarFile.exists() && grammarFile.isFile()) {
|
||||||
|
|
||||||
|
final String fileName = grammarFile.getName();
|
||||||
|
final String grammarName = fileName.substring(0, fileName.lastIndexOf('.'));
|
||||||
|
final String grammarDir = grammarFile.getParent();
|
||||||
|
final File testFile = new File(grammarDir + File.separator + grammarName + TEST_SUITE_EXT);
|
||||||
|
|
||||||
|
final TestSuite result = new TestSuite(grammarName, testFile);
|
||||||
|
result.rules = loadRulesFromGrammar(grammarFile);
|
||||||
|
|
||||||
|
if(saveTestSuite(result)) {
|
||||||
|
return result;
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Can't save test suite file.");
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new RuntimeException("Invalid grammar file.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Load rules from an ANTLR grammar file. */
|
||||||
|
private static List<Rule> loadRulesFromGrammar(File grammarFile) {
|
||||||
|
|
||||||
|
// get all the rule names
|
||||||
|
final List<String> ruleNames = new ArrayList<String>();
|
||||||
|
try {
|
||||||
|
final Reader reader = new BufferedReader(new FileReader(grammarFile));
|
||||||
|
final ANTLRv3Lexer lexer = new ANTLRv3Lexer(new ANTLRReaderStream(reader));
|
||||||
|
final CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
final ANTLRv3Parser parser = new ANTLRv3Parser(tokens);
|
||||||
|
parser.rules = ruleNames;
|
||||||
|
parser.grammarDef();
|
||||||
|
reader.close();
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
|
||||||
|
// convert to rule object
|
||||||
|
final List<Rule> ruleList = new ArrayList<Rule>();
|
||||||
|
for(String str: ruleNames) {
|
||||||
|
ruleList.add(new Rule(str));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ruleList;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Save testsuite to *.gunit file. */
|
||||||
|
public static boolean saveTestSuite(TestSuite testSuite) {
|
||||||
|
final String data = getScript(testSuite);
|
||||||
|
try {
|
||||||
|
FileWriter fw = new FileWriter(testSuite.getTestSuiteFile());
|
||||||
|
fw.write(data);
|
||||||
|
fw.flush();
|
||||||
|
fw.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the text script from the testSuite.
|
||||||
|
* @param testSuite
|
||||||
|
* @return test script
|
||||||
|
*/
|
||||||
|
public static String getScript(TestSuite testSuite) {
|
||||||
|
if(testSuite == null) return null;
|
||||||
|
StringTemplate gUnitScript = templates.getInstanceOf("gUnitFile");
|
||||||
|
gUnitScript.setAttribute("testSuite", testSuite);
|
||||||
|
|
||||||
|
return gUnitScript.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* From textual script to program model.
|
||||||
|
* @param file testsuite file (.gunit)
|
||||||
|
* @return test suite object
|
||||||
|
*/
|
||||||
|
public static TestSuite loadTestSuite(File file) {
|
||||||
|
if ( file.getName().endsWith(GRAMMAR_EXT) ) {
|
||||||
|
throw new RuntimeException(file.getName()+" is a grammar file not a gunit file");
|
||||||
|
}
|
||||||
|
// check grammar file
|
||||||
|
final File grammarFile = getGrammarFile(file);
|
||||||
|
if(grammarFile == null)
|
||||||
|
throw new RuntimeException("Can't find grammar file associated with gunit file: "+file.getAbsoluteFile());
|
||||||
|
|
||||||
|
TestSuite result = new TestSuite("", file);
|
||||||
|
|
||||||
|
// read in test suite
|
||||||
|
try {
|
||||||
|
final Reader reader = new BufferedReader(new FileReader(file));
|
||||||
|
final StGUnitLexer lexer = new StGUnitLexer(new ANTLRReaderStream(reader));
|
||||||
|
final CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
final StGUnitParser parser = new StGUnitParser(tokens);
|
||||||
|
final TestSuiteAdapter adapter = new TestSuiteAdapter(result);
|
||||||
|
parser.adapter = adapter;
|
||||||
|
parser.gUnitDef();
|
||||||
|
result.setTokens(tokens);
|
||||||
|
reader.close();
|
||||||
|
} catch (Exception ex) {
|
||||||
|
throw new RuntimeException("Error reading test suite file.\n" + ex.getMessage());
|
||||||
|
}
|
||||||
|
|
||||||
|
// load un-tested rules from grammar
|
||||||
|
final List<Rule> completeRuleList = loadRulesFromGrammar(grammarFile);
|
||||||
|
for(Rule rule: completeRuleList) {
|
||||||
|
if(!result.hasRule(rule)) {
|
||||||
|
result.addRule(rule);
|
||||||
|
//System.out.println("Add rule:" + rule);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the grammar file of the testsuite file in the same directory.
|
||||||
|
* @param testsuiteFile
|
||||||
|
* @return grammar file or null
|
||||||
|
*/
|
||||||
|
private static File getGrammarFile(File testsuiteFile) {
|
||||||
|
String sTestFile;
|
||||||
|
try {
|
||||||
|
sTestFile = testsuiteFile.getCanonicalPath();
|
||||||
|
}
|
||||||
|
catch (IOException e) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
// Try Foo.g from Foo.gunit
|
||||||
|
String fname =
|
||||||
|
sTestFile.substring(0, sTestFile.lastIndexOf('.')) + GRAMMAR_EXT;
|
||||||
|
File fileGrammar = new File(fname);
|
||||||
|
if(fileGrammar.exists() && fileGrammar.isFile()) return fileGrammar;
|
||||||
|
// Try FooParser.g from Foo.gunit
|
||||||
|
fname = sTestFile.substring(0, sTestFile.lastIndexOf('.'))+"Parser"+GRAMMAR_EXT;
|
||||||
|
if(fileGrammar.exists() && fileGrammar.isFile()) return fileGrammar;
|
||||||
|
return fileGrammar;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,73 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.runner;
|
||||||
|
|
||||||
|
import org.antlr.gunit.*;
|
||||||
|
import org.antlr.gunit.swingui.model.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The gUnit test executer that will respond to the fail/pass event during the
|
||||||
|
* execution. The executer is passed into gUnit Interp for execution.
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class NotifiedTestExecuter extends gUnitExecutor {
|
||||||
|
|
||||||
|
private TestSuite testSuite ;
|
||||||
|
|
||||||
|
public NotifiedTestExecuter(GrammarInfo grammarInfo, ClassLoader loader, String testsuiteDir, TestSuite suite) {
|
||||||
|
super(grammarInfo, loader, testsuiteDir);
|
||||||
|
|
||||||
|
testSuite = suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onFail(ITestCase failTest) {
|
||||||
|
if(failTest == null) throw new IllegalArgumentException("Null fail test");
|
||||||
|
|
||||||
|
final String ruleName = failTest.getTestedRuleName();
|
||||||
|
if(ruleName == null) throw new NullPointerException("Null rule name");
|
||||||
|
|
||||||
|
final Rule rule = testSuite.getRule(ruleName);
|
||||||
|
final TestCase failCase = (TestCase) rule.getElementAt(failTest.getTestCaseIndex());
|
||||||
|
failCase.setPass(false);
|
||||||
|
//System.out.println(String.format("[FAIL] %s (%d) ", failTest.getTestedRuleName(), failTest.getTestCaseIndex()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPass(ITestCase passTest) {
|
||||||
|
if(passTest == null) throw new IllegalArgumentException("Null pass test");
|
||||||
|
|
||||||
|
final String ruleName = passTest.getTestedRuleName();
|
||||||
|
if(ruleName == null) throw new NullPointerException("Null rule name");
|
||||||
|
|
||||||
|
final Rule rule = testSuite.getRule(ruleName);
|
||||||
|
final TestCase passCase = (TestCase) rule.getElementAt(passTest.getTestCaseIndex());
|
||||||
|
passCase.setPass(true);
|
||||||
|
//System.out.println(String.format("[PASS] %s (%d) ", passTest.getTestedRuleName(), passTest.getTestCaseIndex()));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,124 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.runner;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class loader for parser & lexer generated by antlr.
|
||||||
|
* @author Shaoting
|
||||||
|
*/
|
||||||
|
public class ParserLoader extends ClassLoader {
|
||||||
|
|
||||||
|
private HashMap<String, Class<?>> classList;
|
||||||
|
private String grammar;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create a class loader for antlr parser/lexer.
|
||||||
|
* @param grammarName
|
||||||
|
* @param classDir
|
||||||
|
*/
|
||||||
|
public ParserLoader(String grammarName, String classDir) throws IOException, ClassNotFoundException {
|
||||||
|
|
||||||
|
final String lexerName = grammarName + "Lexer";
|
||||||
|
|
||||||
|
// load all the class files in the "classDir" related to the grammarName
|
||||||
|
File dir = new File(classDir);
|
||||||
|
if(dir.isDirectory()) {
|
||||||
|
classList = new HashMap<String, Class<?>>();
|
||||||
|
grammar = grammarName;
|
||||||
|
File[] files = dir.listFiles(new ClassFilenameFilter(grammarName));
|
||||||
|
for(File f : files) {
|
||||||
|
|
||||||
|
// load class data
|
||||||
|
final InputStream in = new BufferedInputStream(new FileInputStream(f));
|
||||||
|
final byte[] classData = new byte[in.available()];
|
||||||
|
in.read(classData);
|
||||||
|
in.close();
|
||||||
|
|
||||||
|
// define class
|
||||||
|
final Class<?> newClass = defineClass(null, classData, 0, classData.length);
|
||||||
|
assert(newClass != null);
|
||||||
|
resolveClass(newClass);
|
||||||
|
|
||||||
|
// save to hashtable
|
||||||
|
final String fileName = f.getName();
|
||||||
|
final String className = fileName.substring(0, fileName.lastIndexOf("."));
|
||||||
|
classList.put(className, newClass);
|
||||||
|
//System.out.println("adding: " + className);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
throw new IOException(classDir + " is not a directory.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if(classList.isEmpty() || !classList.containsKey(lexerName)) {
|
||||||
|
throw new ClassNotFoundException(lexerName + " not found.");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||||
|
//System.out.print("loading: " + name);
|
||||||
|
if(name.startsWith(grammar)) {
|
||||||
|
if(classList.containsKey(name)) {
|
||||||
|
//System.out.println(" .... found");
|
||||||
|
return classList.get(name);
|
||||||
|
} else {
|
||||||
|
//System.out.println(" .... not found");
|
||||||
|
throw new ClassNotFoundException(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
final Class<?> c = findSystemClass(name);
|
||||||
|
//System.out.println(" .... system found " + c.getName());
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Accepts grammarname...($...)?.class
|
||||||
|
*/
|
||||||
|
protected static class ClassFilenameFilter implements FilenameFilter {
|
||||||
|
|
||||||
|
private String grammarName;
|
||||||
|
|
||||||
|
protected ClassFilenameFilter(String name) {
|
||||||
|
grammarName = name;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean accept(File dir, String name) {
|
||||||
|
return name.startsWith(grammarName) && name.endsWith(".class");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,104 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.runner;
|
||||||
|
|
||||||
|
import org.antlr.gunit.swingui.model.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter class for gunit parser to save information into testsuite object.
|
||||||
|
* @author Shaoting
|
||||||
|
*/
|
||||||
|
public class TestSuiteAdapter {
|
||||||
|
|
||||||
|
private TestSuite model ;
|
||||||
|
private Rule currentRule;
|
||||||
|
|
||||||
|
public TestSuiteAdapter(TestSuite testSuite) {
|
||||||
|
model = testSuite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setGrammarName(String name) {
|
||||||
|
model.setGrammarName(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void startRule(String name) {
|
||||||
|
currentRule = new Rule(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void endRule() {
|
||||||
|
model.addRule(currentRule);
|
||||||
|
currentRule = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addTestCase(ITestCaseInput in, ITestCaseOutput out) {
|
||||||
|
TestCase testCase = new TestCase(in, out);
|
||||||
|
currentRule.addTestCase(testCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String trimChars(String text, int numOfChars) {
|
||||||
|
return text.substring(numOfChars, text.length() - numOfChars);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ITestCaseInput createFileInput(String fileName) {
|
||||||
|
if(fileName == null) throw new IllegalArgumentException("null");
|
||||||
|
return new TestCaseInputFile(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ITestCaseInput createStringInput(String line) {
|
||||||
|
if(line == null) throw new IllegalArgumentException("null");
|
||||||
|
// trim double quotes
|
||||||
|
return new TestCaseInputString(trimChars(line, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ITestCaseInput createMultiInput(String text) {
|
||||||
|
if(text == null) throw new IllegalArgumentException("null");
|
||||||
|
// trim << and >>
|
||||||
|
return new TestCaseInputMultiString(trimChars(text, 2));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ITestCaseOutput createBoolOutput(boolean bool) {
|
||||||
|
return new TestCaseOutputResult(bool);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ITestCaseOutput createAstOutput(String ast) {
|
||||||
|
if(ast == null) throw new IllegalArgumentException("null");
|
||||||
|
return new TestCaseOutputAST(ast);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ITestCaseOutput createStdOutput(String text) {
|
||||||
|
if(text == null) throw new IllegalArgumentException("null");
|
||||||
|
// trim double quotes
|
||||||
|
return new TestCaseOutputStdOut(trimChars(text, 1));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ITestCaseOutput createReturnOutput(String text) {
|
||||||
|
if(text == null) throw new IllegalArgumentException("null");
|
||||||
|
// trim square brackets
|
||||||
|
return new TestCaseOutputReturn(trimChars(text, 1));
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,80 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2009 Shaoting Cai
|
||||||
|
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.gunit.swingui.runner;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.IOException;
|
||||||
|
import org.antlr.runtime.*;
|
||||||
|
import org.antlr.runtime.CharStream;
|
||||||
|
import org.antlr.gunit.*;
|
||||||
|
import org.antlr.gunit.swingui.model.TestSuite;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adapter between gUnitEditor Swing GUI and gUnit command-line tool.
|
||||||
|
* @author scai
|
||||||
|
*/
|
||||||
|
public class gUnitAdapter {
|
||||||
|
|
||||||
|
private ParserLoader loader ;
|
||||||
|
private TestSuite testSuite;
|
||||||
|
|
||||||
|
public gUnitAdapter(TestSuite suite) throws IOException, ClassNotFoundException {
|
||||||
|
int i = 3;
|
||||||
|
loader = new ParserLoader(suite.getGrammarName(),
|
||||||
|
suite.getTestSuiteFile().getParent());
|
||||||
|
testSuite = suite;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void run() {
|
||||||
|
if (testSuite == null)
|
||||||
|
throw new IllegalArgumentException("Null testsuite.");
|
||||||
|
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
// Parse gUnit test suite file
|
||||||
|
final CharStream input = new ANTLRFileStream(testSuite.getTestSuiteFile().getCanonicalPath());
|
||||||
|
final gUnitLexer lexer = new gUnitLexer(input);
|
||||||
|
final CommonTokenStream tokens = new CommonTokenStream(lexer);
|
||||||
|
final GrammarInfo grammarInfo = new GrammarInfo();
|
||||||
|
final gUnitParser parser = new gUnitParser(tokens, grammarInfo);
|
||||||
|
parser.gUnitDef(); // parse gunit script and save elements to grammarInfo
|
||||||
|
|
||||||
|
// Execute test suite
|
||||||
|
final gUnitExecutor executer = new NotifiedTestExecuter(
|
||||||
|
grammarInfo, loader,
|
||||||
|
testSuite.getTestSuiteFile().getParent(), testSuite);
|
||||||
|
executer.execTest();
|
||||||
|
|
||||||
|
} catch (Exception e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon, Jen-Yuan Su
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
group gUnitTestResult;
|
||||||
|
|
||||||
|
testResult(title, num_of_test, num_of_failure, failure, has_invalid, num_of_invalid, invalid) ::= <<
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
<title> with <num_of_test> tests
|
||||||
|
-----------------------------------------------------------------------
|
||||||
|
<num_of_failure> failures found:
|
||||||
|
<failure:{<it.header>
|
||||||
|
expected: <it.expectedResult>
|
||||||
|
actual: <it.actualResult>
|
||||||
|
|
||||||
|
}>
|
||||||
|
<if(has_invalid)>
|
||||||
|
<num_of_invalid> invalid inputs found:
|
||||||
|
<invalid:{<it.header>
|
||||||
|
invalid input: <it.actual>
|
||||||
|
}>
|
||||||
|
<endif>
|
||||||
|
|
||||||
|
Tests run: <num_of_test>, Failures: <num_of_failure>
|
||||||
|
|
||||||
|
>>
|
@ -0,0 +1,85 @@
|
|||||||
|
/*
|
||||||
|
[The "BSD licence"]
|
||||||
|
Copyright (c) 2007-2008 Leon, Jen-Yuan Su
|
||||||
|
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.
|
||||||
|
*/
|
||||||
|
group junit;
|
||||||
|
|
||||||
|
classHeader(header,junitFileName,hasTreeAdaptor,treeAdaptorPath,
|
||||||
|
hasPackage,packagePath,lexerPath,parserPath,treeParserPath,isTreeGrammar) ::= <<
|
||||||
|
<header>
|
||||||
|
|
||||||
|
import org.antlr.gunit.gUnitBaseTest;
|
||||||
|
|
||||||
|
public class <junitFileName> extends gUnitBaseTest {
|
||||||
|
|
||||||
|
public void setUp() {
|
||||||
|
<if(hasTreeAdaptor)><\t><\t>this.treeAdaptorPath = "<treeAdaptorPath>";<endif>
|
||||||
|
<if(hasPackage)><\t><\t>this.packagePath = "<packagePath>";<endif>
|
||||||
|
this.lexerPath = "<lexerPath>";
|
||||||
|
this.parserPath = "<parserPath>";
|
||||||
|
<if(isTreeGrammar)><\t><\t>this.treeParserPath = "<treeParserPath>";<endif>
|
||||||
|
}<\n><\n>
|
||||||
|
>>
|
||||||
|
|
||||||
|
testTreeRuleMethod(methodName,testTreeRuleName,testRuleName,test,tokenType,expecting) ::= <<
|
||||||
|
public void <methodName>() throws Exception {
|
||||||
|
// gunit test on line <test.line>
|
||||||
|
Object retval = execTreeParser(<testTreeRuleName>, <testRuleName>, "<test.inputEscaped>", <test.isFile>);
|
||||||
|
Object actual = examineExecResult(<tokenType>, retval);
|
||||||
|
Object expecting = <expecting>;
|
||||||
|
|
||||||
|
assertEquals("testing rule "+<testTreeRuleName>, expecting, actual);
|
||||||
|
}<\n><\n>
|
||||||
|
>>
|
||||||
|
|
||||||
|
testTreeRuleMethod2(methodName,testTreeRuleName,testRuleName,test,returnType,expecting) ::= <<
|
||||||
|
public void <methodName>() throws Exception {
|
||||||
|
// gunit test on line <test.line>
|
||||||
|
<returnType> retval = (<returnType>)execTreeParser(<testTreeRuleName>, <testRuleName>, "<test.inputEscaped>", <test.isFile>);
|
||||||
|
|
||||||
|
assertTrue("testing rule "+<testTreeRuleName>, <expecting>);
|
||||||
|
}<\n><\n>
|
||||||
|
>>
|
||||||
|
|
||||||
|
testRuleMethod(isLexicalRule,methodName,testRuleName,test,tokenType,expecting) ::= <<
|
||||||
|
public void <methodName>() throws Exception {
|
||||||
|
// gunit test on line <test.line>
|
||||||
|
Object retval = <if(isLexicalRule)>execLexer<else>execParser<endif>(<testRuleName>, <test.line>, "<test.inputEscaped>", <test.isFile>);
|
||||||
|
Object actual = examineExecResult(<tokenType>, retval);
|
||||||
|
Object expecting = <expecting>;
|
||||||
|
|
||||||
|
assertEquals("testing rule "+<testRuleName>, expecting, actual);
|
||||||
|
}<\n><\n>
|
||||||
|
>>
|
||||||
|
|
||||||
|
testRuleMethod2(methodName,testRuleName,test,returnType,expecting) ::= <<
|
||||||
|
public void <methodName>() throws Exception {
|
||||||
|
// gunit test on line <test.line>
|
||||||
|
<returnType> retval = (<returnType>)execParser(<testRuleName>, <test.line>, "<test.inputEscaped>", <test.isFile>);
|
||||||
|
|
||||||
|
assertTrue("testing rule "+<testRuleName>, <expecting>);
|
||||||
|
}<\n><\n>
|
||||||
|
>>
|
@ -0,0 +1,19 @@
|
|||||||
|
group gunit;
|
||||||
|
|
||||||
|
gUnitFile(testSuite) ::= <<gunit <testSuite.grammarName>;
|
||||||
|
|
||||||
|
<testSuite.rulesForStringTemplate:testGroup()>
|
||||||
|
>>
|
||||||
|
|
||||||
|
testGroup() ::= <<
|
||||||
|
<if(it.notEmpty)>
|
||||||
|
|
||||||
|
//------------------- <it.name>
|
||||||
|
<it.name>:
|
||||||
|
|
||||||
|
<it.testCases: testCase(); separator="\n\n">
|
||||||
|
|
||||||
|
<endif>
|
||||||
|
>>
|
||||||
|
|
||||||
|
testCase() ::= "<it.input> <it.output>"
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user