Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use antlr4 in Eclipse?

Since Antlr4 is new version of Antlr and this is the first time I use it. I have downloaded the Antlr4 plugin from eclipse marketplace. I made new ANTLR 4 project and I got Hello.g4

Afterward I saw this small grammar:

  /**
  * Define a grammar called Hello
   */
   grammar Hello;
     r  : 'hello' ID ;         // match keyword hello followed by an                                                          identifier

      ID : [a-z]+ ;             // match lower-case identifiers

       WS : [ \t\r\n]+ -> skip ; // skip spaces, tabs, newlines

Once it was saved, It was build and I saw it from the Antlr console, I wanted to test the program but I didn't know how, and I didn't know how to make a new file that can be compiled by the new grammar?

Thanks in advance for any help.

like image 994
Naji Kadri Avatar asked Feb 05 '15 19:02

Naji Kadri


1 Answers

You need to create an instance of the generated parser in order to run it.

  • Create a Java project J next to your ANTLR project A.
  • Create a linked folder in project J referencing the generated-sources/antlr4 folder from A, and make this linked folder a source folder. Compile errors should appear.
  • Add the antlr4 jar to the build path of project J. This should remove the compile errors.
  • Write a main program in J which creates an instance of the generated parser and feeds it with text. You can take the TestRig from the ANTLR documentation, pasted below for convenience.

The TestRig must be invoked by passing the grammar name (Hello, in your example) and the starting rule (r).

import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CharStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.DefaultErrorStrategy;
import org.antlr.v4.runtime.DiagnosticErrorListener;
import org.antlr.v4.runtime.InputMismatchException;
import org.antlr.v4.runtime.Lexer;
import org.antlr.v4.runtime.Parser;
import org.antlr.v4.runtime.ParserRuleContext;
import org.antlr.v4.runtime.RecognitionException;
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.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 Test {
    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 Test(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 {
        Test test = new Test(args);
        if(args.length >= 2) {
            test.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) {
                System.err.println("1: 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);
            //parser.setErrorHandler(new BailErrorStrategy());

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

  @SuppressWarnings("unused")
  private static class BailErrorStrategy extends DefaultErrorStrategy {
      /** Instead of recovering from exception e, rethrow it wrapped
      * in a generic RuntimeException so it is not caught by the
      * rule function catches. Exception e is the "cause" of the
      * RuntimeException.
      */
      @Override
      public void recover(Parser recognizer, RecognitionException e) {
      throw new RuntimeException(e);
      }
      /** Make sure we don't attempt to recover inline; if the parser
      * successfully recovers, it won't throw an exception.
      */
      @Override
      public Token recoverInline(Parser recognizer)
      throws RecognitionException
      {
      throw new RuntimeException(new InputMismatchException(recognizer));
      }
      /** Make sure we don't attempt to recover from problems in subrules. */
      @Override
      public void sync(Parser recognizer) { }
      }
}

'Hope this helps!

like image 50
Marc Q. Avatar answered Oct 09 '22 14:10

Marc Q.