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,在我接受之前,我会让它打开一段时间。事实上,这是我以前做过的工作。我想我试着清理代币流,所以我给了格罗森伯格的解决方案一次机会。我会看看我最终会得到什么。事实上,这就是我以前做过的工作。我想我试着清理代币流,所以我给了格罗森伯格的解决方案一次机会。我看看我会得到什么。