This test illustrates the problem:
BASE_SRC_DIR=<your choice>;
NODE_DEFAULT_VOID=true;
PARSER_PACKAGE="test";
TREE_BUILDING_ENABLED=false;
TOKEN :
< INTEGER: ( "0" )* ( ( "1" ( ["0"-"9"] )+ ) | ( ["2"-"9"] ( ["0"-"9"] )* ) ) >
;
UNPARSED :
<SINGLE_REPEAT: "(" ( "0" )* "1)" >
;
Test :
APluralityOfFoos =>|| | "bar"
;
APluralityOfFoos :
( ASSERT ~(LoneFoo) "foo" =>|| [ Repeat ] )+
;
Repeat :
"(" < INTEGER > ")"
;
LoneFoo :
"foo" ASSERT ~( "foo" | Repeat ) =>||
;
SKIP : " " ;
INJECT PARSER_CLASS :
{
public static void main(String[] args) {
if (args.length == 0) {
System.err.println("No input provided.");
System.exit(1);
}
PARSER_CLASS parser;
for (String input : args) {
try {
parser = new PARSER_CLASS(input);
parser.Test();
System.out.println("'" + input + "' accepted");
} catch (ParseException | NullPointerException e) {
System.err.println("'" + input + "' failed to parse: " + e.getLocalizedMessage());
}
}
}
}
Given the input "foo" or "foo(1)" it should fail, but given "foo foo" or "foo(2)" it should succeed, but does not. I've done a pull request for what I think fixes the problem. Basically the nested ASSERT inside lookahead needs to not leave a hitFailure active when it bubbles up. I assumed for the fix that it needs to restore the hitFailure to the previous value after any lookahead ASSERT, but that could be overkill.