考虑这个非常简化的示例,其中应匹配以下形式的输入
mykey -> This is the value
我的真实情况要复杂得多,但这样做可以展示我想要实现的目标。 mykey
是ID
,而在->
的右侧,我们有一组Words
。如果我使用
grammar Root;
parse
: ID '->' value
;
value
: Word+
;
ID
: ('a'..'z')+
;
Word
: ('a'..'z' | 'A'..'Z' | '0'..'9')+
;
WS
: ' ' -> skip
;
该示例将不会被解析,因为词法分析器将为第一个ID
提供is
令牌,该Word+
令牌与value
不匹配。在我的实例中,mode
- 语言有很大的不同,我想用不同的语法解析它。
我考虑过不同的解决方案:
切换词法分析器value
但是AFAIK,将词法分析器切换到其他模式只能在词法分析器规则中进行。对于这种情况和我的实际情况以及没有唯一的标记来启动和结束value
部分,这是有问题的。我需要的是像“用不同的规则标记value
”这样的东西当然是愚蠢的,因为词法分析器和解析器独立行动,一旦解析器启动,一切都已经被标记化了
为value
使用不同的语法。当我看到这一点时,导入语法的方法将不起作用,因为它始终组合两个语法导致相同的错误标记化情况。
创建第一个原始解析器,它接受整个语言,但不为value
创建正确的树。然后,我可以使用访问者并使用不同的子解析器重新分析textField
个节点,从而可能为值插入新的,正确的子树。这感觉有点笨拙。
如果您需要一个简单的实际应用程序,那么您可以考虑Java中的字符串。其中一些可能是正则表达式,需要使用完全不同的解析器进行解析。它类似于您可以在IDEA中使用的注入语言。
问题:ANTRL4中是否有一种习惯用来解析具有不同语法的特定规则?最好的情况是,如果我可以在语法级别指定它,以便生成的AST是包含注入语言的子树的外部语言的组合。
答案 0 :(得分:1)
实际上,使用模式是惯用的解决方案。只需要在识别模式保护方面有点创造性:
parser grammar RootParser ;
options {
tokenVocab = RootLexer ;
}
parse : ID RARROW value EOF ;
value : WORD+ ;
和
lexer grammar RootLexer ;
ID : [a-z]+ ;
RARROW : '->' -> pushMode(value) ;
mode value ;
EOL : [\r\n]+ -> popMode, skip ;
WORD : [a-zA-Z0-9]+ ;
WS : ' ' -> skip ;
答案 1 :(得分:1)
您可以尝试将决策内容转换为解析器:
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
因此,在解析器节点级别,您将只有单词。