我有一个简单的语法:
grammar sample;
options { output = AST; }
assignment
: IDENT ':=' expr ';'
;
expr
: factor ('*' factor)*
;
factor
: primary ('+' primary)*
;
primary
: NUM
| '(' expr ')'
;
IDENT : ('a'..'z')+ ;
NUM : ('0'..'9')+ ;
WS : (' '|'\n'|'\t'|'\r')+ {$channel=HIDDEN;} ;
Run Code Online (Sandbox Code Playgroud)
现在我想添加一些重写规则来生成AST.从我在网上阅读的语言模式书中,我应该能够像这样修改语法:
assignment
: IDENT ':=' expr ';' -> ^(':=' IDENT expr)
;
expr
: factor ('*' factor)* -> ^('*' factor+)
;
factor
: primary ('+' primary)* -> ^('+' primary+)
;
primary
: NUM
| '(' expr ')' -> ^(expr)
;
Run Code Online (Sandbox Code Playgroud)
但它不起作用.虽然它编译得很好,但是当我运行解析器时,我得到一个RewriteEmptyStreamException错误.事情变得奇怪了.
如果我定义伪令牌ADD和MULT并使用它们而不是树节点文字,它可以正常工作.
tokens { ADD; MULT; }
expr
: factor ('*' factor)* -> ^(MULT factor+)
;
factor
: primary ('+' primary)* -> ^(ADD primary+)
;
Run Code Online (Sandbox Code Playgroud)
或者,如果我使用节点后缀表示法,它似乎也可以正常工作:
expr
: factor ('*'^ factor)*
;
factor
: primary ('+'^ primary)*
;
Run Code Online (Sandbox Code Playgroud)
这种行为差异是一个错误吗?
Bar*_*ers 10
不,不是一个错误,AFAIK.以你的expr
规则为例:
expr
: factor ('*' factor)* -> ^('*' factor+)
;
Run Code Online (Sandbox Code Playgroud)
由于*
可能不存在,它也应该不在您的AST重写规则中.所以,以上是不正确的,ANTLR抱怨它是正确的.
现在,如果您插入一个虚构的令牌,MULT
而不是:
expr
: factor ('*' factor)* -> ^(MULT factor+)
;
Run Code Online (Sandbox Code Playgroud)
一切都没关系,因为你的规则总会产生一个或多个factor
.
你可能想要做的是这样的:
expr
: (factor -> factor) ('*' f=factor -> ^('*' $expr $f))*
;
Run Code Online (Sandbox Code Playgroud)
另请参见第7章:树的建立从权威ANTLR参考.特别是"在子规则中重写规则"(第173页)和"在重写规则中引用先前规则AST"(第174/175页)中的段落.
如果要为'*'运算符生成N元树,并且所有子级都在同一级别,则可以执行以下操作:
expr
: (s=factor -> factor) (('*' factor)+ -> ^('*' $s factor+))?
;
Run Code Online (Sandbox Code Playgroud)
以下是一些将返回的示例:
Tokens: AST
factor: factor
factor '*' factor: ^('*' factor factor)
factor '*' factor '*' factor: ^('*' factor factor factor)
Run Code Online (Sandbox Code Playgroud)
Bart上面的第三个例子将生成一个嵌套树,因为每个连续迭代的$ expr结果是一个有两个子节点的节点,如下所示:
factor * factor * factor: ^('*' factor ^('*' factor factor))
Run Code Online (Sandbox Code Playgroud)
你可能不需要,因为乘法是可交换的.
归档时间: |
|
查看次数: |
2080 次 |
最近记录: |