ANTLR贪婪地解析,即使它可以匹配高优先级规则
我使用以下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
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)规则。请注意,在解析器规则中,~(“{'.}')
与{
和}
以外的任何字符都不匹配,而是与{
和}
匹配的令牌以外的任何令牌。