ANTLR贪婪地解析,即使它可以匹配高优先级规则



我使用以下ANTLR语法来定义函数。

definition_function
    : DEFINE FUNCTION function_name '[' language_name ']'
      RETURN attribute_type '{' function_body '}'
    ;
function_name
    : id
    ;
language_name
    : id
    ;
function_body
    : SCRIPT
    ;
SCRIPT
    :   '{' ('u0020'..'u007e' | ~( '{' | '}' ) )* '}' 
        { setText(getText().substring(1, getText().length()-1)); }
    ;

但当我试图解析下面这样的两个函数时,

define function concat[Scala] return string {
  var concatenatedString = ""
  for(i <- 0 until data.length) {
     concatenatedString += data(i).toString
  }
  concatenatedString
};
define function concat[JavaScript] return string {
  var str1 = data[0];
  var str2 = data[1];
  var str3 = data[2];
  var res = str1.concat(str2,str3);
  return res;
};

然后ANTLR不像两个函数定义那样解析它,而是像一个具有以下主体的函数

  var concatenatedString = ""
  for(i <- 0 until data.length) {
     concatenatedString += data(i).toString
  }
  concatenatedString
};
define function concat[JavaScript] return string {
  var str1 = data[0];
  var str2 = data[1];
  var str3 = data[2];
  var res = str1.concat(str2,str3);
  return res;

你能解释一下这种行为吗?函数的主体可以包含任何内容。如何正确定义此语法?

您的规则非常匹配,因为规则'{' ('u0020'..'u007e' | ~( '{' | '}' ) )* '}'中的'u0020'..'u007e'{}都匹配。

如果你这样定义你的规则:

SCRIPT
    :   '{' ( SCRIPT | ~( '{' | '}' ) )* '}' 
    ;

但是,当脚本块包含(例如)包含{}的字符串或注释时,这将失败。以下是一种匹配SCRIPT令牌的方法,包括可能包含{和"}"的注释和字符串文字:

SCRIPT
 : '{' SCRIPT_ATOM* '}'
 ;
fragment SCRIPT_ATOM
 : ~[{}]
 | '"' ~["]* '"'
 | '//' ~[rn]*
 | SCRIPT
 ;

一个完整的语法,正确地解析你的输入,然后看起来像这样:

grammar T;
parse
 : definition_function* EOF
 ;
definition_function
 : DEFINE FUNCTION function_name '[' language_name ']' RETURN attribute_type SCRIPT ';'
 ;
function_name
 : ID
 ;
language_name
 : ID
 ;
attribute_type
 : ID
 ;
DEFINE
 : 'define'
 ;
FUNCTION
 : 'function'
 ;
RETURN
 : 'return'
 ;
ID
 : [a-zA-Z_] [a-zA-Z_0-9]*
 ;
SCRIPT
 : '{' SCRIPT_ATOM* '}'
 ;
SPACES
 : [ trn]+ -> skip
 ;
fragment SCRIPT_ATOM
 : ~[{}]
 | '"' ~["]* '"'
 | '//' ~[rn]*
 | SCRIPT
 ;

它还正确地解析以下输入:

define function concat[JavaScript] return string {
  for (;;) { 
    while (true) { } 
  }
  var s = "}"
  // }
  return s 
};

除非您绝对需要SCRIPT作为令牌(由lexer规则识别),否则您可以使用识别嵌套块的解析器(下面的规则)。这里包含的语法应该将您的示例解析为两个不同的函数定义。

DEFINE : 'define';
FUNCTION : 'function';
RETURN : 'return';
ID : [A-Za-z]+;
ANY : . ;
WS : [ rtn]+ -> skip ;
test : definition_function* ;
definition_function
    : DEFINE FUNCTION function_name '[' language_name ']'
      RETURN attribute_type block ';'
    ;
function_name : id ;
language_name : id ;
attribute_type : 'string' ;
id : ID;
block
    : '{' ( ( ~('{'|'}') )+ | block)* '}'
    ;

相关内容

  • 没有找到相关文章

最新更新