ANTLR4:为特定规则

时间:2017-11-04 08:07:55

标签: parsing antlr4

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

mykey -> This is the value

我的真实情况要复杂得多,但这样做可以展示我想要实现的目标。 mykeyID,而在->的右侧,我们有一组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 - 语言有很大的不同,我想用不同的语法解析它。

我考虑过不同的解决方案:

  1. 切换词法分析器value但是AFAIK,将词法分析器切换到其他模式只能在词法分析器规则中进行。对于这种情况和我的实际情况以及没有唯一的标记来启动和结束value部分,这是有问题的。我需要的是像“用不同的规则标记value”这样的东西当然是愚蠢的,因为词法分析器和解析器独立行动,一旦解析器启动,一切都已经被标记化了

  2. value使用不同的语法。当我看到这一点时,导入语法的方法将不起作用,因为它始终组合两个语法导致相同的错误标记化情况。

  3. 创建第一个原始解析器,它接受整个语言,但不为value创建正确的树。然后,我可以使用访问者并使用不同的子解析器重新分析textField个节点,从而可能为值插入新的,正确的子树。这感觉有点笨拙。

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

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

2 个答案:

答案 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

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