/*
 * Copyright (c) 2012-2017 The ANTLR Project. All rights reserved.
 * Use of this file is governed by the BSD 3-clause license that
 * can be found in the LICENSE.txt file in the project root.
 */

package org.antlr.v4.gui;

import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CharStreams;
import org.antlr.v4.runtime.CommonToken;
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.Token;
import org.antlr.v4.runtime.TokenStream;
import org.antlr.v4.runtime.atn.PredictionMode;

import javax.print.PrintException;
import java.io.IOException;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.nio.charset.Charset;
import java.nio.file.Paths;
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)]
/** 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.gui.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); Constructor<? extends Parser> parserCtor = parserClass.getConstructor(TokenStream.class); parser = parserCtor.newInstance((TokenStream)null); } Charset charset = ( encoding == null ? Charset.defaultCharset () : Charset.forName(encoding) ); if ( inputFiles.size()==0 ) { CharStream charStream = CharStreams.fromStream(System.in, charset); process(lexer, parserClass, parser, charStream); return; } for (String inputFile : inputFiles) { CharStream charStream = CharStreams.fromPath(Paths.get(inputFile), charset); if ( inputFiles.size()>1 ) { System.err.println(inputFile); } process(lexer, parserClass, parser, charStream); } } protected void process(Lexer lexer, Class<? extends Parser> parserClass, Parser parser, CharStream input) throws IOException, IllegalAccessException, InvocationTargetException, PrintException { lexer.setInputStream(input); CommonTokenStream tokens = new CommonTokenStream(lexer); tokens.fill(); if ( showTokens ) { for (Token tok : tokens.getTokens()) { if ( tok instanceof CommonToken ) { System.out.println(((CommonToken)tok).toString(lexer)); } else { System.out.println(tok.toString()); } } } 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"); } } }