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

Aya*_*ash 6 antlr antlr4

我使用以下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)); }
    ;
Run Code Online (Sandbox Code Playgroud)

但是当我尝试解析下面的两个函数时,

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;
};
Run Code Online (Sandbox Code Playgroud)

然后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;
Run Code Online (Sandbox Code Playgroud)

你能解释一下这种行为吗?函数体可以包含任何内容.我怎样才能正确定义这个语法?

Mar*_* Q. 0

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

DEFINE : 'define';
FUNCTION : 'function';
RETURN : 'return';
ID : [A-Za-z]+;
ANY : . ;
WS : [ \r\t\n]+ -> 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)* '}'
    ;
Run Code Online (Sandbox Code Playgroud)