/* GuiTestScriptParser.java */
/* Generated By:JJTree&JavaCC: Do not edit this line. GuiTestScriptParser.java */
 package ur_rna.GUITester.ScriptParser;

/** Script Parser for GUI Test Framework */
public class GuiTestScriptParser/*@bgen(jjtree)*/implements GuiTestScriptParserTreeConstants, GuiTestScriptParserConstants {/*@bgen(jjtree)*/
  protected JJTGuiTestScriptParserState jjtree = new JJTGuiTestScriptParserState();/** Main entry point, if used as a stand-alone program (e.g. for testing). */
  public static void main(String args[]) throws ParseException {
    // Create the parser and parse the script
        GuiTestScriptParser parser = new GuiTestScriptParser(System.in);
    SimpleNode parseTree = parser.parse();
        // Print a textual representation of the the tree hierarchy.
        System.out.println("Parse Tree: ");
        System.out.println("--------------------------");
        parseTree.dump(">");
        System.out.println("--------------------------");
  }

  public SimpleNode parse() throws ParseException {
        return ParseScriptProgram();
  }

  public ScriptNode peekNode() {
        return (ScriptNode) jjtree.peekNode();
  }
  public ScriptNode popNode() {
        return (ScriptNode) jjtree.popNode();
  }
  public ScriptNode popTypedNode(int nodeType) {
        if (testTopNodeType(nodeType)) return popNode();
        throw new RuntimeException("Expected node type: " + jjtNodeName[nodeType] + ". Found: " + jjtNodeName[peekNodeId()]);
  }
  public ScriptNode tryPopTypedNode(int nodeType) {
        if (testTopNodeType(nodeType)) return popNode();
        return null;
  }
  public int peekNodeId() {
        return jjtree.peekNode().getId();
  }
  public boolean testTopNodeType(int nodeType) {
        return jjtree.peekNode().getId()==nodeType;
  }

  /**
   * Return the text (image) of the last consumed token.
   */
  public String lastText() {    return lastText(0);  }
  /**
   * Return the kind of the last consumed token.
   */
  public int lastKind() {       return lastKind(0);  }
  /**
   * Return the last consumed token.
   */
  public Token lastToken() {    return lastToken(0);  }
  /**
   * Return the text (image) of the token consumed pos steps before last.
   */
  public String lastText(int pos) {     return getToken(-pos).image;  }
  /**
   * Return the kind of the token consumed pos steps before last.
   */
  public int lastKind(int pos) {        return getToken(-pos).kind;  }
  /**
   * Return the token consumed pos steps before last.
   */
  public Token lastToken(int pos) {     return getToken(-pos);  }

  public Object EvalLiteralToken(Token t, String sign) throws ParseFormatException {
        try {
                if (sign == null) sign = "";
                return EvalLiteral(sign + t.image, t.kind);
        } catch (NumberFormatException ex) {
                throw new ParseFormatException("Invalid literal number format: " + ex.getMessage(), t, ex);
        } catch (IllegalArgumentException ex) {
                throw new ParseFormatException(ex.getMessage(), t, ex);
        }
  }

