forked from jasder/antlr
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:
commit
b555099842
|
@ -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>
|
||||
|
@ -70,22 +62,6 @@
|
|||
</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>
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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.
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
|
@ -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;
|
|
@ -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;
|
||||
|
|
@ -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;
|
|
@ -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() {
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue