antlr.ParseTreeWalkerDefault.Walk is invoking label functions even in case of error

60 views
Skip to first unread message

Anil Dasari

unread,
Jan 28, 2020, 7:02:23 PM1/28/20
to antlr-discussion
HI,

i am playing with antlr4. following is used antlr4 grammar


grammar Filter;

// Tokens.
AND: 'AND';
OR: 'OR';
OBJECT: (('a' ..'z' | 'A' ..'Z' | '\\' | '/' | '_')+);
OPERATOR: '=' | '!=';
WHITESPACE: [ \r\n\t]+ -> skip;

OPEN_CURLY: '(';
CLOSE_CURLY: ')';
VALUE: (STRING | NUMBER | TRUE | FALSE);


fragment TRUE: 'true';
fragment FALSE: 'false';
fragment STRING: '"' (ESC | .)*? '"';
fragment NUMBER: [0-9.]+;
fragment UNICODE: ('\u0000' ..'\u00FF')+;
fragment ESC: '\\"' | '\\\\';

// Rules.

start: expression EOF;
expression
    : OBJECT OPERATOR VALUE                     # comparison
    | expression AND expression # comparisonAND
    | expression OR expression  # comparisonOR
    | OPEN_CURLY expression CLOSE_CURLY # nestedExpression
    ;


parser logic in go is

type filterListener struct {
    *parser.BaseFilterListener
    errorListener ErrorListener
}


// errorListener is custom implmentation of error listener

// ExitStart is called when exiting the start production.
func (s *filterListener) ExitStart(c *parser.StartContext) {
    fmt.Printf("ExitStart: %v\n", c.GetText())
}

// ExitComparison is called when exiting the comparison production.
func (s *filterListener) ExitComparison(c *parser.ComparisonContext) {  
    fmt.Printf("ExitComparison: %v\n", c.GetText())
}

// ExitComparison is called when exiting the comparison production.
func (s *filterListener) ExitComparisonAND(c *parser.ComparisonANDContext) {
    fmt.Printf("ExitComparison: %v\n", c.GetText())
}

// ExitComparison is called when exiting the comparison production.
func (s *filterListener) ExitComparisonOR(c *parser.ComparisonORContext) {
    fmt.Printf("ExitComparison: %v\n", c.GetText())
}

// ExitNestedExpression is called when exiting the nestedExpression production.
func (s *filterListener) ExitNestedExpression(c *parser.NestedExpressionContext) {
    fmt.Printf("ExitNestedExpression: %v\n", c.GetText())
}

// Parse
func Parse(input string) (stringstringerror) {
    // Setup the input.
    is := antlr.NewInputStream(input)

    // Create the Lexer.
    lexer := parser.NewFilterLexer(is)
    
    stream := antlr.NewCommonTokenStream(lexer, antlr.TokenDefaultChannel)

    
    // Create the Parser.
    p := parser.NewFilterParser(stream)

    // Finally parse the expression (by walking the tree).
    listener := filterListener{}

    // Add err listener for the parser.
    p.AddErrorListener(&listener.errorListener)

    antlr.ParseTreeWalkerDefault.Walk(&listener, p.Start())

    // return the err message on encountering
    // err while parsing.
    if listener.errorListener.err != nil {
        fmt.Printf("failed to run")
        return """", listener.errorListener.err
    }

    
    return """"nil
}

func main() {
    
    qs := []string{
        `test123`,
        
    }

    for _q := range qs {
        if __err := Parse(q); err != nil {
            fmt.Printf("*********************\n\n failed - %s : %v\n\n*************************** \n", q, err)
        }
        fmt.Printf("*********************\n\n completed*************************** \n")
    }
}

output is :

go run parser.go
line 1:4 missing OPERATOR at '123'
ExitComparison: test<missing >123
ExitStart: test<missing >123<EOF>
*********************

 failed - test123 : missing OPERATOR at '123' column:4

***************************

line 1:4 missing OPERATOR at '123' is the message from the syntax error from custom error listener. Is there any way to stop the walk tree when there is an error  or check for errors before actually invoking parser listener ? thanks in advance. 


Thanks
Reply all
Reply to author
Forward
0 new messages