Java 在LR4中允许空白部分

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

我有一个antlr4语法,它是为嵌入到文本模板中的领域特定语言设计的

有两种模式:

应保留文本空白 应该忽略代码空白 语法部分示例:

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模式,因此您应该可以使用它们。但您必须发布代码和文本规则,以便我们查看您是否真的需要第二次传递。如果文本的分隔符不区分上下文,也就是说,如果这些分隔符的任何出现打开/关闭了文本部分,这可能很好。如果这取决于解析器的状态,即分隔符是分隔文本还是其他语言结构,那么我就很难理解了。但您必须发布代码和文本规则,以便我们查看您是否真的需要第二次传递。如果文本的分隔符不区分上下文,也就是说,如果这些分隔符的任何出现打开/关闭了文本部分,这可能很好。如果这取决于解析器的状态,即分隔符是分隔文本还是另一种语言结构,那么我就很难理解了。这是一个很好的解决方案。如果你总是需要全文,但你的解决方案允许更多的情况,例如,你可以启用空白,但禁用注释。很好的解决方案。如果您总是需要全文,但您的解决方案允许更多的场景,例如,您可以启用空白,但禁用注释。