/*@bgen(jjtree) Generated By:JJTree: Do not edit this line. QueryParser.jj */
/*@egen*//**
 * A simple boolean query language that supports a number of features for free text querying.  These
 * features include: "and"s, "or"s, sub-expressions using parens "( )", negation, and prefix and postfix wildcard queries.
 *
 * Most of the classes in this package are auto-generated from QueryParser.jjt using javacc and jjtree.  ASTExpression and
 * ASTTerm slightly modified versions of the auto-generated files.
 * 
 * I highly recommend the "JavaCC Eclipse Plug-in".
 */options{
                 JDK_VERSION = "1.5";  IGNORE_CASE = true;                         
  static = false;
//  DEBUG_PARSER = true;
//  DEBUG_LOOKAHEAD = true;}PARSER_BEGIN(QueryParser)package org.apache.rya.indexing.accumulo.freetext.query;
import java.io.StringReader;
public class QueryParser/*@bgen(jjtree)*/implements QueryParserTreeConstants/*@egen*/{/*@bgen(jjtree)*/
  protected JJTQueryParserState jjtree = new JJTQueryParserState();

/*@egen*/
  // Helper method to parse Strings (instead of streams)
  public static SimpleNode parse(String query) throws ParseException, TokenMgrError  {    QueryParser parser = new QueryParser(new StringReader(query));    return parser.Start();  }}PARSER_END(QueryParser)SKIP : /* Ignore Whitespace */{  " " | "\t" | "\n" | "\r"
}
TOKEN : {
  <AND:       ("AND" | "&&" | "&") >
| <OR:        ("OR" | "||" | "|") >
| <NOT:       ("NOT" | "!") >
| <LPAREN:    "(" >
| <RPAREN:    ")" >
| <QUOTED:     "\"" (<_QUOTED_CHAR>)* "\"">
| <#_QUOTED_CHAR:  ~[ "\""] >
| <TERM:      <_TERM_CHAR> (<_TERM_CHAR>)*  >
| <PREFIXTERM:  "*" <TERM> >
| <WILDTERM:   <TERM> "*" >
| <#_TERM_CHAR: ~[ " ", "\t", "\n", "\r", "*", "(", ")", "!"] >
}  
SimpleNode Start()            :{/*@bgen(jjtree) SimpleNode */
  ASTSimpleNode jjtn000 = new ASTSimpleNode(JJTSIMPLENODE);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
/*@egen*/}{/*@bgen(jjtree) SimpleNode */
   try {
/*@egen*/
  // "or"s have the lowest order of operations, so they will be highest on the tree.  Start with them.   OrExpression() < EOF >/*@bgen(jjtree)*/
  {
    jjtree.closeNodeScope(jjtn000, true);
    jjtc000 = false;
  }
/*@egen*/  {    return jjtn000;  }/*@bgen(jjtree)*/
   } catch (Throwable jjte000) {
     if (jjtc000) {
       jjtree.clearNodeScope(jjtn000);
       jjtc000 = false;
     } else {
       jjtree.popNode();
     }
     if (jjte000 instanceof RuntimeException) {
       throw (RuntimeException)jjte000;
     }
     if (jjte000 instanceof ParseException) {
       throw (ParseException)jjte000;
     }
     throw (Error)jjte000;
   } finally {
     if (jjtc000) {
       jjtree.closeNodeScope(jjtn000, true);
     }
   }
/*@egen*/}

void OrExpression()                :
{/*@bgen(jjtree) #Expression(> 1) */
  ASTExpression jjtn000 = new ASTExpression(JJTEXPRESSION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
/*@egen*/ jjtn000.setType(ASTExpression.OR); }	
{/*@bgen(jjtree) #Expression(> 1) */
  try {
/*@egen*/
  AndExpression() (< OR > AndExpression())*/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);
    }
  }
/*@egen*/}

void AndExpression()                :{/*@bgen(jjtree) #Expression(> 1) */
  ASTExpression jjtn000 = new ASTExpression(JJTEXPRESSION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
/*@egen*/ jjtn000.setType(ASTExpression.AND); }
{/*@bgen(jjtree) #Expression(> 1) */
  try {
/*@egen*/  Term() ([< AND >] Term())*/*@bgen(jjtree)*/
  } catch (Throwable jjte000) {
    if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      throw (RuntimeException)jjte000;
    }
    if (jjte000 instanceof ParseException) {
      throw (ParseException)jjte000;
    }
    throw (Error)jjte000;
  } finally {
    if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, jjtree.nodeArity() > 1);
    }
  }
/*@egen*/
}
void Term() :{ Token t; boolean notFlag = false; String type = ""; }{
  // Update the notFlag if a "not" is present
  [ < NOT > { notFlag = true; } ]

  (    // Create a term, if a term is present
    (	  t = < TERM > { type = ASTTerm.TERM; }	  | t = < WILDTERM > { type = ASTTerm.WILDTERM; }
	  | t = < PREFIXTERM > { type = ASTTerm.PREFIXTERM; }
	  | t = < QUOTED > { type = ASTTerm.QUOTED; }
	)/*@bgen(jjtree) #Term(true) */
        {
          ASTTerm jjtn001 = new ASTTerm(JJTTERM);
          boolean jjtc001 = true;
          jjtree.openNodeScope(jjtn001);
        }
        try {
/*@egen*//*@bgen(jjtree)*/
        {
          jjtree.closeNodeScope(jjtn001, true);
          jjtc001 = false;
        }
/*@egen*/	{ jjtn001.setTerm(t.image); jjtn001.setNotFlag(notFlag); jjtn001.setType(type); }/*@bgen(jjtree)*/
        } finally {
          if (jjtc001) {
            jjtree.closeNodeScope(jjtn001, true);
          }
        }
/*@egen*/        
	
    // Otherwise, we a dealing with a Sub-Expression, so start back from the top.
	| ( < LPAREN > ( OrExpression() ) <  RPAREN > )
    {
      // pass on the notFlag state to the sub-expression
      // note: the sub-expression might be a term (eg, "a" is a term in "!(!a)")
      {
	   if (notFlag) {
	     Node n = jjtree.peekNode();
	     if (n instanceof ASTExpression) {
	       boolean v = ((ASTExpression)n).isNotFlag();
		   ((ASTExpression)n).setNotFlag(v ^ notFlag);
	     }
	     if (n instanceof ASTTerm) {	       boolean v = ((ASTTerm)n).isNotFlag();		   ((ASTTerm)n).setNotFlag(v ^ notFlag);	      }
	    }
      }
    }
  )
  
}