使用重写规则在Antlr中折叠一些AST子树

时间:2011-02-11 12:05:39

标签: tree rewrite antlr

我有以下语法(我只显示重要的部分)

packageDeclaration
    :   PACKAGE qualifiedIdentifier SEMI -> ^(PACKAGE qualifiedIdentifier+) 
    ;

qualifiedIdentifier
    :   (   IDENT               ->  IDENT
        )
        (   DOT ident=IDENT     ->  ^(DOT $qualifiedIdentifier $ident)
        )*
    ;

让我说我有一个包“dec。”包“a.b.c”(Java解析器顺便说一句)

我现在得到的是某种形式 (包(。(。a b)c))

我想要的是内联包装以便我得到 (包a.b.c)

我不想更改qualifiedIdentifier的重写,但仅限于packageDeclaration。

我该怎么做。

我理解别名和+现在是什么意思。但是我仍然不清楚重写规则中qualifiedIdentifier和$ qualifiedIdentifier之间的区别。

至于我的第二个问题,我的意思是我删除了qualifiedIdentifier的重写规则,对于包我有以下内容:

packageDeclaration
    :   PACKAGE ident=qualifiedIdentifier SEMI -> ^(PACKAGE $ident+) 
    ;

我得到的结果是嵌套的标记,如:

 (package
    (a) [end:a]

    (.) [end:.]

    (b) [end:b]

    (.) [end:.]

    (c) [end:c]
  ) [end:package]

Each token is represented as "(<token's text property>) [end: <token's text property>]"

我希望在上面的输出中清楚但我有一个带有5个孩子的父令牌(包)。现在他们处于正确的顺序和所有这一切。我想要的是同一个父母只有一个孩子,如:

 (package
    (a.b.c) [end:a.b.c]
  ) [end:package]

1 个答案:

答案 0 :(得分:1)

如果您要从树中删除DOT,只保留来自a的令牌bcimport a.b.c;(带{ {root}当然是{1}}尝试:

PACKAGE

或使用qualifiedIdentifier : IDENT (DOT IDENT)* -> IDENT+ ; ,只需删除重写规则:

DOT

顺便说一下,您的qualifiedIdentifier : IDENT (DOT IDENT)* ; 中有错误:

packageDeclaration

packageDeclaration : PACKAGE qualifiedIdentifier SEMI -> ^(PACKAGE qualifiedIdentifier+) ; 应该是qualifiedIdentifier+

  

Coder写道:

     

我不想更改qualifiedIdentifier的重写,但仅限于packageDeclaration。

这是不可能的。

除非您在qualifiedIdentifier内未使用qualifiedIdentifier,否则您可以执行以下操作:

packageDeclaration

修改

关于你的意见:

  

Coder写道:

     

我对重写规则中+的含义有点困惑。这里的文档antlr.org/wiki/display/ANTLR3/Tree+construction说你可以把树分成“a:(^(ID INT))+ - &gt; INT + ID +; //将树分成序列” 。

从规则:

packageDeclaration
  :  PACKAGE IDENT (DOT IDENT)* SEMI -> ^(PACKAGE IDENT+)
  ;

a : (^(ID INT))+ -> INT+ ID+ ; 表示有一个或多个(^(ID INT))+和一个或多个ID,只有这样才能在重写规则中使用INT(所有内容) - >&gt;的右边。

另一方面,你有:

+

那里只有一个packageDeclaration : PACKAGE qualifiedIdentifier SEMI ; ,所以你只能在重写规则中使用那个sinle qualifiedIdentifier(没有qualifiedIdentifier!)

  

Coder写道:

     

我也很困惑在重写规则中指定别名与“PACKAGE ident:qualifiedIdentifier - &gt; $ ident”vs之间的区别,使用quanlifiedIdentifier vs $ quanlifiedIdentifier

如果不明显哪个规则应该放在树中的哪个位置,或者如果您想要更好地控制子项的放置方式,则可以使用别名。例如,给定规则:

+

并且您希望第一个name : ID '.' ID ; 成为正确的孩子。这样做的:

ID

将第一个ID作为左子项。为了使它成为正确的孩子,请执行以下操作:

name
  :  ID '.' ID > ^(NAME ID ID)
  ;

编辑II

  

Coder写道:

     

我得到的结果是嵌套的标记,如:

     

<强> (SNIP)

     

每个令牌都表示为......

好的,我明白你的意思了。你必须明白解析器是“词法分析器”的“馈送”。词法分析器会填充字符输入并从这些字符创建标记(name : a=ID '.' b=ID > ^(NAME $b $a) ; 就是这样的标记,就像IDENT一样)。然后将这些标记传递给解析器。解析器不能只创建或合并令牌。所以答案是:你想要的东西不容易做到,你的语法里面的“ANTLR语法”当然是不可能的。