tunnelvisionlabs / antlr4cs

The original, highly-optimized C# Target for ANTLR 4
Other
449 stars 103 forks source link

Grammar Recognition in Version 4.6.6 #318

Closed zhangjianxi2008 closed 5 years ago

zhangjianxi2008 commented 5 years ago

Hello,

I'm trying to make a simple formula calculator, but in some cases it can't recognize grammatical errors. Can you help me figure out where the errors are?Thank you very much!

Here is my grammar:

grammar Formula;

prog : expr
;
expr 
    :  op=(PLUS | MINUS) expr             #unaryExpr
    | expr CARET expr                     #binaryExpr
    | expr op=(MULT | DIV) expr           #binaryExpr
    | expr op=(PLUS | MINUS) expr         #binaryExpr
    | '(' expr ')'                        #parenthesisExpr
    | '|' expr '|'                        #absoluteExpr
    | MATH_FUNC_1 '(' expr ')'            #mathFunc1Expr
    | MATH_FUNC_2 '(' expr ',' expr ')'   #mathFunc2Expr
    | NUMBER                              #numberExpr
    | MACRO                               #macroExpr
;

PLUS : '+' ;
MINUS : '-';
MULT : '*' ;
DIV : '/' ;
LPAREN : '(';
RPAREN : ')';
CARET: '^';
NUMBER : DIGIT+
   | DIGIT+ '.' DIGIT*
   | '.' DIGIT+
;

MATH_FUNC_1 : 'abs'|'sin'|'sinh'|'cos'|'cosh'|'tan'|'tanh'|'asin'|'acos'|'atan'|'ceil'|'floor'|'sqrt'|'log'|'log10'|'round'|'truncate';
MATH_FUNC_2 : 'atan2'|'div'|'rem'|'ieeerem'|'log'|'max'|'min'|'pow'|'round';
MACRO : (ID '.' ID) | ID;
WS :  [ \t\r\n]+ -> channel(HIDDEN);

fragment ID : ID_LETTER (ID_LETTER | DIGIT)*;
fragment ID_LETTER: [a-zA-Z_];
fragment DIGIT : [0-9];

And my test program (C#), showing the input stream:

            string expr = "xyz(";
            var errorListener = new FormulaParseErrorListener();
            AntlrInputStream input = new AntlrInputStream(expr);
            FormulaLexer lexer = new FormulaLexer(input);
            lexer.RemoveErrorListeners();
            lexer.AddErrorListener(errorListener);
            CommonTokenStream tokens = new CommonTokenStream(lexer);
            tokens.Fill();
            FormulaParser parser = new FormulaParser(tokens);
            parser.RemoveErrorListeners();
            parser.AddErrorListener(errorListener);
            parser.prog();
            foreach (var err in errorListener.Errors) {
                Console.WriteLine($"err(start:{err.Start}, end:{err.End}, msg:{err.Msg})");
            }

Your help would be appreciated. Best regards,

ZJX.

sharwell commented 5 years ago

You need to add an explicit EOF to your entry rule. Otherwise, the parsing process is allowed to terminate before the end of the file if it means an error is avoided.

prog
  : expr EOF
  ;
zhangjianxi2008 commented 5 years ago

You need to add an explicit EOF to your entry rule. Otherwise, the parsing process is allowed to terminate before the end of the file if it means an error is avoided.

prog
  : expr EOF
  ;

Thanks a lot for the trouble you've taken to help us! ^&^