Your rule matches that '\u0020'..'\u007e' from the rule '{' ('\u0020'..'\u007e' | ~( '{' | '}' ) )* '}' matches both { and } .
Your rule should work if you define it like this:
SCRIPT : '{' ( SCRIPT | ~( '{' | '}' ) )* '}' ;
However, this will fail if the script block contains, says, lines or comments containing { or } . The following is a way to map the SCRIPT token, including comments and string literals that may contain { and '}':
SCRIPT : '{' SCRIPT_ATOM* '}' ; fragment SCRIPT_ATOM : ~[{}] | '"' ~["]* '"' | '
A complete grammar that parses your input correctly will look like this:
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 : ~[{}] | '"' ~["]* '"' | '
which also parses the following input correctly:
define function concat[JavaScript] return string { for (;;) { while (true) { } } var s = "}"
source share