  //public Object EvalLiteral(String data, int kind) { return EvalLiteral(data, kind, null); }
  public Object EvalLiteral(String data, int kind) throws IllegalArgumentException  {
        switch(kind) {
            case STRING_LITERAL: return data.substring(1, data.length() - 1);
                case INTEGER_LITERAL:
                        switch(Character.toUpperCase(data.charAt(data.length()-1))) {
                                case 'L': return Long.parseLong(trimRight(data,1));
                                case 'B': return Byte.parseByte(trimRight(data,1));
                                case 'S': return Short.parseShort(trimRight(data,1));
                                default:  return Integer.decode(data);
                        }
                case FLOAT_LITERAL:
                        switch(Character.toUpperCase(data.charAt(data.length()-1))) {
                                case 'D': return Double.parseDouble(trimRight(data,1));
                                case 'F': return Float.parseFloat(trimRight(data,1));
                                default:  return Double.parseDouble(data);
                        }
                case TRUE: return Boolean.TRUE;
                case FALSE: return Boolean.FALSE;
                case NULL: return null;
                default:
                        throw new IllegalArgumentException("Invalid literal kind indicator: " + kind);
        }
  }
  private String trimRight(String s, int numChars) { return s.substring(0, s.length() - numChars); }

/*******************************************
 * THE SCRIPT LANGUAGE GRAMMAR STARTS HERE *
 *******************************************/

/* The grammatical root node */
  final public SimpleNode ParseScriptProgram() throws ParseException {
    trace_call("ParseScriptProgram");
    try {/*@bgen(jjtree) Root */
  ASTRoot jjtn000 = new ASTRoot(JJTROOT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
      try {
        label_1:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case NEWLINE:
          case SEMICOLON:{
              break;
            }
          default:
            jj_la1[0] = jj_gen;
            break label_1;
          }
          EOS();
        }
        label_2:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case METHOD_PREFIX:
          case IDENTIFIER:
          case HOOK:{
              break;
            }
          default:
            jj_la1[1] = jj_gen;
            break label_2;
          }
          Instruction();
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case NEWLINE:
          case SEMICOLON:{
            label_3:
            while (true) {
              EOS();
              switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
              case NEWLINE:
              case SEMICOLON:{
                  break;
                }
              default:
                jj_la1[2] = jj_gen;
                break label_3;
              }
            }
            break;
            }
          case 0:{
            jj_consume_token(0);
            break;
            }
          default:
            jj_la1[3] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
        }
        jj_consume_token(0);
jjtree.closeNodeScope(jjtn000, true);
    jjtc000 = false;
//Return the root tree-node constructed by parsing the script.
        {if ("" != null) return jjtn000;}
      } catch (Throwable jjte000) {
if (jjtc000) {
      jjtree.clearNodeScope(jjtn000);
      jjtc000 = false;
    } else {
      jjtree.popNode();
    }
    if (jjte000 instanceof RuntimeException) {
      {if (true) throw (RuntimeException)jjte000;}
    }
    if (jjte000 instanceof ParseException) {
      {if (true) throw (ParseException)jjte000;}
    }
    {if (true) throw (Error)jjte000;}
      } finally {
if (jjtc000) {
      jjtree.closeNodeScope(jjtn000, true);
    }
      }
    throw new Error("Missing return statement in function");
    } finally {
      trace_return("ParseScriptProgram");
    }
  }

/* END-OF-STATEMENT: Statements must end with either a semi-colon or a newline.  */
  final public void EOS() throws ParseException {
    trace_call("EOF");
    try {
      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
      case NEWLINE:{
        jj_consume_token(NEWLINE);
        break;
        }
      case SEMICOLON:{
        jj_consume_token(SEMICOLON);
        break;
        }
      default:
        jj_la1[4] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    } finally {
      trace_return("EOF");
    }
  }

  final public void Instruction() throws ParseException {
    trace_call("Instruction");
    try {
      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
      case HOOK:{
        Assignment();
        break;
        }
      case METHOD_PREFIX:
      case IDENTIFIER:{
        Action();
        break;
        }
      default:
        jj_la1[5] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    } finally {
      trace_return("Instruction");
    }
  }

/* Variable Assignments */
  final public void Assignment() throws ParseException {
    trace_call("Assignment");
    try {/*@bgen(jjtree) #Assignment( 0) */
  ASTAssignment jjtn000 = new ASTAssignment(JJTASSIGNMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
      try {
        VarRef();
jjtn000.subject=popNode();
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case ASSIGN:
        case ASSIGN_REF:{
          AssignmentOperator();
jjtn000.operatorKind=lastKind();
          Expression();
jjtn000.newValue=popNode();
          break;
          }
        default:
          jj_la1[6] = jj_gen;
        }
      } catch (Throwable jjte000) {
if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            {if (true) throw (RuntimeException)jjte000;}
          }
          if (jjte000 instanceof ParseException) {
            {if (true) throw (ParseException)jjte000;}
          }
          {if (true) throw (Error)jjte000;}
      } finally {
if (jjtc000) {
            jjtree.closeNodeScope(jjtn000,  0);
          }
      }
    } finally {
      trace_return("Assignment");
    }
  }

  final public void AssignmentOperator() throws ParseException {
    trace_call("AssignmentOperator");
    try {
      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
      case ASSIGN:{
        jj_consume_token(ASSIGN);
        break;
        }
      case ASSIGN_REF:{
        jj_consume_token(ASSIGN_REF);
        break;
        }
      default:
        jj_la1[7] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    } finally {
      trace_return("AssignmentOperator");
    }
  }

