我有一个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
应该支持
答案 0 :(得分:5)
这就是我最后解决问题的方法:
这个想法是在解析器规则中启用/禁用空格:
templateBody : {enableWs();} templateChunk* {disableWs();};
因此,我们必须在解析器基类中定义enableWs
和disableWs
:
public void enableWs() {
if (_input instanceof MultiChannelTokenStream) {
((MultiChannelTokenStream) _input).enable(HIDDEN);
}
}
public void disableWs() {
if (_input instanceof MultiChannelTokenStream) {
((MultiChannelTokenStream) _input).disable(HIDDEN);
}
}
现在这是什么MultiChannelTokenStream
?
CommonTokenStream
,它是仅从一个频道读取的令牌流。 MultiChannelTokenStream
是从启用的频道读取的令牌流。为了实现,我采用了CommonTokenStream的源代码,并将channel
的每个引用替换为channels
(等式比较得到包含比较)上面的语法示例实现可以在antlr4multichannel
找到