ANTLR:如何生成一棵有 2 个以上子节点的树?

发布于 2024-10-06 13:54:02 字数 583 浏览 3 评论 0原文

给定语法

parse   : expr EOF -> ^(ROOT expr);
expr    : atom ('|'^ atom)*;
atom    : LITERAL | ('('! expr ')'!);

LITERAL : 'a'..'z';
WS      : (' '|'\t'|'\r'|'\n'){Skip();};

和输入,

a|b|c

我得到一棵看起来像

http://graph.gafol 的 树.net/pic/dsqoQhzgs.png

而我想要一棵看起来像

http://graph.gafol.net/pic/dsrGWVUfz.png

我如何在语法中表达这一点?

Given the grammar,

parse   : expr EOF -> ^(ROOT expr);
expr    : atom ('|'^ atom)*;
atom    : LITERAL | ('('! expr ')'!);

LITERAL : 'a'..'z';
WS      : (' '|'\t'|'\r'|'\n'){Skip();};

And input,

a|b|c

I get a tree that looks like,

http://graph.gafol.net/pic/dsqoQhzgs.png

Whereas I'd like a tree that looks like,

http://graph.gafol.net/pic/dsrGWVUfz.png

How would I express that in the grammar?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

夏花。依旧 2024-10-13 13:54:02

这有点棘手。您可以通过使用语法谓词 (LOOK-AHEAD -TOKENS-HERE)=> 在匹配“OR-链”之前:

expr
  :  (atom '|')=> atom ('|' atom)+ -> ^('|' atom+)
  |  atom
  ;

正确处理 a|b|ca|b一个。

但您可能想解释一下您实际上要解析的语言:可能有更好(更优雅?)的方式来表达它。

为什么您不想像第一个图中那样拥有 AST?当根(操作数)只有两个子项时,计算表达式很容易,对吧?

It's a bit tricky. You could do it by using a syntactic predicate (LOOK-AHEAD-TOKENS-HERE)=> before matching an "OR-chain":

expr
  :  (atom '|')=> atom ('|' atom)+ -> ^('|' atom+)
  |  atom
  ;

which properly handles a|b|c, a|b and a.

But you might want to explain what language you're actually trying to parse: there might be better (more elegant?) ways to express it.

Why wouldn't you want to have an AST as in your first diagram? Evaluating expressions is easy when the root (operand) has only two children, right?

伏妖词 2024-10-13 13:54:02
parse   : expr EOF -> ^(ROOT expr);
expr    : atom ('|'^ atom)* -> atom+;
atom    : LITERAL | ('('! expr ')'!);

LITERAL : 'a'..'z';
WS      : (' '|'\t'|'\r'|'\n'){Skip();};

我认为这可以通过添加重写规则来实现,但我现在没有 antlrworks,所以我不能确定。但它已经很接近了,所以请尝试一下,并在必要时修改重写语法。

parse   : expr EOF -> ^(ROOT expr);
expr    : atom ('|'^ atom)* -> atom+;
atom    : LITERAL | ('('! expr ')'!);

LITERAL : 'a'..'z';
WS      : (' '|'\t'|'\r'|'\n'){Skip();};

I think this will do it by adding a rewrite rule but I don't have antlrworks right now so I can't be sure. But it's close so give it a shot and modify the rewrite syntax if necessary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文