如何避免使用ANTLR3构建中间体和无用的AST节点? [英] How to avoid building intermediates and useless AST nodes with ANTLR3?

查看:92
本文介绍了如何避免使用ANTLR3构建中间体和无用的AST节点?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我写了一个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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