Java 在LR4中允许空白部分
我有一个antlr4语法,它是为嵌入到文本模板中的领域特定语言设计的 有两种模式: 应保留文本空白 应该忽略代码空白 语法部分示例:Java 在LR4中允许空白部分,java,antlr,antlr4,Java,Antlr,Antlr4,我有一个antlr4语法,它是为嵌入到文本模板中的领域特定语言设计的 有两种模式: 应保留文本空白 应该忽略代码空白 语法部分示例: template : '{' templateBody '}' ; templateBody : templateChunk* ; templateChunk : code # codeChunk // dsl code, ignore whitespace | text # textChunk // any text, preser
template
: '{' templateBody '}'
;
templateBody
: templateChunk*
;
templateChunk
: code # codeChunk // dsl code, ignore whitespace
| text # textChunk // any text, preserve 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]
;
在这个示例中,代码有一个虚拟实现,指出它可以包含嵌套的代码/模板部分。实际上,代码应该支持
多参数
基元类型参数int、string、。。。
地图和清单
功能评估
...
这就是我最后解决问题的方法: 其思想是在解析器规则中启用/禁用空白:
templateBody : {enableWs();} templateChunk* {disableWs();};
因此,我们必须在解析器基类中定义启用和禁用:
public void enableWs() {
if (_input instanceof MultiChannelTokenStream) {
((MultiChannelTokenStream) _input).enable(HIDDEN);
}
}
public void disableWs() {
if (_input instanceof MultiChannelTokenStream) {
((MultiChannelTokenStream) _input).disable(HIDDEN);
}
}
现在这个多通道令牌流是什么
Antlr4定义了一个CommonTokenStream,它是一个仅从一个通道读取的令牌流。
MultiChannelTokenStream是从启用的通道读取的令牌流。对于实现,我获取了CommonTokenStream的源代码,并将每个对通道的引用替换为通道相等比较
上述语法的示例实现可以在中找到,这就是我最后解决问题的方法: 其思想是在解析器规则中启用/禁用空白:
templateBody : {enableWs();} templateChunk* {disableWs();};
因此,我们必须在解析器基类中定义启用和禁用:
public void enableWs() {
if (_input instanceof MultiChannelTokenStream) {
((MultiChannelTokenStream) _input).enable(HIDDEN);
}
}
public void disableWs() {
if (_input instanceof MultiChannelTokenStream) {
((MultiChannelTokenStream) _input).disable(HIDDEN);
}
}
现在这个多通道令牌流是什么
Antlr4定义了一个CommonTokenStream,它是一个仅从一个通道读取的令牌流。
MultiChannelTokenStream是从启用的通道读取的令牌流。对于实现,我获取了CommonTokenStream的源代码,并将每个对通道的引用替换为通道相等比较
可以在中找到具有上述语法的示例实现。您可以使用push/pop lexer模式,因此您应该可以使用它们。但您必须发布代码和文本规则,以便我们查看您是否真的需要第二次传递。如果文本的分隔符不区分上下文,也就是说,如果这些分隔符的任何出现打开/关闭了文本部分,这可能很好。如果这取决于解析器的状态,即分隔符是分隔文本还是其他语言结构,那么我就很难理解了。但您必须发布代码和文本规则,以便我们查看您是否真的需要第二次传递。如果文本的分隔符不区分上下文,也就是说,如果这些分隔符的任何出现打开/关闭了文本部分,这可能很好。如果这取决于解析器的状态,即分隔符是分隔文本还是另一种语言结构,那么我就很难理解了。这是一个很好的解决方案。如果你总是需要全文,但你的解决方案允许更多的情况,例如,你可以启用空白,但禁用注释。很好的解决方案。如果您总是需要全文,但您的解决方案允许更多的场景,例如,您可以启用空白,但禁用注释。