2

我有一条要拆分的规则,因为我也想在其他规则中重复使用相同的子规则。原始版本工作正常:

type
  : ( basicType -> basicType )
  ( '*' -> ^(TYPE_POINTER basicType)
  | '[' ']' -> ^(TYPE_DYN_ARRAY basicType)
  | '[' IntegerLiteral ']' -> ^(TYPE_STATIC_ARRAY IntegerLiteral basicType)
  | '[' IntegerLiteral '..' IntegerLiteral ']' -> ^(REF_TYPE_SLICE IntegerLiteral IntegerLiteral basicType)
  | '[' type ']' -> ^(TYPE_MAP_ARRAY type basicType)
  )?
  ;

这条规则可以将一个普通类型(basicType,它可以是引用或主要类型,如 int、char 等)放在不同的 AST 节点下,使其成为指针、数组等。这在类似 C 的语言中很常见。

但是,如果我这样拆分:

basicType2
  : '*' -> ^(TYPE_POINTER)
  | '[' ']' -> ^(TYPE_DYN_ARRAY)
  | '[' IntegerLiteral ']' -> ^(TYPE_STATIC_ARRAY IntegerLiteral)
  | '[' IntegerLiteral '..' IntegerLiteral ']' -> ^(REF_TYPE_SLICE IntegerLiteral IntegerLiteral)
  | '[' type ']' -> ^(TYPE_MAP_ARRAY type)
  ;

type
  : ( basicType -> basicType )
    ( basicType2 -> ^(basicType2 basicType) )?
  ;

一切看起来都很好,解析不会受到影响,但是在 AST 中,basicType2 的孩子完全丢失了。在 TYPE_STATIC_ARRAY、REF_TYPE_SLICE 或 TYPE_MAP_ARRAY 的情况下,只会将根复制到类型之上,但缺少子节点。

我调试了解析器代码,在我看来,CommonTree 类的复制构造函数在不复制子项时调用,只有令牌和源范围信息。有没有办法通过重写规则将 CommonTree 节点及其子节点带到另一个节点的顶​​部?

4

1 回答 1

2

始终使用单个标记作为树的根:而不是另一棵树,就像你在做的basicType2那样:

type
  : ( basicType -> basicType )
    ( basicType2 -> ^(basicType2 basicType) )?
  ;

试试这个:

grammar ...

options { ... }

tokens { T2; }

...

type
  : ( basicType -> basicType )
    ( basicType2 -> ^(T2 basicType2 basicType) )?
  ;

...
于 2012-08-06T12:05:22.047 回答