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

ANTLR贪婪地解析,即使它可以匹配高优先级规则,antlr,antlr4,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 ; SCR

我使用以下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;
};
定义函数concat[Scala]返回字符串{
var concatenatedString=“”

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

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)* '}'
    ;

您的规则与此非常匹配,因为
'\u0020'..'\u007e'
规则中的
'{'('\u0020'..'\u007e'| ~('{'.}'))*'}'
同时匹配
{
}

如果您这样定义规则,则规则应该有效:

SCRIPT
    :   '{' ( 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
 : [ \t\r\n]+ -> skip
 ;

fragment SCRIPT_ATOM
 : ~[{}]
 | '"' ~["]* '"'
 | '//' ~[\r\n]*
 | SCRIPT
 ;
但是,如果脚本块包含字符串或注释,并且这些字符串或注释包含
{
}
,则此操作将失败。下面是一种匹配
脚本
标记的方法,包括注释和可能包含
{
和'}'的字符串文字:

SCRIPT
 : '{' SCRIPT_ATOM* '}'
 ;

fragment SCRIPT_ATOM
 : ~[{}]
 | '"' ~["]* '"'
 | '//' ~[\r\n]*
 | SCRIPT
 ;
正确解析输入的完整语法如下所示:

SCRIPT
    :   '{' ( 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
 : [ \t\r\n]+ -> skip
 ;

fragment SCRIPT_ATOM
 : ~[{}]
 | '"' ~["]* '"'
 | '//' ~[\r\n]*
 | SCRIPT
 ;
它还正确解析以下输入:

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

请注意,lexer规则还可以包含递归(lexer)规则。请注意,在解析器规则中,
~(“{'.}')
{
}
以外的任何字符都不匹配,而是与
{
}
匹配的令牌以外的任何令牌。