Paul McGuire - 2018-09-19

( ( ) ) may be valid Lucene, but it isn't valid as far as infixNotation is concerned. There have to be some operands in the string to be parsed, not just empty grouping ()'s. That is what that ParseException is trying to say.

Your definition of term is just the parens around expression, which is unnecessary since infixNotation does this recursive part for you. Plus, you haven't defined just what a valid operand looks like. Reading your comments, a valid query string would look like ( (role:foo) || (role:bar) ), so I defined your grammar as:

term = ~(and_ | or_) + Word(alphas, alphas+':')
expression = infixNotation(term,
    [
        ((and_ | '&&').setParseAction(lambda: "AND"), 2, opAssoc.LEFT),
        (Optional(or_ | '||').setParseAction(lambda: "OR"), 2, opAssoc.LEFT),
    ])

(Note: no Forwards - infixNotation takes care of that). There is a lot of recursion going on here, I believe stemming from the use of the Optional || operator. But with these changes to term and expression, I was able to run this code against the original query, with and without packratting (much faster with), and with and without the call to threading.stack_size.