ANTLR匹配解析器规则的一部分,即使它无法完全匹配规则

时间:2013-11-16 16:02:37

标签: c# parsing antlr dsl

我开始使用ANTLR并尝试使用非常简单的语言创建解析器。 目前我的语法定义为:

/*
 * Parser Rules
 */

public compileUnit
    : DEFINE IDENTIFIER END_OF_STATEMENT { Console.WriteLine($IDENTIFIER.text); };

/*
 * Lexer Rules
 */


DEFINE : 'define';

// Basic tokens
INT : '0'..'9'+;

END_OF_STATEMENT : ';';

// Whitespace
WS :  (' '|'\t'|'\r'|'\n')+ {Skip();} ;

// Sub-statement tokens

IDENTIFIER : ('a'..'z' | 'A'..'Z')+ (INT | ('a'..'z' | 'A'..'Z') | '_')*;

语言为CSharp3

当我尝试输入以下内容时,它可以正常工作,打印标识符名称:

define My_Identifier1;

但是,输入garbage也会导致garbage打印出来,就好像它是标识符一样。

为什么compileUnit不会抛出异常? 这可能是语法规则定义顺序的问题吗?

2 个答案:

答案 0 :(得分:1)

仅仅为了记录,如果你想转换,这就是它在NLT中的表现,有一些细微的差别,但没有什么难以理解的。

/*
 * Parser Rules
 */
compileUnit -> DEFINE id:IDENTIFIER END_OF_STATEMENT 
               {{ Console.WriteLine(id); return null; }};

/*
 * Lexer Rules
 */

"define" -> DEFINE;
/[0-9]+/ -> INT,Convert.ToInt32($text);
";" -> END_OF_STATEMENT;

// Whitespace
/[ \\t\\r\\n]+/ { };

// Sub-statement tokens
/[a-zA-z][a-zA-Z0-9_]*/ -> IDENTIFIER;

这只是草稿。

答案 1 :(得分:1)

此问题的解决方案是将解析器规则更改为(请注意添加EOF令牌):

public compileUnit
: DEFINE IDENTIFIER END_OF_STATEMENT EOF { Console.WriteLine($IDENTIFIER.text); };

并覆盖解析器类的ReportError方法。

public override void ReportError(Antlr.Runtime.RecognitionException e)
{
    base.ReportError(e);
    throw e;
}

现在,调用代码可以访问异常并继续开发。

值得指出的是,在遇到解决方案后,我进行了快速搜索并找到this Stack Overflow question,这似乎是相似的。这似乎不是ANTLR的一个非常明显的部分(即ANTLR如何处理BNF语法)以及该平台的新手的潜在绊脚石。