Merge pull request #955 from parrt/move-swing-dependency

move swing related stuff out of runtime package into org.antlr.v4.gui
This commit is contained in:
Terence Parr 2015-07-14 17:27:51 -07:00
commit b555099842
20 changed files with 446 additions and 417 deletions

View File

@ -11,14 +11,6 @@
<name>ANTLR 4 Runtime</name>
<description>The ANTLR 4 Runtime</description>
<dependencies>
<dependency>
<groupId>org.abego.treelayout</groupId>
<artifactId>org.abego.treelayout.core</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<build>
<sourceDirectory>src</sourceDirectory>
<plugins>
@ -38,7 +30,7 @@
</execution>
</executions>
</plugin>
<plugin>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>2.5.4</version>
@ -46,7 +38,7 @@
<execution>
<id>bundle-manifest</id>
<phase>process-classes</phase>
<configuration>
<configuration>
<instructions>
<Bundle-SymbolicName>org.antlr.antlr4-runtime-osgi</Bundle-SymbolicName>
<Implementation-Title>ANTLR 4 Runtime</Implementation-Title>
@ -55,37 +47,21 @@
<Implementation-Version>${project.version}</Implementation-Version>
</instructions>
</configuration>
<goals>
<goals>
<goal>manifest</goal>
</goals>
</goals>
</execution>
</executions>
</plugin>
</plugin>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<version>2.4</version>
<configuration>
<archive>
<archive>
<manifestFile>${project.build.outputDirectory}/META-INF/MANIFEST.MF</manifestFile>
</archive>
</archive>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>2.3</version>
<executions>
<execution>
<phase>package</phase>
<configuration>
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
</configuration>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -34,7 +34,6 @@ import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.ParseTreeVisitor;
import org.antlr.v4.runtime.tree.RuleNode;
import org.antlr.v4.runtime.tree.Trees;
import org.antlr.v4.runtime.tree.gui.TreeViewer;
import javax.print.PrintException;
import javax.swing.*;
@ -183,49 +182,6 @@ public class RuleContext implements RuleNode {
@Override
public <T> T accept(ParseTreeVisitor<? extends T> visitor) { return visitor.visitChildren(this); }
/** Call this method to view a parse tree in a dialog box visually. */
public Future<JDialog> inspect(Parser parser) {
List<String> ruleNames = parser != null ? Arrays.asList(parser.getRuleNames()) : null;
return inspect(ruleNames);
}
public Future<JDialog> inspect(List<String> ruleNames) {
TreeViewer viewer = new TreeViewer(ruleNames, this);
return viewer.open();
}
/** Save this tree in a postscript file */
public void save(Parser parser, String fileName)
throws IOException, PrintException
{
List<String> ruleNames = parser != null ? Arrays.asList(parser.getRuleNames()) : null;
save(ruleNames, fileName);
}
/** Save this tree in a postscript file using a particular font name and size */
public void save(Parser parser, String fileName,
String fontName, int fontSize)
throws IOException
{
List<String> ruleNames = parser != null ? Arrays.asList(parser.getRuleNames()) : null;
save(ruleNames, fileName, fontName, fontSize);
}
/** Save this tree in a postscript file */
public void save(List<String> ruleNames, String fileName)
throws IOException, PrintException
{
Trees.writePS(this, ruleNames, fileName);
}
/** Save this tree in a postscript file using a particular font name and size */
public void save(List<String> ruleNames, String fileName,
String fontName, int fontSize)
throws IOException
{
Trees.writePS(this, ruleNames, fileName, fontName, fontSize);
}
/** Print out a whole tree, not just a node, in LISP format
* (root child1 .. childN). Print just a node if this is a leaf.
* We have to know the recognizer so we can get rule names.

View File

@ -1,270 +1,29 @@
/*
* [The "BSD license"]
* Copyright (c) 2012 Terence Parr
* Copyright (c) 2012 Sam Harwell
* 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.v4.runtime.misc;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.DiagnosticErrorListener;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.atn.PredictionMode;
import javax.print.PrintException;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/** Run a lexer/parser combo, optionally printing tree string or generating
* postscript file. Optionally taking input file.
/** A proxy for the real org.antlr.v4.gui.TestRig that we moved to tool
* artifact from runtime.
*
* $ java org.antlr.v4.runtime.misc.TestRig GrammarName startRuleName
* [-tree]
* [-tokens] [-gui] [-ps file.ps]
* [-trace]
* [-diagnostics]
* [-SLL]
* [input-filename(s)]
* @deprecated
* @since 4.5.1
*/
public class TestRig {
public static final String LEXER_START_RULE_NAME = "tokens";
protected String grammarName;
protected String startRuleName;
protected final List<String> inputFiles = new ArrayList<String>();
protected boolean printTree = false;
protected boolean gui = false;
protected String psFile = null;
protected boolean showTokens = false;
protected boolean trace = false;
protected boolean diagnostics = false;
protected String encoding = null;
protected boolean SLL = false;
public TestRig(String[] args) throws Exception {
if ( args.length < 2 ) {
System.err.println("java org.antlr.v4.runtime.misc.TestRig GrammarName startRuleName\n" +
" [-tokens] [-tree] [-gui] [-ps file.ps] [-encoding encodingname]\n" +
" [-trace] [-diagnostics] [-SLL]\n"+
" [input-filename(s)]");
System.err.println("Use startRuleName='tokens' if GrammarName is a lexer grammar.");
System.err.println("Omitting input-filename makes rig read from stdin.");
return;
}
int i=0;
grammarName = args[i];
i++;
startRuleName = args[i];
i++;
while ( i<args.length ) {
String arg = args[i];
i++;
if ( arg.charAt(0)!='-' ) { // input file name
inputFiles.add(arg);
continue;
}
if ( arg.equals("-tree") ) {
printTree = true;
}
if ( arg.equals("-gui") ) {
gui = true;
}
if ( arg.equals("-tokens") ) {
showTokens = true;
}
else if ( arg.equals("-trace") ) {
trace = true;
}
else if ( arg.equals("-SLL") ) {
SLL = true;
}
else if ( arg.equals("-diagnostics") ) {
diagnostics = true;
}
else if ( arg.equals("-encoding") ) {
if ( i>=args.length ) {
System.err.println("missing encoding on -encoding");
return;
}
encoding = args[i];
i++;
}
else if ( arg.equals("-ps") ) {
if ( i>=args.length ) {
System.err.println("missing filename on -ps");
return;
}
psFile = args[i];
i++;
}
}
}
public static void main(String[] args) throws Exception {
TestRig testRig = new TestRig(args);
if(args.length >= 2) {
testRig.process();
}
}
public void process() throws Exception {
// System.out.println("exec "+grammarName+"."+startRuleName);
String lexerName = grammarName+"Lexer";
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class<? extends Lexer> lexerClass = null;
public static void main(String[] args) {
try {
lexerClass = cl.loadClass(lexerName).asSubclass(Lexer.class);
}
catch (java.lang.ClassNotFoundException cnfe) {
// might be pure lexer grammar; no Lexer suffix then
lexerName = grammarName;
Class<?> testRigClass = Class.forName("org.antlr.v4.gui.TestRig");
System.err.println("Warning: TestRig moved to org.antlr.v4.gui.TestRig; calling automatically");
try {
lexerClass = cl.loadClass(lexerName).asSubclass(Lexer.class);
Method mainMethod = testRigClass.getMethod("main", String[].class);
mainMethod.invoke(null, (Object)args);
}
catch (ClassNotFoundException cnfe2) {
System.err.println("Can't load "+lexerName+" as lexer or parser");
return;
catch (Exception nsme) {
System.err.println("Problems calling org.antlr.v4.gui.TestRig.main(args)");
}
}
Constructor<? extends Lexer> lexerCtor = lexerClass.getConstructor(CharStream.class);
Lexer lexer = lexerCtor.newInstance((CharStream)null);
Class<? extends Parser> parserClass = null;
Parser parser = null;
if ( !startRuleName.equals(LEXER_START_RULE_NAME) ) {
String parserName = grammarName+"Parser";
parserClass = cl.loadClass(parserName).asSubclass(Parser.class);
if ( parserClass==null ) {
System.err.println("Can't load "+parserName);
}
Constructor<? extends Parser> parserCtor = parserClass.getConstructor(TokenStream.class);
parser = parserCtor.newInstance((TokenStream)null);
}
if ( inputFiles.size()==0 ) {
InputStream is = System.in;
Reader r;
if ( encoding!=null ) {
r = new InputStreamReader(is, encoding);
}
else {
r = new InputStreamReader(is);
}
process(lexer, parserClass, parser, is, r);
return;
}
for (String inputFile : inputFiles) {
InputStream is = System.in;
if ( inputFile!=null ) {
is = new FileInputStream(inputFile);
}
Reader r;
if ( encoding!=null ) {
r = new InputStreamReader(is, encoding);
}
else {
r = new InputStreamReader(is);
}
if ( inputFiles.size()>1 ) {
System.err.println(inputFile);
}
process(lexer, parserClass, parser, is, r);
}
}
protected void process(Lexer lexer, Class<? extends Parser> parserClass, Parser parser, InputStream is, Reader r) throws IOException, IllegalAccessException, InvocationTargetException, PrintException {
try {
ANTLRInputStream input = new ANTLRInputStream(r);
lexer.setInputStream(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
tokens.fill();
if ( showTokens ) {
for (Object tok : tokens.getTokens()) {
System.out.println(tok);
}
}
if ( startRuleName.equals(LEXER_START_RULE_NAME) ) return;
if ( diagnostics ) {
parser.addErrorListener(new DiagnosticErrorListener());
parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);
}
if ( printTree || gui || psFile!=null ) {
parser.setBuildParseTree(true);
}
if ( SLL ) { // overrides diagnostics
parser.getInterpreter().setPredictionMode(PredictionMode.SLL);
}
parser.setTokenStream(tokens);
parser.setTrace(trace);
try {
Method startRule = parserClass.getMethod(startRuleName);
ParserRuleContext tree = (ParserRuleContext)startRule.invoke(parser, (Object[])null);
if ( printTree ) {
System.out.println(tree.toStringTree(parser));
}
if ( gui ) {
tree.inspect(parser);
}
if ( psFile!=null ) {
tree.save(parser, psFile); // Generate postscript
}
}
catch (NoSuchMethodException nsme) {
System.err.println("No method for rule "+startRuleName+" or it has arguments");
}
}
finally {
if ( r!=null ) r.close();
if ( is!=null ) is.close();
catch (ClassNotFoundException cnfe) {
System.err.println("Use of TestRig now requires the use of the tool jar, antlr-4.X-complete.jar");
System.err.println("Maven users need group ID org.antlr and artifact ID antlr4");
}
}
}

View File

@ -37,12 +37,7 @@ import org.antlr.v4.runtime.Token;
import org.antlr.v4.runtime.misc.Interval;
import org.antlr.v4.runtime.misc.Predicate;
import org.antlr.v4.runtime.misc.Utils;
import org.antlr.v4.runtime.tree.gui.TreePostScriptGenerator;
import org.antlr.v4.runtime.tree.gui.TreeTextProvider;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@ -51,41 +46,6 @@ import java.util.List;
/** A set of utility routines useful for all kinds of ANTLR trees. */
public class Trees {
public static String getPS(Tree t, List<String> ruleNames,
String fontName, int fontSize)
{
TreePostScriptGenerator psgen =
new TreePostScriptGenerator(ruleNames, t, fontName, fontSize);
return psgen.getPS();
}
public static String getPS(Tree t, List<String> ruleNames) {
return getPS(t, ruleNames, "Helvetica", 11);
}
public static void writePS(Tree t, List<String> ruleNames,
String fileName,
String fontName, int fontSize)
throws IOException
{
String ps = getPS(t, ruleNames, fontName, fontSize);
FileWriter f = new FileWriter(fileName);
BufferedWriter bw = new BufferedWriter(f);
try {
bw.write(ps);
}
finally {
bw.close();
}
}
public static void writePS(Tree t, List<String> ruleNames, String fileName)
throws IOException
{
writePS(t, ruleNames, fileName, "Helvetica", 11);
}
/** Print out a whole tree in LISP form. {@link #getNodeText} is used on the
* node payloads to get the text for the nodes. Detect
* parse trees and extract data appropriately.
@ -104,38 +64,23 @@ public class Trees {
return toStringTree(t, ruleNamesList);
}
/** Print out a whole tree in LISP form. Arg nodeTextProvider is used on the
* node payloads to get the text for the nodes.
*
* @since 4.5.1
*/
public static String toStringTree(Tree t, TreeTextProvider nodeTextProvider) {
if ( t==null ) return "null";
String s = Utils.escapeWhitespace(nodeTextProvider.getText(t), false);
if ( t.getChildCount()==0 ) return s;
StringBuilder buf = new StringBuilder();
buf.append("(");
s = Utils.escapeWhitespace(nodeTextProvider.getText(t), false);
buf.append(s);
buf.append(' ');
for (int i = 0; i<t.getChildCount(); i++) {
if ( i>0 ) buf.append(' ');
buf.append(toStringTree(t.getChild(i), nodeTextProvider));
}
buf.append(")");
return buf.toString();
}
/** Print out a whole tree in LISP form. {@link #getNodeText} is used on the
* node payloads to get the text for the nodes.
*/
public static String toStringTree(final Tree t, final List<String> ruleNames) {
return toStringTree(t, new TreeTextProvider() {
@Override
public String getText(Tree node) {
return getNodeText(node, ruleNames);
}
});
String s = Utils.escapeWhitespace(getNodeText(t, ruleNames), false);
if ( t.getChildCount()==0 ) return s;
StringBuilder buf = new StringBuilder();
buf.append("(");
s = Utils.escapeWhitespace(getNodeText(t, ruleNames), false);
buf.append(s);
buf.append(' ');
for (int i = 0; i<t.getChildCount(); i++) {
if ( i>0 ) buf.append(' ');
buf.append(toStringTree(t.getChild(i), ruleNames));
}
buf.append(")");
return buf.toString();
}
public static String getNodeText(Tree t, Parser recog) {
@ -204,7 +149,7 @@ public class Trees {
if ( t==null || u==null || t.getParent()==null ) return false;
Tree p = u.getParent();
while ( p!=null ) {
if ( t == p ) return true;
if ( t==p ) return true;
p = p.getParent();
}
return false;

View File

@ -3,7 +3,7 @@ package org.antlr.v4.test.tool;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.Tree;
import org.antlr.v4.runtime.tree.Trees;
import org.antlr.v4.runtime.tree.gui.TreeTextProvider;
import org.antlr.v4.gui.TreeTextProvider;
import org.antlr.v4.tool.GrammarInterpreterRuleContext;
import java.util.Arrays;

View File

@ -14,7 +14,7 @@ import org.antlr.v4.runtime.atn.PredictionMode;
import org.antlr.v4.runtime.atn.RuleStartState;
import org.antlr.v4.runtime.atn.Transition;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.Trees;
import org.antlr.v4.gui.Trees;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.GrammarParserInterpreter;
import org.antlr.v4.tool.LexerGrammar;

View File

@ -34,7 +34,7 @@ import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.InterpreterRuleContext;
import org.antlr.v4.runtime.LexerInterpreter;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.Trees;
import org.antlr.v4.gui.Trees;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.GrammarParserInterpreter;
import org.antlr.v4.tool.LexerGrammar;

View File

@ -7,7 +7,7 @@ import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.atn.DecisionInfo;
import org.antlr.v4.runtime.atn.LookaheadEventInfo;
import org.antlr.v4.runtime.tree.ParseTree;
import org.antlr.v4.runtime.tree.Trees;
import org.antlr.v4.gui.Trees;
import org.antlr.v4.tool.Grammar;
import org.antlr.v4.tool.GrammarParserInterpreter;
import org.antlr.v4.tool.LexerGrammar;

View File

@ -46,6 +46,11 @@
<version>4.0.8</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.abego.treelayout</groupId>
<artifactId>org.abego.treelayout.core</artifactId>
<version>1.0.1</version>
</dependency>
</dependencies>
<build>
@ -93,14 +98,14 @@
<execution>
<phase>package</phase>
<configuration>
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
</configuration>
<dependencyReducedPomLocation>${project.build.directory}/dependency-reduced-pom.xml</dependencyReducedPomLocation>
</configuration>
<goals>
<goal>shade</goal>
</goals>
</execution>
</executions>
</plugin>
</plugin>
</plugins>
</build>
</project>

View File

@ -28,7 +28,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.tree.gui;
package org.antlr.v4.gui;
/** Font metrics. The only way to generate accurate images
* in any format that contain text is to know the font metrics.

View File

@ -28,7 +28,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.misc;
package org.antlr.v4.gui;
import javax.imageio.ImageIO;
import javax.print.DocFlavor;

View File

@ -27,7 +27,7 @@
* (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.v4.runtime.misc;
package org.antlr.v4.gui;
import javax.swing.*;
import java.io.File;

View File

@ -28,7 +28,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.tree.gui;
package org.antlr.v4.gui;
import java.awt.*;
import java.util.HashMap;

View File

@ -28,7 +28,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.tree.gui;
package org.antlr.v4.gui;
import java.awt.*;
import java.awt.font.FontRenderContext;

View File

@ -0,0 +1,270 @@
/*
* [The "BSD license"]
* Copyright (c) 2012 Terence Parr
* Copyright (c) 2012 Sam Harwell
* 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.v4.gui;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.DiagnosticErrorListener;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.atn.PredictionMode;
import javax.print.PrintException;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
/** Run a lexer/parser combo, optionally printing tree string or generating
* postscript file. Optionally taking input file.
*
* $ java org.antlr.v4.runtime.misc.TestRig GrammarName startRuleName
* [-tree]
* [-tokens] [-gui] [-ps file.ps]
* [-trace]
* [-diagnostics]
* [-SLL]
* [input-filename(s)]
*/
public class TestRig {
public static final String LEXER_START_RULE_NAME = "tokens";
protected String grammarName;
protected String startRuleName;
protected final List<String> inputFiles = new ArrayList<String>();
protected boolean printTree = false;
protected boolean gui = false;
protected String psFile = null;
protected boolean showTokens = false;
protected boolean trace = false;
protected boolean diagnostics = false;
protected String encoding = null;
protected boolean SLL = false;
public TestRig(String[] args) throws Exception {
if ( args.length < 2 ) {
System.err.println("java org.antlr.v4.runtime.misc.TestRig GrammarName startRuleName\n" +
" [-tokens] [-tree] [-gui] [-ps file.ps] [-encoding encodingname]\n" +
" [-trace] [-diagnostics] [-SLL]\n"+
" [input-filename(s)]");
System.err.println("Use startRuleName='tokens' if GrammarName is a lexer grammar.");
System.err.println("Omitting input-filename makes rig read from stdin.");
return;
}
int i=0;
grammarName = args[i];
i++;
startRuleName = args[i];
i++;
while ( i<args.length ) {
String arg = args[i];
i++;
if ( arg.charAt(0)!='-' ) { // input file name
inputFiles.add(arg);
continue;
}
if ( arg.equals("-tree") ) {
printTree = true;
}
if ( arg.equals("-gui") ) {
gui = true;
}
if ( arg.equals("-tokens") ) {
showTokens = true;
}
else if ( arg.equals("-trace") ) {
trace = true;
}
else if ( arg.equals("-SLL") ) {
SLL = true;
}
else if ( arg.equals("-diagnostics") ) {
diagnostics = true;
}
else if ( arg.equals("-encoding") ) {
if ( i>=args.length ) {
System.err.println("missing encoding on -encoding");
return;
}
encoding = args[i];
i++;
}
else if ( arg.equals("-ps") ) {
if ( i>=args.length ) {
System.err.println("missing filename on -ps");
return;
}
psFile = args[i];
i++;
}
}
}
public static void main(String[] args) throws Exception {
TestRig testRig = new TestRig(args);
if(args.length >= 2) {
testRig.process();
}
}
public void process() throws Exception {
// System.out.println("exec "+grammarName+"."+startRuleName);
String lexerName = grammarName+"Lexer";
ClassLoader cl = Thread.currentThread().getContextClassLoader();
Class<? extends Lexer> lexerClass = null;
try {
lexerClass = cl.loadClass(lexerName).asSubclass(Lexer.class);
}
catch (java.lang.ClassNotFoundException cnfe) {
// might be pure lexer grammar; no Lexer suffix then
lexerName = grammarName;
try {
lexerClass = cl.loadClass(lexerName).asSubclass(Lexer.class);
}
catch (ClassNotFoundException cnfe2) {
System.err.println("Can't load "+lexerName+" as lexer or parser");
return;
}
}
Constructor<? extends Lexer> lexerCtor = lexerClass.getConstructor(CharStream.class);
Lexer lexer = lexerCtor.newInstance((CharStream)null);
Class<? extends Parser> parserClass = null;
Parser parser = null;
if ( !startRuleName.equals(LEXER_START_RULE_NAME) ) {
String parserName = grammarName+"Parser";
parserClass = cl.loadClass(parserName).asSubclass(Parser.class);
if ( parserClass==null ) {
System.err.println("Can't load "+parserName);
}
Constructor<? extends Parser> parserCtor = parserClass.getConstructor(TokenStream.class);
parser = parserCtor.newInstance((TokenStream)null);
}
if ( inputFiles.size()==0 ) {
InputStream is = System.in;
Reader r;
if ( encoding!=null ) {
r = new InputStreamReader(is, encoding);
}
else {
r = new InputStreamReader(is);
}
process(lexer, parserClass, parser, is, r);
return;
}
for (String inputFile : inputFiles) {
InputStream is = System.in;
if ( inputFile!=null ) {
is = new FileInputStream(inputFile);
}
Reader r;
if ( encoding!=null ) {
r = new InputStreamReader(is, encoding);
}
else {
r = new InputStreamReader(is);
}
if ( inputFiles.size()>1 ) {
System.err.println(inputFile);
}
process(lexer, parserClass, parser, is, r);
}
}
protected void process(Lexer lexer, Class<? extends Parser> parserClass, Parser parser, InputStream is, Reader r) throws IOException, IllegalAccessException, InvocationTargetException, PrintException {
try {
ANTLRInputStream input = new ANTLRInputStream(r);
lexer.setInputStream(input);
CommonTokenStream tokens = new CommonTokenStream(lexer);
tokens.fill();
if ( showTokens ) {
for (Object tok : tokens.getTokens()) {
System.out.println(tok);
}
}
if ( startRuleName.equals(LEXER_START_RULE_NAME) ) return;
if ( diagnostics ) {
parser.addErrorListener(new DiagnosticErrorListener());
parser.getInterpreter().setPredictionMode(PredictionMode.LL_EXACT_AMBIG_DETECTION);
}
if ( printTree || gui || psFile!=null ) {
parser.setBuildParseTree(true);
}
if ( SLL ) { // overrides diagnostics
parser.getInterpreter().setPredictionMode(PredictionMode.SLL);
}
parser.setTokenStream(tokens);
parser.setTrace(trace);
try {
Method startRule = parserClass.getMethod(startRuleName);
ParserRuleContext tree = (ParserRuleContext)startRule.invoke(parser, (Object[])null);
if ( printTree ) {
System.out.println(tree.toStringTree(parser));
}
if ( gui ) {
Trees.inspect(tree, parser);
}
if ( psFile!=null ) {
Trees.save(tree, parser, psFile); // Generate postscript
}
}
catch (NoSuchMethodException nsme) {
System.err.println("No method for rule "+startRuleName+" or it has arguments");
}
}
finally {
if ( r!=null ) r.close();
if ( is!=null ) is.close();
}
}
}

View File

@ -28,7 +28,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.tree.gui;
package org.antlr.v4.gui;
import org.abego.treelayout.TreeForTreeLayout;
import org.antlr.v4.runtime.tree.Tree;

View File

@ -28,7 +28,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.tree.gui;
package org.antlr.v4.gui;
import org.abego.treelayout.Configuration;
import org.abego.treelayout.NodeExtentProvider;

View File

@ -28,7 +28,7 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.tree.gui;
package org.antlr.v4.gui;
import org.antlr.v4.runtime.tree.Tree;

View File

@ -28,15 +28,13 @@
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.antlr.v4.runtime.tree.gui;
package org.antlr.v4.gui;
import org.abego.treelayout.NodeExtentProvider;
import org.abego.treelayout.TreeForTreeLayout;
import org.abego.treelayout.TreeLayout;
import org.abego.treelayout.util.DefaultConfiguration;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.misc.GraphicsSupport;
import org.antlr.v4.runtime.misc.JFileChooserConfirmOverwrite;
import org.antlr.v4.runtime.misc.Utils;
import org.antlr.v4.runtime.tree.ErrorNode;
import org.antlr.v4.runtime.tree.Tree;

View File

@ -0,0 +1,120 @@
package org.antlr.v4.gui;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.misc.Utils;
import org.antlr.v4.runtime.tree.Tree;
import javax.print.PrintException;
import javax.swing.*;
import java.io.BufferedWriter;
import java.io.FileWriter;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Future;
public class Trees {
/** Call this method to view a parse tree in a dialog box visually. */
public static Future<JDialog> inspect(Tree t, List<String> ruleNames) {
TreeViewer viewer = new TreeViewer(ruleNames, t);
return viewer.open();
}
/** Call this method to view a parse tree in a dialog box visually. */
public static Future<JDialog> inspect(Tree t, Parser parser) {
List<String> ruleNames = parser != null ? Arrays.asList(parser.getRuleNames()) : null;
return inspect(t, ruleNames);
}
/** Save this tree in a postscript file */
public static void save(Tree t, Parser parser, String fileName)
throws IOException, PrintException
{
List<String> ruleNames = parser != null ? Arrays.asList(parser.getRuleNames()) : null;
save(t, ruleNames, fileName);
}
/** Save this tree in a postscript file using a particular font name and size */
public static void save(Tree t, Parser parser, String fileName,
String fontName, int fontSize)
throws IOException
{
List<String> ruleNames = parser != null ? Arrays.asList(parser.getRuleNames()) : null;
save(t, ruleNames, fileName, fontName, fontSize);
}
/** Save this tree in a postscript file */
public static void save(Tree t, List<String> ruleNames, String fileName)
throws IOException, PrintException
{
writePS(t, ruleNames, fileName);
}
/** Save this tree in a postscript file using a particular font name and size */
public static void save(Tree t,
List<String> ruleNames, String fileName,
String fontName, int fontSize)
throws IOException
{
writePS(t, ruleNames, fileName, fontName, fontSize);
}
public static String getPS(Tree t, List<String> ruleNames,
String fontName, int fontSize)
{
TreePostScriptGenerator psgen =
new TreePostScriptGenerator(ruleNames, t, fontName, fontSize);
return psgen.getPS();
}
public static String getPS(Tree t, List<String> ruleNames) {
return getPS(t, ruleNames, "Helvetica", 11);
}
public static void writePS(Tree t, List<String> ruleNames,
String fileName,
String fontName, int fontSize)
throws IOException
{
String ps = getPS(t, ruleNames, fontName, fontSize);
FileWriter f = new FileWriter(fileName);
BufferedWriter bw = new BufferedWriter(f);
try {
bw.write(ps);
}
finally {
bw.close();
}
}
public static void writePS(Tree t, List<String> ruleNames, String fileName)
throws IOException
{
writePS(t, ruleNames, fileName, "Helvetica", 11);
}
/** Print out a whole tree in LISP form. Arg nodeTextProvider is used on the
* node payloads to get the text for the nodes.
*
* @since 4.5.1
*/
public static String toStringTree(Tree t, TreeTextProvider nodeTextProvider) {
if ( t==null ) return "null";
String s = Utils.escapeWhitespace(nodeTextProvider.getText(t), false);
if ( t.getChildCount()==0 ) return s;
StringBuilder buf = new StringBuilder();
buf.append("(");
s = Utils.escapeWhitespace(nodeTextProvider.getText(t), false);
buf.append(s);
buf.append(' ');
for (int i = 0; i<t.getChildCount(); i++) {
if ( i>0 ) buf.append(' ');
buf.append(toStringTree(t.getChild(i), nodeTextProvider));
}
buf.append(")");
return buf.toString();
}
private Trees() {
}
}