允许空白部分ANTLR4

时间:2015-03-15 12:17:13

标签: java antlr antlr4

我有一个antlr4语法,专门用于嵌入到文本模板中的特定于域的语言。

有两种模式:

  • 文字(应保留空白)
  • 代码(应忽略空格)

示例语法部分:

template
  :  '{' templateBody '}'
  ;

templateBody
  : templateChunk*
  ;

templateChunk
  : code # codeChunk // dsl code, ignore whitespace
  | text # textChunk // any text, preserve whitespace
  ;

code的规则可能包含对template规则的嵌套引用。因此解析器必须支持嵌套空白/非空白部分。

也许 lexer模式可以提供帮助 - 有一些缺点:

  • 必须在另一个编译器传递
  • 中解析代码段
  • 我怀疑嵌套部分是否可以正确映射

然而,最有希望的方法似乎是操纵隐藏渠道

我的问题:是否有最佳做法来满足这些要求?是否有一个示例语法,已经解决了类似的问题?

附录

语法的其余部分可能如下:

code
  : '@' function
  ;

function
  : Identifier '(' argument ')'
  ;

argument
  : function
  | template
  ;

text
  : Whitespace+
  | Identifier
  | .+
  ;

Identifier
  : LETTER (LETTER|DIGIT)*
  ;

Whitespace
  : [ \t\n\r] -> channel(HIDDEN)
  ;

fragment LETTER
    : [a-zA-Z]
    ;

fragment DIGIT
    : [0-9]
    ;

在此示例中,code有一个虚拟实现,指出它可以包含嵌套的代码/模板部分。实际上code应该支持

  • 多个参数
  • 基本类型参​​数(整数,字符串,......)
  • 地图和列表
  • 功能评估
  • ...

1 个答案:

答案 0 :(得分:5)

这就是我最后解决问题的方法:

这个想法是在解析器规则中启用/禁用空格:

 templateBody : {enableWs();} templateChunk* {disableWs();};

因此,我们必须在解析器基类中定义enableWsdisableWs

public void enableWs() {
    if (_input instanceof MultiChannelTokenStream) {
        ((MultiChannelTokenStream) _input).enable(HIDDEN);
    }
}

public void disableWs() {
    if (_input instanceof MultiChannelTokenStream) {
        ((MultiChannelTokenStream) _input).disable(HIDDEN);
    }
}

现在这是什么MultiChannelTokenStream

  • Antlr4定义CommonTokenStream,它是仅从一个频道读取的令牌流。
  • MultiChannelTokenStream是从启用的频道读取的令牌流。为了实现,我采用了CommonTokenStream的源代码,并将channel的每个引用替换为channels(等式比较得到包含比较)

上面的语法示例实现可以在antlr4multichannel

找到