chr*_*nhy 4 antlr antlrworks antlr3
我的问题是关于在ANTLRWorks中运行以下语法:
INT :('0'..'9')+;
SEMICOLON: ';';
NEWLINE: ('\r\n'|'\n'|'\r');
STMTEND: (SEMICOLON (NEWLINE)*|NEWLINE+);
statement
: STMTEND
| INT STMTEND
;
program: statement+;
Run Code Online (Sandbox Code Playgroud)
无论选择哪个换行NL(CR / LF / CRLF)或整数,我都可以通过以下输入(以程序作为开始规则)获得以下结果:
“; NL ”或“ 32; NL ”解析没有错误。“;” 或“ 45;” (不包含换行符)将导致EarlyExitException。“ NL ”本身解析没有错误。不带分号的“ 456 NL ”会导致MismatchedTokenException。
我想要的是一个语句以换行符,分号或分号后接换行符来终止,并且我希望解析器在终止符上尽可能多地吃掉连续的换行符,因此“; NL NL NL NL ”只是一个终端,而不是四个或五个。另外,我希望文件结尾的情况也可以是有效的终止,但是我还不知道该怎么做。
那么,这有什么问题,如何使它在EOF终止呢?我对解析,ANTLR和EBNF完全陌生,并且在简单的计算器示例和参考之间的某个水平上,我没有发现太多要阅读的资料(我有The Definitive ANTLR Reference,但它确实是一个参考,前面有一个快速入门,我还没有在ANTLRWorks之外运行过,所以任何阅读建议(除了Wirth的1977 ACM论文)也将有所帮助。谢谢!
在输入如";"或的情况下,将永远不会创建"45;"令牌STMTEND。
";"将创建一个令牌:SEMICOLON,"45;"并将产生:INT SEMICOLON。
你(可能)想要的是SEMICOLON和NEWLINE永远不会进入真正的标记本身,但他们将永远是一个STMTEND。您可以通过使它们成为所谓的“碎片”规则来做到这一点:
program: statement+;
statement
: STMTEND
| INT STMTEND
;
INT : '0'..'9'+;
STMTEND : SEMICOLON NEWLINE* | NEWLINE+;
fragment SEMICOLON : ';';
fragment NEWLINE : '\r' '\n' | '\n' | '\r';
Run Code Online (Sandbox Code Playgroud)
片段规则仅可用于其他词法分析器规则,因此它们永远不会以解析器(生产)规则结尾。要强调的是:上面的语法只会创建INT或STMTEND标记。