语法:
grammar Test;
file: (procDef | statement)* EOF;
procDef: 'procedure' ID NL statement+ ;
statement: 'statement'? NL;
WS: (' ' | '\t') -> skip;
NL: ('\r\n' | '\r' | '\n');
ID: [a-zA-Z0-9]+;
测试数据:
statement
procedure Proc1
statement
statement
解析器执行我想要的操作(即语句+贪婪),但它报告了歧义,因为它不知道最后一个语句是属于procDef还是文件(据我理解)。 由于谓词是语言依赖的,我不想使用谓词。 当一个不属于它的语句(例如“程序”)发生时,该程序应该结束。 我也希望将语句绑定到过程以避免以后重新排列结构。
似乎我应该稍微扩展我的测试数据(但是我会留下原件,因为它很小并显示我想要解决的模糊性)。 我希望能够处理这样的情况:
statement
procedure Proc1
statement
statement
procedure Proc2
statement
statement
procedure Proc2a
statement
statement
global
statement
procedure Proc3
statement
statement
(缩进不重要。)我可以在没有类似
之类的谓词的情况下做到这一点。file: (
commonStatement
| globalStatement
)* EOF;
procDef: 'procedure' ID NL commonStatement+ ;
commonStatement: 'statement'? NL;
globalStatement: 'global' NL | procDef (globalStatement | EOF);
但是随着每个连续的procDef,树变得更深,这感觉非常不合需要。 那么带谓词的解决方案实际上更可取。
@parser::members { boolean inProc; }
file: (
{!inProc}? commonStatement
| globalStatement
)* EOF;
procDef: 'procedure' ID {inProc = true;} NL commonStatement+ ;
commonStatement: 'statement'? NL;
globalStatement: ('global' NL {inProc = false;} | procDef) ;
情况实际上比这更糟糕,因为全局可访问的commonStatements可以在没有干预的globalStatement(可通过gotos访问)的情况下发生,但是解析器无法区分它和属于该过程的语句,所以我的计划是只是不鼓励这样的使用(我不认为它很常见)。事实上,将转换为程序代码也是完全合法的...... 可能结果是,最后我将不得不检查运行时路径(范围在运行时非常确定),并且语法可能最终会像
file: (
commonStatement
| globalStatement
| procDef
)* EOF;
procDef: 'procedure' ID NL procStatement*;
commonStatement: 'statement'? NL;
procStatement: 'proc' NL;
globalStatement: 'global' NL;
我们会看到......
答案 0 :(得分:0)
根据您的标准,声明不可能遵循procDef。你完全有权使用这种方式设计一种语言,但我希望你能为常见问题解答做好准备“如何编写一个在程序定义之后的语句。”
编写语法很容易:
file: statement* procDef* EOF;