/* Actions */
  final public void Action() throws ParseException {
    trace_call("Action");
    try {/*@bgen(jjtree) Action */
  ASTAction jjtn000 = new ASTAction(JJTACTION);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);String prefix = "";
      try {
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case METHOD_PREFIX:{
          prefix = jj_consume_token(METHOD_PREFIX).image;
          break;
          }
        default:
          jj_la1[8] = jj_gen;
        }
        jj_consume_token(IDENTIFIER);
jjtn000.verb=prefix+lastText();
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case TRUE:
        case FALSE:
        case NULL:
        case INTEGER_LITERAL:
        case FLOAT_LITERAL:
        case STRING_LITERAL:
        case LBRACE:
        case HOOK:
        case PLUS:
        case MINUS:{
          ArgumentList();
          break;
          }
        default:
          jj_la1[9] = jj_gen;
        }
      } catch (Throwable jjte000) {
if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            {if (true) throw (RuntimeException)jjte000;}
          }
          if (jjte000 instanceof ParseException) {
            {if (true) throw (ParseException)jjte000;}
          }
          {if (true) throw (Error)jjte000;}
      } finally {
if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
          }
      }
    } finally {
      trace_return("Action");
    }
  }

  final public void GuiReference() throws ParseException {
    trace_call("GuiReference");
    try {/*@bgen(jjtree) GuiReference */
  ASTGuiReference jjtn000 = new ASTGuiReference(JJTGUIREFERENCE);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
      try {
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case HOOK:{
          VarRef();
          break;
          }
        case LBRACE:{
          SingleGuiItem();
          break;
          }
        default:
          jj_la1[10] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
jjtn000.guiItem=popNode();
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case PARENT:
        case ANCESTOR:
        case CHILD:
        case SIBLING:
        case DESCENDANT:{
          GuiRelation();
jjtn000.relationshipKind=lastKind();
          GuiReference();
jjtn000.relative=(ASTGuiReference)popNode();
          break;
          }
        default:
          jj_la1[11] = jj_gen;
        }
      } catch (Throwable jjte000) {
if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            {if (true) throw (RuntimeException)jjte000;}
          }
          if (jjte000 instanceof ParseException) {
            {if (true) throw (ParseException)jjte000;}
          }
          {if (true) throw (Error)jjte000;}
      } finally {
if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
          }
      }
    } finally {
      trace_return("GuiReference");
    }
  }

  final public void GuiRelation() throws ParseException {
    trace_call("GuiRelation");
    try {
      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
      case CHILD:{
        jj_consume_token(CHILD);
        break;
        }
      case PARENT:{
        jj_consume_token(PARENT);
        break;
        }
      case DESCENDANT:{
        jj_consume_token(DESCENDANT);
        break;
        }
      case ANCESTOR:{
        jj_consume_token(ANCESTOR);
        break;
        }
      case SIBLING:{
        jj_consume_token(SIBLING);
        break;
        }
      default:
        jj_la1[12] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    } finally {
      trace_return("GuiRelation");
    }
  }

  final public void SingleGuiItem() throws ParseException {
    trace_call("SingleGuiItem");
    try {/*@bgen(jjtree) GuiSearchCriteria */
  ASTGuiSearchCriteria jjtn000 = new ASTGuiSearchCriteria(JJTGUISEARCHCRITERIA);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
      try {
        jj_consume_token(LBRACE);
        if (jj_2_1(2147483647)) {
          jjtn000.itemType = jj_consume_token(IDENTIFIER).image;
        } else {
        }
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case TRUE:
        case FALSE:
        case NULL:
        case INTEGER_LITERAL:
        case FLOAT_LITERAL:
        case STRING_LITERAL:
        case IDENTIFIER:
        case LBRACE:
        case HOOK:
        case PLUS:
        case MINUS:{
          NamedArgumentList();
          break;
          }
        default:
          jj_la1[13] = jj_gen;
        }
        jj_consume_token(RBRACE);
jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
if (jjtn000.itemType == null && jjtn000.jjtGetNumChildren() == 0)
                        {if (true) throw new ParseFormatException("Empty GUI reference.", lastToken(), null);}
      } catch (Throwable jjte000) {
if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            {if (true) throw (RuntimeException)jjte000;}
          }
          if (jjte000 instanceof ParseException) {
            {if (true) throw (ParseException)jjte000;}
          }
          {if (true) throw (Error)jjte000;}
      } finally {
if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
          }
      }
    } finally {
      trace_return("SingleGuiItem");
    }
  }

  final public void VarRef() throws ParseException {
    trace_call("VarRef");
    try {/*@bgen(jjtree) VarRef */
  ASTVarRef jjtn000 = new ASTVarRef(JJTVARREF);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);Token t;
      try {
        jj_consume_token(HOOK);
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case IDENTIFIER:{
          t = jj_consume_token(IDENTIFIER);
          break;
          }
        case LBRACE:{
          jj_consume_token(LBRACE);
          t = jj_consume_token(IDENTIFIER);
          jj_consume_token(RBRACE);
          break;
          }
        default:
          jj_la1[14] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;
jjtn000.varName=t.image;
      } finally {
if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
          }
      }
    } finally {
      trace_return("VarRef");
    }
  }

  final public void Expression() throws ParseException {
    trace_call("Expression");
    try {
      switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
      case PLUS:
      case MINUS:{
        SignedNumber();
        break;
        }
      case TRUE:
      case FALSE:
      case NULL:
      case INTEGER_LITERAL:
      case FLOAT_LITERAL:
      case STRING_LITERAL:{
        Literal();
        break;
        }
      default:
        jj_la1[15] = jj_gen;
        if (jj_2_2(2147483647)) {
          GuiReference();
        } else if (jj_2_3(2147483647)) {
          GuiReference();
        } else {
          switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
          case HOOK:{
            VarRef();
            break;
            }
          default:
            jj_la1[16] = jj_gen;
            jj_consume_token(-1);
            throw new ParseException();
          }
        }
      }
    } finally {
      trace_return("Expression");
    }
  }

