Parsing ANTLR4:为特定规则调用不同的子解析器

Parsing ANTLR4:为特定规则调用不同的子解析器,parsing,antlr4,Parsing,Antlr4,考虑这个非常简化的示例,其中应匹配以下形式的输入 mykey -> This is the value 我的真实情况要复杂得多,但这将有助于展示我试图实现的目标mykey是一个ID,而在->的右侧,我们有一组单词。如果我使用 grammar Root; parse : ID '->' value ; value : Word+ ; ID : ('a'..'z')+ ; Word : ('a'..'z' | 'A'..

考虑这个非常简化的示例,其中应匹配以下形式的输入

mykey -> This is the value
我的真实情况要复杂得多,但这将有助于展示我试图实现的目标
mykey
是一个
ID
,而在
->
的右侧,我们有一组
单词。如果我使用

grammar Root;

parse
    : ID '->' value
    ;

value
    : Word+
    ;

ID
    : ('a'..'z')+
    ;


Word
    : ('a'..'z' | 'A'..'Z' | '0'..'9')+
    ;

WS
    : ' ' -> skip
    ;
不会解析该示例,因为lexer将为第一个
is
提供一个
ID
标记,该标记与
Word+
不匹配。在我的真实示例中,
-语言有很大的不同,我想用不同的语法来解析它

我曾考虑过不同的解决办法:

  • 切换lexer
    模式
    但是,请注意,只有在lexer规则中才能将lexer切换到其他模式。这对于本例和我的真实案例是有问题的,并且没有唯一的标记来开始和结束
    部分。我需要的是类似于“使用不同规则标记化
    value
    ”的东西,这当然是愚蠢的,因为lexer和parser是独立工作的,一旦解析器启动,一切都已经标记化了

  • 值使用不同的语法。如果我看对了,那么导入语法的方法就行不通了,因为它总是将两个语法组合在一起,导致相同的错误标记化情况

  • 创建第一个粗糙的解析器,它接受整个语言,但不为
    值创建正确的树。然后,我可以使用一个访问者,使用不同的子解析器重新分析
    value
    节点,可能会为value插入一个新的、正确的子树。这感觉有点笨拙

  • 如果需要一个简单的现实世界应用程序,那么可以考虑java中的字符串。其中一些可能是需要使用完全不同的解析器解析的正则表达式。它类似于您可以在IDEA内部使用的注入语言


    问题:在ANTRL4中是否有一种惯用的方法来解析具有不同语法的特定规则?最好的情况是,如果我可以在语法级别指定它,那么生成的AST是外部语言的组合,其中包含注入语言的一个子树。

    实际上,使用模式是惯用的解决方案。只需要在识别模式卫士时有点创造性:

    parser grammar RootParser ;
    
    options {
        tokenVocab = RootLexer ;
    }
    
    parse   : ID RARROW value EOF ;
    value   : WORD+ ;
    


    实际上,使用模式是惯用的解决方案。只需要在识别模式卫士时有点创造性:

    parser grammar RootParser ;
    
    options {
        tokenVocab = RootLexer ;
    }
    
    parse   : ID RARROW value EOF ;
    value   : WORD+ ;
    


    您可以尝试将单词是什么的决策转移到解析器中:

    grammar Root;
    
    parse
      : ID '->' value
      ;
    
    value
      : word+
      ;
    
    word : Word | ID;
    
    //the same lexer rules as above
    
    这将解析

    This  -> Word -> word
    is    -> ID   -> word
    the   -> ID   -> word
    value -> ID   -> word
    

    因此,在解析器节点级别,您将只有单词。

    您可以尝试将单词是什么的决策转移到解析器中:

    grammar Root;
    
    parse
      : ID '->' value
      ;
    
    value
      : word+
      ;
    
    word : Word | ID;
    
    //the same lexer rules as above
    
    这将解析

    This  -> Word -> word
    is    -> ID   -> word
    the   -> ID   -> word
    value -> ID   -> word
    

    因此,在解析器节点级别,您将只有单词。

    是的,我想您是对的。在过去的两个小时里,我一直在思考这个问题,似乎我可以让它适用于我的真实例子。谢谢你写了一个答案。你得到了我的+1,我会让它打开一段时间再接受。是的,我想你是对的。在过去的两个小时里,我一直在思考这个问题,似乎我可以让它适用于我的真实例子。谢谢你写了一个答案。你得到了我的+1,在我接受之前,我会让它打开一段时间。事实上,这是我以前做过的工作。我想我试着清理代币流,所以我给了格罗森伯格的解决方案一次机会。我会看看我最终会得到什么。事实上,这就是我以前做过的工作。我想我试着清理代币流,所以我给了格罗森伯格的解决方案一次机会。我看看我会得到什么。