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



我在单独的文件中为ANTLR4提供了以下语法分析器和lexer语法(指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
: [ trn]+ -> 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
;

请注意,从lexer语法中,非终端以小写字母开头,而终端以大写字母开头。这个给定的语法有一个错误。第三条规则使用大写字母(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的开头需要一个Non-Terminal符号,这正是我所期望的。然而,如果情况并非如此,会发生什么?另一个奇怪的问题是,包含lexer识别的令牌的CommonTokenStream对象只包含第二条规则结束前的令牌,而不包含第三条规则(S)的令牌。这种行为恰当吗?

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

相关内容

  • 没有找到相关文章

最新更新