/** Usually numbers of the format (+|-)NUMBER (e.g. +3 or -2.5 etc)
    are interpreted as Unary expressions instead of as literals. 
	This is usually fine because it will be evaluated properly during runtime.
	However in cases where the true value needs to be known ahead of runtime 
	(e.g. for directives) we need to be able to identify and evaluate these 
	expressions without resorting to runtime expression processing. 
	TODO: Remove the need for this by having the parser 
	evaluate all expressions at compile-time and only leave 
	variables (and other runtime nodes) unevaluated.	*/
  final public void SignedNumber() throws ParseException {
    trace_call("SignedNumber");
    try {/*@bgen(jjtree) #Literal( 0) */
  ASTLiteral jjtn000 = new ASTLiteral(JJTLITERAL);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);String sign = null;
      try {
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case PLUS:{
          jj_consume_token(PLUS);
          break;
          }
        case MINUS:{
          sign = jj_consume_token(MINUS).image;
          break;
          }
        default:
          jj_la1[17] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case INTEGER_LITERAL:{
          jj_consume_token(INTEGER_LITERAL);
          break;
          }
        case FLOAT_LITERAL:{
          jj_consume_token(FLOAT_LITERAL);
          break;
          }
        default:
          jj_la1[18] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
jjtree.closeNodeScope(jjtn000,  0);
          jjtc000 = false;
jjtn000.setValue(EvalLiteralToken(lastToken(), sign));
      } finally {
if (jjtc000) {
            jjtree.closeNodeScope(jjtn000,  0);
          }
      }
    } finally {
      trace_return("SignedNumber");
    }
  }

  final public void Literal() throws ParseException {
    trace_call("Literal");
    try {/*@bgen(jjtree) #Literal( 0) */
  ASTLiteral jjtn000 = new ASTLiteral(JJTLITERAL);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
      try {
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case INTEGER_LITERAL:{
          jj_consume_token(INTEGER_LITERAL);
          break;
          }
        case FLOAT_LITERAL:{
          jj_consume_token(FLOAT_LITERAL);
          break;
          }
        case STRING_LITERAL:{
          jj_consume_token(STRING_LITERAL);
          break;
          }
        case TRUE:{
          jj_consume_token(TRUE);
          break;
          }
        case FALSE:{
          jj_consume_token(FALSE);
          break;
          }
        case NULL:{
          jj_consume_token(NULL);
          break;
          }
        default:
          jj_la1[19] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
jjtree.closeNodeScope(jjtn000,  0);
          jjtc000 = false;
jjtn000.setValue(EvalLiteralToken(lastToken(), null));
      } finally {
if (jjtc000) {
            jjtree.closeNodeScope(jjtn000,  0);
          }
      }
    } finally {
      trace_return("Literal");
    }
  }

  final public void ArgumentList() throws ParseException {
    trace_call("ArgumentList");
    try {
      Expression();
      label_4:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case COMMA:{
            break;
          }
        default:
          jj_la1[20] = jj_gen;
          break label_4;
        }
        jj_consume_token(COMMA);
        Expression();
      }
    } finally {
      trace_return("ArgumentList");
    }
  }

  final public void NamedArgumentList() throws ParseException {
    trace_call("NamedArgumentList");
    try {
      NamedArgument();
      label_5:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk_f():jj_ntk) {
        case COMMA:{
            break;
          }
        default:
          jj_la1[21] = jj_gen;
          break label_5;
        }
        jj_consume_token(COMMA);
        NamedArgument();
      }
    } finally {
      trace_return("NamedArgumentList");
    }
  }

  final public void NamedArgument() throws ParseException {
    trace_call("NamedArgument");
    try {/*@bgen(jjtree) NamedArgument */
  ASTNamedArgument jjtn000 = new ASTNamedArgument(JJTNAMEDARGUMENT);
  boolean jjtc000 = true;
  jjtree.openNodeScope(jjtn000);
      try {
        if (jj_2_4(2)) {
          jjtn000.name = jj_consume_token(IDENTIFIER).image;
          jj_consume_token(ASSIGN);
        } else {
        }
        Expression();
jjtn000.val=popNode();
jjtree.closeNodeScope(jjtn000, true);
          jjtc000 = false;

      } catch (Throwable jjte000) {
if (jjtc000) {
            jjtree.clearNodeScope(jjtn000);
            jjtc000 = false;
          } else {
            jjtree.popNode();
          }
          if (jjte000 instanceof RuntimeException) {
            {if (true) throw (RuntimeException)jjte000;}
          }
          if (jjte000 instanceof ParseException) {
            {if (true) throw (ParseException)jjte000;}
          }
          {if (true) throw (Error)jjte000;}
      } finally {
if (jjtc000) {
            jjtree.closeNodeScope(jjtn000, true);
          }
      }
    } finally {
      trace_return("NamedArgument");
    }
  }

  private boolean jj_2_1(int xla)
 {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_1(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(0, xla); }
  }

  private boolean jj_2_2(int xla)
 {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_2(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(1, xla); }
  }

  private boolean jj_2_3(int xla)
 {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_3(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(2, xla); }
  }

  private boolean jj_2_4(int xla)
 {
    jj_la = xla; jj_lastpos = jj_scanpos = token;
    try { return !jj_3_4(); }
    catch(LookaheadSuccess ls) { return true; }
    finally { jj_save(3, xla); }
  }

  private boolean jj_3R_6()
 {
     return jj_3R_9();
 }

  private boolean jj_3_4()
 {
    if (jj_scan_token(IDENTIFIER)) return true;
     return jj_scan_token(ASSIGN);
 }

  private boolean jj_3_3()
 {
    if (jj_3R_7()) return true;
     return jj_3R_8();
 }

  private boolean jj_3R_9()
 {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(10)) {
    jj_scanpos = xsp;
    if (jj_scan_token(17)) {
    jj_scanpos = xsp;
    if (jj_scan_token(20)) {
    jj_scanpos = xsp;
    if (jj_scan_token(7)) {
    jj_scanpos = xsp;
    if (jj_scan_token(8)) {
    jj_scanpos = xsp;
    if (jj_scan_token(9)) return true;
    }
    }
    }
    }
    }
    return false;
  }

  private boolean jj_3_1()
 {
    if (jj_scan_token(IDENTIFIER)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(28)) {
    jj_scanpos = xsp;
    if (jj_3R_6()) {
    jj_scanpos = xsp;
    if (jj_scan_token(35)) return true;
    }
    }
    return false;
  }

  private boolean jj_3R_10()
 {
    if (jj_scan_token(LBRACE)) return true;
    if (jj_scan_token(IDENTIFIER)) return true;
     return jj_scan_token(RBRACE);
 }

  private boolean jj_3R_7()
 {
    if (jj_scan_token(HOOK)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(28)) {
    jj_scanpos = xsp;
    if (jj_3R_10()) return true;
    }
    return false;
  }

  private boolean jj_3_2()
 {
     return jj_scan_token(LBRACE);
 }

  private boolean jj_3R_8()
 {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(69)) {
    jj_scanpos = xsp;
    if (jj_scan_token(67)) {
    jj_scanpos = xsp;
    if (jj_scan_token(72)) {
    jj_scanpos = xsp;
    if (jj_scan_token(68)) {
    jj_scanpos = xsp;
    if (jj_scan_token(70)) return true;
    }
    }
    }
    }
    return false;
  }

  /** Generated Token Manager. */
  public GuiTestScriptParserTokenManager token_source;
  JavaCharStream jj_input_stream;
  /** Current token. */
  public Token token;
  /** Next token. */
  public Token jj_nt;
  private int jj_ntk;
  private Token jj_scanpos, jj_lastpos;
  private int jj_la;
  private int jj_gen;
  final private int[] jj_la1 = new int[22];
  static private int[] jj_la1_0;
  static private int[] jj_la1_1;
  static private int[] jj_la1_2;
  static {
      jj_la1_init_0();
      jj_la1_init_1();
      jj_la1_init_2();
   }
   private static void jj_la1_init_0() {
      jj_la1_0 = new int[] {0x8,0x18000000,0x8,0x9,0x8,0x18000000,0x0,0x0,0x8000000,0x120780,0x0,0x0,0x0,0x10120780,0x10000000,0x120780,0x0,0x0,0x20400,0x120780,0x0,0x0,};
   }
   private static void jj_la1_init_1() {
      jj_la1_1 = new int[] {0x40,0x10000,0x40,0x40,0x40,0x10000,0xc00,0xc00,0x0,0xc010004,0x10004,0x0,0x0,0xc010004,0x4,0xc000000,0x10000,0xc000000,0x0,0x0,0x80,0x80,};
   }
   private static void jj_la1_init_2() {
      jj_la1_2 = new int[] {0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x178,0x178,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,};
   }
  final private JJCalls[] jj_2_rtns = new JJCalls[4];
  private boolean jj_rescan = false;
  private int jj_gc = 0;

  /** Constructor with InputStream. */
  public GuiTestScriptParser(java.io.InputStream stream) {
     this(stream, null);
  }
  /** Constructor with InputStream and supplied encoding */
  public GuiTestScriptParser(java.io.InputStream stream, String encoding) {
    try { jj_input_stream = new JavaCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
    token_source = new GuiTestScriptParserTokenManager(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 22; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  /** Reinitialise. */
  public void ReInit(java.io.InputStream stream) {
     ReInit(stream, null);
  }
  /** Reinitialise. */
  public void ReInit(java.io.InputStream stream, String encoding) {
    try { jj_input_stream.ReInit(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
    token_source.ReInit(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jjtree.reset();
    jj_gen = 0;
    for (int i = 0; i < 22; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  /** Constructor. */
  public GuiTestScriptParser(java.io.Reader stream) {
    jj_input_stream = new JavaCharStream(stream, 1, 1);
    token_source = new GuiTestScriptParserTokenManager(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 22; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  /** Reinitialise. */
  public void ReInit(java.io.Reader stream) {
    jj_input_stream.ReInit(stream, 1, 1);
    token_source.ReInit(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jjtree.reset();
    jj_gen = 0;
    for (int i = 0; i < 22; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  /** Constructor with generated Token Manager. */
  public GuiTestScriptParser(GuiTestScriptParserTokenManager tm) {
    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 22; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  /** Reinitialise. */
  public void ReInit(GuiTestScriptParserTokenManager tm) {
    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jjtree.reset();
    jj_gen = 0;
    for (int i = 0; i < 22; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  private Token jj_consume_token(int kind) throws ParseException {
    Token oldToken;
    if ((oldToken = token).next != null) token = token.next;
    else token = token.next = token_source.getNextToken();
    jj_ntk = -1;
    if (token.kind == kind) {
      jj_gen++;
      if (++jj_gc > 100) {
        jj_gc = 0;
        for (int i = 0; i < jj_2_rtns.length; i++) {
          JJCalls c = jj_2_rtns[i];
          while (c != null) {
            if (c.gen < jj_gen) c.first = null;
            c = c.next;
          }
        }
      }
      trace_token(token, "");
      return token;
    }
    token = oldToken;
    jj_kind = kind;
    throw generateParseException();
  }

  @SuppressWarnings("serial")
  static private final class LookaheadSuccess extends java.lang.Error { }
  final private LookaheadSuccess jj_ls = new LookaheadSuccess();
  private boolean jj_scan_token(int kind) {
    if (jj_scanpos == jj_lastpos) {
      jj_la--;
      if (jj_scanpos.next == null) {
        jj_lastpos = jj_scanpos = jj_scanpos.next = token_source.getNextToken();
      } else {
        jj_lastpos = jj_scanpos = jj_scanpos.next;
      }
    } else {
      jj_scanpos = jj_scanpos.next;
    }
    if (jj_rescan) {
      int i = 0; Token tok = token;
      while (tok != null && tok != jj_scanpos) { i++; tok = tok.next; }
      if (tok != null) jj_add_error_token(kind, i);
    }
    if (jj_scanpos.kind != kind) return true;
    if (jj_la == 0 && jj_scanpos == jj_lastpos) throw jj_ls;
    return false;
  }


/** Get the next Token. */
  final public Token getNextToken() {
    if (token.next != null) token = token.next;
    else token = token.next = token_source.getNextToken();
    jj_ntk = -1;
    jj_gen++;
      trace_token(token, " (in getNextToken)");
    return token;
  }

/** Get the specific Token. */
  final public Token getToken(int index) {
    Token t = token;
    for (int i = 0; i < index; i++) {
      if (t.next != null) t = t.next;
      else t = t.next = token_source.getNextToken();
    }
    return t;
  }

  private int jj_ntk_f() {
    if ((jj_nt=token.next) == null)
      return (jj_ntk = (token.next=token_source.getNextToken()).kind);
    else
      return (jj_ntk = jj_nt.kind);
  }

  private java.util.List<int[]> jj_expentries = new java.util.ArrayList<int[]>();
  private int[] jj_expentry;
  private int jj_kind = -1;
  private int[] jj_lasttokens = new int[100];
  private int jj_endpos;

  private void jj_add_error_token(int kind, int pos) {
    if (pos >= 100) return;
    if (pos == jj_endpos + 1) {
      jj_lasttokens[jj_endpos++] = kind;
    } else if (jj_endpos != 0) {
      jj_expentry = new int[jj_endpos];
      for (int i = 0; i < jj_endpos; i++) {
        jj_expentry[i] = jj_lasttokens[i];
      }
      jj_entries_loop: for (java.util.Iterator<?> it = jj_expentries.iterator(); it.hasNext();) {
        int[] oldentry = (int[])(it.next());
        if (oldentry.length == jj_expentry.length) {
          for (int i = 0; i < jj_expentry.length; i++) {
            if (oldentry[i] != jj_expentry[i]) {
              continue jj_entries_loop;
            }
          }
          jj_expentries.add(jj_expentry);
          break jj_entries_loop;
        }
      }
      if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
    }
  }

  /** Generate ParseException. */
  public ParseException generateParseException() {
    jj_expentries.clear();
    boolean[] la1tokens = new boolean[84];
    if (jj_kind >= 0) {
      la1tokens[jj_kind] = true;
      jj_kind = -1;
    }
    for (int i = 0; i < 22; i++) {
      if (jj_la1[i] == jj_gen) {
        for (int j = 0; j < 32; j++) {
          if ((jj_la1_0[i] & (1<<j)) != 0) {
            la1tokens[j] = true;
          }
          if ((jj_la1_1[i] & (1<<j)) != 0) {
            la1tokens[32+j] = true;
          }
          if ((jj_la1_2[i] & (1<<j)) != 0) {
            la1tokens[64+j] = true;
          }
        }
      }
    }
    for (int i = 0; i < 84; i++) {
      if (la1tokens[i]) {
        jj_expentry = new int[1];
        jj_expentry[0] = i;
        jj_expentries.add(jj_expentry);
      }
    }
    jj_endpos = 0;
    jj_rescan_token();
    jj_add_error_token(0, 0);
    int[][] exptokseq = new int[jj_expentries.size()][];
    for (int i = 0; i < jj_expentries.size(); i++) {
      exptokseq[i] = jj_expentries.get(i);
    }
    return new ParseException(token, exptokseq, tokenImage);
  }

  private int trace_indent = 0;
  private boolean trace_enabled = true;

/** Enable tracing. */
  final public void enable_tracing() {
    trace_enabled = true;
  }

/** Disable tracing. */
  final public void disable_tracing() {
    trace_enabled = false;
  }

  private void trace_call(String s) {
    if (trace_enabled) {
      for (int i = 0; i < trace_indent; i++) { System.out.print(" "); }
      System.out.println("Call:   " + s);
    }
    trace_indent = trace_indent + 2;
  }

  private void trace_return(String s) {
    trace_indent = trace_indent - 2;
    if (trace_enabled) {
      for (int i = 0; i < trace_indent; i++) { System.out.print(" "); }
      System.out.println("Return: " + s);
    }
  }

  private void trace_token(Token t, String where) {
    if (trace_enabled) {
      for (int i = 0; i < trace_indent; i++) { System.out.print(" "); }
      System.out.print("Consumed token: <" + tokenImage[t.kind]);
      if (t.kind != 0 && !tokenImage[t.kind].equals("\"" + t.image + "\"")) {
        System.out.print(": \"" + t.image + "\"");
      }
      System.out.println(" at line " + t.beginLine + " column " + t.beginColumn + ">" + where);
    }
  }

  private void trace_scan(Token t1, int t2) {
    if (trace_enabled) {
      for (int i = 0; i < trace_indent; i++) { System.out.print(" "); }
      System.out.print("Visited token: <" + tokenImage[t1.kind]);
      if (t1.kind != 0 && !tokenImage[t1.kind].equals("\"" + t1.image + "\"")) {
        System.out.print(": \"" + t1.image + "\"");
      }
      System.out.println(" at line " + t1.beginLine + " column " + t1.beginColumn + ">; Expected token: <" + tokenImage[t2] + ">");
    }
  }

  private void jj_rescan_token() {
    jj_rescan = true;
    for (int i = 0; i < 4; i++) {
    try {
      JJCalls p = jj_2_rtns[i];
      do {
        if (p.gen > jj_gen) {
          jj_la = p.arg; jj_lastpos = jj_scanpos = p.first;
          switch (i) {
            case 0: jj_3_1(); break;
            case 1: jj_3_2(); break;
            case 2: jj_3_3(); break;
            case 3: jj_3_4(); break;
          }
        }
        p = p.next;
      } while (p != null);
      } catch(LookaheadSuccess ls) { }
    }
    jj_rescan = false;
  }

  private void jj_save(int index, int xla) {
    JJCalls p = jj_2_rtns[index];
    while (p.gen > jj_gen) {
      if (p.next == null) { p = p.next = new JJCalls(); break; }
      p = p.next;
    }
    p.gen = jj_gen + xla - jj_la; p.first = token; p.arg = xla;
  }

  static final class JJCalls {
    int gen;
    Token first;
    int arg;
    JJCalls next;
  }

//  public T pop<T extends ScriptNode>() {
//    try {
//		T node = (T)peek(); //if this succeeds, the node is of the proper type.
//		return pop();
//	} catch (InvalidCastException ex) {
//		throw new RuntimeError("Node type found, '" + + jjtNodeName[peekId()] + "' is different than expected.", ex);
//	}
//  }
}
