如何避免使用 ANTLR3 构建中间体和无用的 AST 节点? [英] How to avoid building intermediates and useless AST nodes with ANTLR3?
问题描述
我编写了一个 ANTLR3 语法,将其细分为更小的规则以提高可读性.例如:
I wrote an ANTLR3 grammar subdivided into smaller rules to increase readability. For example:
messageSequenceChart:
'msc' mscHead bmsc 'endmsc' end
;
# Where mscHead is a shortcut to :
mscHead:
mscName mscParameterDecl? timeOffset? end
mscInstInterface? mscGateInterface
;
我知道内置的 ANTLR AST 构建功能允许用户声明不会出现在最终 AST 中的中间 AST 节点.但是如果您手动构建 AST 呢?
I know the built-in ANTLR AST building feature allows the user to declare intermediate AST nodes that won't be in the final AST. But what if you build the AST by hand?
messageSequenceChart returns [msc::MessageSequenceChart* n = 0]:
'msc' mscHead bmsc'endmsc' end
{
$n = new msc::MessageSequenceChart(/* mscHead subrules accessors like $mscHead.mscName.n ? */
$bmsc.n);
}
;
mscHead:
mscName mscParameterDecl? timeOffset? end
;
文档没有谈论这样的事情.所以看起来我必须为每个中间规则创建节点才能访问它们的子规则结果.
The documentation does not talk about such a thing. So it looks like I will have to create nodes for every intermediate rules to be able to access their subrules result.
有人知道更好的解决方案吗?
Does anyone know a better solution ?
谢谢.
推荐答案
您可以通过让子规则返回多个值并仅访问您感兴趣的值来解决此问题.
You can solve this by letting your sub-rule(s) return multiple values and accessing only those you're interested in.
下面的演示展示了如何做到这一点.尽管它不是用 C 编写的,但我相信您可以对其进行调整以使其适合您的需要:
The following demo shows how to do it. Although it is not in C, I am confident that you'll be able to adjust it so that it fits your needs:
grammar Test;
parse
: sub EOF {System.out.printf("second=\%s\n", $sub.second);}
;
sub returns [String first, String second, String third]
: a=INT b=INT c=INT
{
$first = $a.text;
$second = $b.text;
$third = $c.text;
}
;
INT
: '0'..'9'+
;
SPACE
: ' ' {$channel=HIDDEN;}
;
如果您使用生成的解析器解析输入 "12 34 56"
,second=34
将打印到控制台,运行后您可以看到:
And if your parse the input "12 34 56"
with the generated parser, second=34
is printed to the console, as you can see after running:
import org.antlr.runtime.*;
public class Main {
public static void main(String[] args) throws Exception {
TestLexer lex = new TestLexer(new ANTLRStringStream("12 34 56"));
TokenStream tokens = new TokenRewriteStream(lex);
TestParser parser = new TestParser(tokens);
parser.parse();
}
}
因此,来自 parse
规则的快捷方式,如 $sub.INT
或 $sub.$a
来访问三个中的一个INT
令牌,不可能,不幸的是.
So, a shortcut from the parse
rule like $sub.INT
, or $sub.$a
to access one of the three INT
tokens, in not possible, unfortunately.
这篇关于如何避免使用 ANTLR3 构建中间体和无用的 AST 节点?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!