允许空白部分 ANTLR4
Allow Whitespace sections ANTLR4
我有一个 antlr4 语法,专为嵌入到文本模板中的领域特定语言而设计。
有两种模式:
- 文本(应保留空格)
- 代码(应忽略空格)
示例语法部分:
template
: '{' templateBody '}'
;
templateBody
: templateChunk*
;
templateChunk
: code # codeChunk // dsl code, ignore whitespace
| text # textChunk // any text, preserve whitespace
;
code
的规则可能包含对 template
规则的嵌套引用。所以解析器必须支持嵌套 whitespace/non-whitespace 部分。
也许 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/template 部分。其实code
应该支持
- 多个参数
- 原始类型参数(整数、字符串...)
- 地图和列表
- 函数求值
- ...
最后我是这样解决问题的:
想法是 enable/disable 解析器规则中的空格:
templateBody : {enableWs();} templateChunk* {disableWs();};
所以我们必须在我们的解析器基础中定义 enableWs
和 disableWs
class:
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
(相等比较包含比较)
找到使用上述语法的示例实现
我有一个 antlr4 语法,专为嵌入到文本模板中的领域特定语言而设计。
有两种模式:
- 文本(应保留空格)
- 代码(应忽略空格)
示例语法部分:
template
: '{' templateBody '}'
;
templateBody
: templateChunk*
;
templateChunk
: code # codeChunk // dsl code, ignore whitespace
| text # textChunk // any text, preserve whitespace
;
code
的规则可能包含对 template
规则的嵌套引用。所以解析器必须支持嵌套 whitespace/non-whitespace 部分。
也许 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/template 部分。其实code
应该支持
- 多个参数
- 原始类型参数(整数、字符串...)
- 地图和列表
- 函数求值
- ...
最后我是这样解决问题的:
想法是 enable/disable 解析器规则中的空格:
templateBody : {enableWs();} templateChunk* {disableWs();};
所以我们必须在我们的解析器基础中定义 enableWs
和 disableWs
class:
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
(相等比较包含比较)