使用ANTLR3解析换行符,EOF作为语句结束标记

时间:2011-04-17 20:56:34

标签: antlr antlr3 antlrworks

我的问题是关于在ANTLRWorks中运行以下语法:

INT :('0'..'9')+;
SEMICOLON: ';';
NEWLINE: ('\r\n'|'\n'|'\r');
STMTEND: (SEMICOLON (NEWLINE)*|NEWLINE+);

statement
    : STMTEND
    | INT STMTEND
    ;

program: statement+;

我使用以下输入获得以下结果(使用 program 作为启动规则),无论哪个换行符 NL (CR / LF / CRLF)或整数I中选择:

“; NL ”或“32; NL ”解析时没有错误。 “;”或“45;” (没有换行符)导致EarlyExitException。 “ NL ”本身解析没有错误。 “456 NL ”,没有分号,会导致MismatchedTokenException。

我想要的是一个语句由换行符,分号或分号后跟换行符终止,我希望解析器在终止时吃尽可能多的连续换行符,所以“; NL NL NL NL “只是一个终止,而不是四个或五个。另外,我希望文件结尾的案例也是一个有效的终止,但我不知道该怎么做。

所以这有什么问题,我怎样才能让它在EOF中很好地终止?我对所有的解析,ANTLR和EBNF都是全新的,我在简单的计算器示例和参考之间的某个层面上找不到很多要读取的材料(我有明确的ANTLR参考,但它真的一个参考,前面快速启动,我还没有在ANTLRWorks之外运行,所以任何阅读建议(除了Wirth的1977 ACM论文)也会有所帮助。谢谢!

1 个答案:

答案 0 :(得分:5)

如果输入";""45;",则永远不会创建令牌STMTEND

";"将创建一个令牌:SEMICOLON"45;"将生成:INT SEMICOLON

您(可能)想要的是SEMICOLONNEWLINE永远不会将其变为真实的令牌,但它们始终是STMTEND。你可以通过制作所谓的“片段”规则来实现这一目标:

program: statement+;

statement
 : STMTEND
 | INT STMTEND
 ;

INT     : '0'..'9'+;
STMTEND : SEMICOLON NEWLINE* | NEWLINE+;

fragment SEMICOLON : ';';
fragment NEWLINE   : '\r' '\n' | '\n' | '\r';

片段规则仅适用于其他词法分析器规则,因此它们永远不会出现在解析器(生产)规则中。要强调:上面的语法只能创建INTSTMTEND个令牌。