允许空白部分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应该支持

  • 多个参数
  • 原始类型参数(整数,字符串,……)
  • 地图和清单
  • function评估

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

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

  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的源代码,并通过channels替换了每个对channel的引用(相等比较得到包含比较)

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