ANTLR4由于解析错误而在到达文件末尾之前成功终止解析的情况

时间:2019-01-13 19:33:59

标签: parsing antlr4

我在单独的文件中为ANTLR4提供了以下解析器和词法分析器语法(指的是BNF语法的简单语法)

parser grammar BNFParser;

options {tokenVocab = BNFLexer;}

compileUnit
    :   grammar_rule+
    ;

grammar_rule : NON_TERMINAL COLON (OR? grammar_rule_alternative)* SEMICOLON
           ;

grammar_rule_alternative : (NON_TERMINAL|TERMINAL)+ 
                    ;

lexer grammar BNFLexer;

TERMINAL : [A-Z][A-Za-z0-9_]*;
NON_TERMINAL : [a-z][A-Za-z0-9_]*;
OR : '|';
COLON : ':';
SEMICOLON : ';';

WS
  : [ \t\r\n]+ -> skip
 ;

主程序

private static void Main(string[] args) {
            StreamReader reader = new StreamReader(args[0]);
            AntlrInputStream stream = new AntlrInputStream(reader);
            BNFLexer lexer = new BNFLexer(stream);
            CommonTokenStream tokens = new CommonTokenStream(lexer);
            BNFParser parser = new BNFParser(tokens);
            IParseTree root = parser.compileUnit();
            Console.WriteLine(root.ToStringTree());
}

还提供了以下测试文件来测试语法

 compileunit : x a
        ;

 x : S b
   ;

 S : compileunit f
  ;

请从词法分析器语法中注意到,非终端以小写字母开头,而终端以大写字母开头。给定的语法有错误。第三条规则使用大写字母(S)定义非终端S。预期的行为是将其报告为错误。相反,解析通过使用前两个规则并忽略S的第三个规则而不报告任何错误而成功。我也看到了生成的文件,并且注意到以下

try {
    EnterOuterAlt(_localctx, 1);
    {
    State = 7;
    _errHandler.Sync(this);
    _la = _input.La(1);
    do {
        {
        {
        State = 6; grammar_rule();
        }
        }
        State = 9;
        _errHandler.Sync(this);
        _la = _input.La(1);
    } while ( _la==NON_TERMINAL );
    }
 }
 catch (RecognitionException re) {
     _localctx.exception = re;
     _errHandler.ReportError(this, re);
     _errHandler.Recover(this, re);
 }

上面的代码显示,语法分析器期望grammar_rule开头的非终端符号,这正是我所期望的。但是,如果不是这种情况怎么办?另一个奇怪的问题是,包含词法分析器识别的标记的CommonTokenStream对象仅包含直到第二条规则结束的标记,而没有包含第三条规则(S)的标记。这是适当的行为吗?

1 个答案:

答案 0 :(得分:1)

将EOF令牌添加到您的主规则(compileUnit)。这将迫使解析器使用所有输入,直到EOF为止,如果不完全匹配,则报告错误。