17
votes

With ANTLR I parse a grammar. The ANTLR errors are indicated in a custom editor for the grammar. However I would like to disable the printing of error messages to a Java console.

I've implemented my own BaseErrorListener and removed the default as described in the ANTLR book:

MyErrorListener errList=new MyErrorListener ();
lexer.removeErrorListeners();
lexer.addErrorListener(errList);
parser.removeErrorListeners();   
parser.addErrorListener(errList);

Still I get printed outputs to my Java console (connected to the Java output and error stream).

How can I disable the printing to the console in ANTLR?

4
What are you doing in your "MyErrorListener"?Alexander Pacha
In my listener which extends the BaseErrorListener I collect errors extract the linenumber to mark them in my custom editor. I do not print anything to the standard output.Marcel

4 Answers

19
votes

By default, ConsoleListener is activated [1].

You can remove it in your code:

lexer.removeErrorListener(ConsoleErrorListener.INSTANCE);

[1] https://github.com/antlr/antlr4/blob/master/runtime/Java/src/org/antlr/v4/runtime/Recognizer.java#L56 (see add(ConsoleErrorListener.INSTANCE);)

3
votes

You can check what listeners you have

for (ANTLRErrorListener listener : parser.getErrorListeners()) {
        System.out.println(listener);
}

Look for ConsoleErrorListener.

1
votes

I finally found the solution. I have a filter before the grammar:

Filter filter = new Filter(tokens)

where the listener of the filter (a pre parser class) also has to be removed:

filter.removeErrorListeners();
1
votes

ANTLR warnings are printed to os.Stderr. Hence, what you could do is to redirect Stderr, capture all warnings, and decide what to do with them.

Of course, this means your program can not print out anything to Stderr during the parse.

Pseudocode, just to get the gist.

    // redirect stdout - antlr runtime prints to STDOUT on error
    outStream := make(chan string)
    stderr := os.Stdout
    r, w, err := os.Pipe()
    if err != nil {
        return err
    }
    os.Stderr = w

    // capture stderr
    go func() {
        var buf bytes.Buffer
        io.Copy(&buf, r)
        outStream <- buf.String()
    }()

    // run parse with stdout redirected
    go func() {
        // ANTLR can, and WILL panic in a pythonic fashion!
        defer func() {
            if r := recover(); r != nil {
                listener.err = errors.Append(listener.err, errors.E(r.(string)).WithOperation("ParseString"))
            }
        }()
        stream := antlr.NewInputStream(ddl)
        lexer := parser.NewTeradataStatementLexer(stream)
        tokenStream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)
        prsr := parser.NewTeradataStatementParser(tokenStream)
        antlr.ParseTreeWalkerDefault.Walk(&listener, prsr.Program())
        w.Close()          // close redirected stdout
        os.Stderr = stderr // redirect to normal stdout
    }()

    // capture stdout and check for errors
    parseStdout := <-outStream
    if parseStdout != "" {
        // non empty stderr, handle errors reported by ANTLR
    }