def parser(self):
operatorOr = Forward()<EOL>operatorWord = Group(Combine(Word(alphanums) + Suppress('<STR_LIT:*>'))).setResultsName('<STR_LIT>') |Group(Word(alphanums)).setResultsName('<STR_LIT>')<EOL>operatorQuotesContent = Forward()<EOL>operatorQuotesContent << (<EOL>(operatorWord + operatorQuotesContent) | operatorWord<EOL>)<EOL>operatorQuotes = Group(<EOL>Suppress('<STR_LIT:">') + operatorQuotesContent + Suppress('<STR_LIT:">')<EOL>).setResultsName("<STR_LIT>") | operatorWord<EOL>operatorParenthesis = Group(<EOL>(Suppress("<STR_LIT:(>") + operatorOr + Suppress("<STR_LIT:)>"))<EOL>).setResultsName("<STR_LIT>") | operatorQuotes<EOL>operatorNot = Forward()<EOL>operatorNot << (Group(<EOL>Suppress(Keyword("<STR_LIT>", caseless=True)) + operatorNot<EOL>).setResultsName("<STR_LIT>") | operatorParenthesis)<EOL>operatorAnd = Forward()<EOL>operatorAnd << (Group(<EOL>operatorNot + Suppress(Keyword("<STR_LIT>", caseless=True)) + operatorAnd<EOL>).setResultsName("<STR_LIT>") | Group(<EOL>operatorNot + OneOrMore(~oneOf("<STR_LIT>") + operatorAnd)<EOL>).setResultsName("<STR_LIT>") | operatorNot)<EOL>operatorOr << (Group(<EOL>operatorAnd + Suppress(Keyword("<STR_LIT>", caseless=True)) + operatorOr<EOL>).setResultsName("<STR_LIT>") | operatorAnd)<EOL>return operatorOr.parseString<EOL>
This function returns a parser.
The grammar should be like most full text search engines (Google, Tsearch, Lucene).

Grammar:
- a query consists of alphanumeric words, with an optional '*' wildcard
  at the end of a word
- a sequence of words between quotes is a literal string
- words can be used together by using operators ('and' or 'or')
- words with operators can be grouped with parenthesis
- a word or group of words can be preceded by a 'not' operator
- the 'and' operator precedes an 'or' operator
- if an operator is missing, use an 'and' operator