/* Generated By:JavaCC: Do not edit this line. JostarParser.java */
package jostarfront;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Iterator;
import java.io.FileReader;
import java.io.PrintWriter;
import java.io.File;

import coins.FatalError;
import coins.FlowRoot;
import coins.HirRoot;
import coins.IoRoot;
import coins.IrRoot;
import coins.SymRoot;
import coins.hir2lir.ConvToNewLIR;
import coins.casttohir.ToHirC;
import coins.casttohir.ToHirBase;
import coins.ir.IrList;
import coins.ir.hir.AssignStmt;
import coins.ir.hir.BlockStmt;
import coins.ir.hir.Exp;
import coins.ir.hir.ConstNode;
import coins.ir.hir.ElemNode;
import coins.ir.hir.ExpStmt;
import coins.ir.hir.ForStmt;
import coins.ir.hir.HIR;
import coins.ir.hir.IfStmt;
import coins.ir.hir.IndexedLoopStmt;
import coins.ir.hir.JumpStmt;
import coins.ir.hir.Program;
import coins.ir.hir.SetDataStmt;
import coins.ir.hir.Stmt;
import coins.ir.hir.SubpDefinition;
import coins.ir.hir.SubpDefinitionImpl;
import coins.ir.hir.SubpNode;
import coins.ir.hir.VarNode;
import coins.sym.Const;
import coins.sym.Elem;
import coins.sym.Label;
import coins.sym.NamedConst;
import coins.sym.IntConst;
import coins.sym.FloatConst;
import coins.sym.Param;
import coins.sym.PointerType;
import coins.sym.RegionType;
import coins.sym.StructType;
import coins.sym.Subp;
import coins.sym.SymTable;
import coins.sym.Sym;
import coins.sym.Type;
import coins.sym.Var;
import coins.sym.VectorType;
import coins.aflow.FlowResults;
import coins.aflow.RegisterFlowAnalClasses;
import coins.aflow.ShowFlow;
import coins.aflow.SubpFlow;
import coins.backend.BackEnd;
import coins.backend.SyntaxError;
import coins.backend.SyntaxErrorException;
import coins.backend.util.ImList;

public class JostarParser implements JostarParserConstants {
        private SymRoot  symRoot; //  root of symbol information
        private Sym sym;              // Sym object creator
        private HirRoot hirRoot;   // root of HIR information
        private HIR hir;                 // HIR object creator
        private IoRoot ioRoot;     // root of I/O information
    private int currentLine=0; // Line number of token that appeared as the first
        // ID of a statement. When currentLine is recorded as the line number
        // of a statement, then it is set to 0 so that it will be set by next ID.

        public JostarParser(SymRoot sRoot, HirRoot hRoot, IoRoot iRoot, FileReader reader) {
                this(reader);
                symRoot = sRoot;
                sym = (Sym)symRoot.sym;
                hirRoot = hRoot;
                hir = (HIR)hirRoot.hir;
                ioRoot = iRoot;
                hirRoot.programRoot = hir.program(null, symRoot.symTableRoot, null, null);
        }

  final public void program() throws ParseException {
    Subp lPrintf, lMain;
    SubpDefinition lMainDef;
    BlockStmt lBlockStmt;
        // Prepare to define main program.
        // See defineSubp of Sym.java.
        lMain = sym.defineSubp("main".intern(), symRoot.typeInt);
        lMain.setVisibility(Sym.SYM_PUBLIC);
        //---- Build HIR ----//
        //printf(char* pFormat, ...);
        lPrintf = sym.defineSubp("printf(".intern(), symRoot.typeInt);
        Type lCharPtr = sym.pointerType(symRoot.typeChar);
        SymTable lLocalSymTable1 = symRoot.symTableRoot.pushSymTable(lPrintf);
        Param lParam1 = sym.defineParam("pFormat".intern(), lCharPtr);
        lPrintf.addParam(lParam1);
        lPrintf.setVisibility(Sym.SYM_EXTERN);
        lPrintf.closeSubpPrototype();
        lLocalSymTable1.popSymTable();
        //main
        symRoot.symTableCurrent.pushSymTable(lMain);
        lMain.closeSubpHeader();
        lMainDef = hir.subpDefinition(lMain, symRoot.symTableCurrent);
        ((Program)hirRoot.programRoot).addSubpDefinition(lMainDef);
        lBlockStmt = hir.blockStmt(null);
    label_1:
    while (true) {
      block(lBlockStmt);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case MAIN:
      case UNDEFINEDID:
        ;
        break;
      default:
        jj_la1[0] = jj_gen;
        break label_1;
      }
    }
    jj_consume_token(0);
        lMainDef.setHirBody(lBlockStmt); // 実行文のブロックをmainに接続
        symRoot.symTableCurrent.popSymTable();   // mainの記号表を閉じる。
        if (((HIR)hirRoot.programRoot).finishHir()) {
        } else {
        }
        hir.print(0);
  }

  final public void block(BlockStmt lBlockStmt) throws ParseException {
    BlockStmt lBlockStatement;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case UNDEFINEDID:
      dahlObjectClass();
      break;
    case MAIN:
      jj_consume_token(MAIN);
      jj_consume_token(LPAREN);
      lBlockStatement = stetementList(lBlockStmt);
      jj_consume_token(RPAREN);
      break;
    default:
      jj_la1[1] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  }

  final public void dahlObjectClass() throws ParseException {
    Token id;
    BlockStmt lBlockStatement;
    Stmt lStatement;
    Subp lSubp;
    SymTable lLocalSymTable;
    id = jj_consume_token(UNDEFINEDID);
        lSubp = sym.defineSubp(id.image.substring(0, id.image.length()-1).intern(), symRoot.typeInt);
        lSubp.setVisibility(Sym.SYM_PUBLIC);
        lSubp.closeSubpHeader();
        lLocalSymTable = symRoot.symTableCurrent.pushSymTable(lSubp);
        lBlockStatement = hir.blockStmt(null);
    jj_consume_token(LPAREN);
    lStatement = stetementList(lBlockStatement);
    jj_consume_token(RPAREN);
        SubpDefinition lDef = hir.subpDefinition(lSubp, symRoot.symTableCurrent);
        lDef.setHirBody(lBlockStatement);
        ((Program)hirRoot.programRoot).addSubpDefinition(lDef);
        symRoot.symTableCurrent.popSymTable();
  }

  final public BlockStmt stetementList(BlockStmt lBlockStatement) throws ParseException {
    Stmt lStmt;
    label_2:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case DIJKSTRA:
      case COROUTINDETACH:
      case COROUTINCALL:
      case COROUTINRESUME:
      case HOARE:
      case SELECT:
      case WHILE:
      case GOTO:
      case RETURN:
      case FOR:
      case EMPTYSTATEMENT:
      case PRINT:
      case MAIN:
      case UNDEFINEDID:
      case PROCEDUREID:
      case SELECTTHIS:
      case SELECTID:
      case ARRAYID:
      case DEFINEDID:
        ;
        break;
      default:
        jj_la1[2] = jj_gen;
        break label_2;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case EMPTYSTATEMENT:
        jj_consume_token(EMPTYSTATEMENT);
        break;
      case UNDEFINEDID:
        variableDeclaration(lBlockStatement);
        break;
      case HOARE:
        hoareCase(lBlockStatement);
        break;
      case PROCEDUREID:
        procedureCall();
        break;
      case DEFINEDID:
        variableAssignment();
        break;
      case SELECT:
        selectiveDeclaration(lBlockStatement);
        break;
      case SELECTTHIS:
      case SELECTID:
      case ARRAYID:
        selectiveUpdate();
        break;
      case WHILE:
        whileStatement(lBlockStatement);
        break;
      case FOR:
        forStatement(lBlockStatement);
        break;
      case GOTO:
        jump();
        break;
      case RETURN:
        returnStatement();
        break;
      case DIJKSTRA:
        dijkstraCocatnation();
        break;
      case PRINT:
        printf(lBlockStatement);
        break;
      case COROUTINDETACH:
        jj_consume_token(COROUTINDETACH);
        jj_consume_token(43);
        jj_consume_token(44);
        break;
      case COROUTINCALL:
        jj_consume_token(COROUTINCALL);
        jj_consume_token(43);
        jj_consume_token(DEFINEDID);
        jj_consume_token(44);
        break;
      case COROUTINRESUME:
        jj_consume_token(COROUTINRESUME);
        jj_consume_token(43);
        jj_consume_token(DEFINEDID);
        jj_consume_token(44);
        break;
      case MAIN:
        jj_consume_token(MAIN);
        jj_consume_token(LPAREN);
        stetementList(lBlockStatement);
        jj_consume_token(RPAREN);
         lStmt = hir.returnStmt(null);
         lBlockStatement.addLastStmt(lStmt);
        break;
      default:
        jj_la1[3] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
        {if (true) return lBlockStatement;}
    throw new Error("Missing return statement in function");
  }

  final public void printf(BlockStmt lBlockStatement) throws ParseException {
    Stmt lCallStmt;
    Token str;
    jj_consume_token(PRINT);
    jj_consume_token(43);
    str = jj_consume_token(STRING);
    jj_consume_token(44);
        //-- printf("");
        Subp lPrintf = (Subp) symRoot.symTableCurrent.search("printf(".intern(), Sym.KIND_SUBP);
        SubpNode lSubpNode1 = hir.subpNode(lPrintf);
        IrList lParamList = hir.irList();
        Const lStr1 = sym.stringConst( str.image.intern());

        //lParamList.add(lConstNode3);  This simplification is also permitted.
        lParamList.add(hir.decayExp( hir.constNode(lStr1) ));

        //lCallStmt may be simplified as
        //lCallStmt = hir.callStmt(lSubpNode1, lParamList);
        lCallStmt = hir.callStmt(hir.exp(HIR.OP_ADDR, lSubpNode1), lParamList);

        lBlockStatement.addLastStmt(lCallStmt);
  }

  final public void dijkstraCocatnation() throws ParseException {
    jj_consume_token(DIJKSTRA);
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case DEFINEDID:
      jj_consume_token(DEFINEDID);
      break;
    case STRING:
      jj_consume_token(STRING);
      break;
    default:
      jj_la1[4] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  }

  final public void variableDeclaration(BlockStmt lBlockStatement) throws ParseException {
    Token id;
    Type t;
    /*<UNDEFINEDID> = "variable:"で、変数名の最後に:が付く
         * その:を取り除くため、substringメソッドを使う*/
        id = jj_consume_token(UNDEFINEDID);
    typeOperation(id.image.substring(0, id.image.length()-1), lBlockStatement);
  }

  final public void typeOperation(String name, BlockStmt lBlockStatement) throws ParseException {
    Exp lExp;
    Type t;
    Token num;
    Var lVar;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case DEFINEDID:
      containElementSet(name, lBlockStatement);
      break;
    case PROCEDUREID:
      procedureDeclaration(lBlockStatement);
        t = symRoot.typeAddress;
      break;
    case 45:
      jj_consume_token(45);
      num = jj_consume_token(NUM);
      jj_consume_token(46);
      t = typeId();
        t = sym.vectorType( t, Long.parseLong(num.image) );
        lVar = sym.defineVar(name.intern(), t);
        lVar.setVisibility(Sym.SYM_PUBLIC);
      break;
    case NEW:
      jj_consume_token(NEW);
      jj_consume_token(DEFINEDID);
        t = symRoot.typeAddress;
        lVar = sym.defineVar(name.intern(), t);
        lVar.setVisibility(Sym.SYM_PUBLIC);
        Sym lSym = (Var)symRoot.symTableCurrent.search(name.intern());
      break;
    case LPAREN:
      jj_consume_token(LPAREN);
      block(lBlockStatement);
      jj_consume_token(RPAREN);
        t = symRoot.typeAddress;
      break;
    default:
      jj_la1[5] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  }

  final public Stmt containElementSet(String name, BlockStmt lBlockStatement) throws ParseException {
    Type lType;
    Exp lExp;
    Var lVar;
    Stmt lStmt;
    /*elment ∈ set
         *assignment() ∈ typeId()
         * example: <NUM> ∈ i
         * */
    
        lType = typeId();
    lExp = assignment();
        /*変数の定義と値の代入*/
        lVar = sym.defineVar(name.intern(), lType);
        lVar.setVisibility(Sym.SYM_PUBLIC);
        ioRoot.dbgHir.print(2, "variableDeclaration", lVar.toString() +
                        " " + lType.toString());
        Sym lSym = (Var)symRoot.symTableCurrent.search(name.intern());
        Exp lVarNode = hir.varNode((Var)lSym);
        lStmt = hir.assignStmt(lVarNode, lExp);
        {if (true) return lStmt;}
    throw new Error("Missing return statement in function");
  }

  final public Type typeId() throws ParseException {
    Token token;
    token = jj_consume_token(DEFINEDID);
        String t = token.image;
        if ( t.equals("i") ) {
            {if (true) return symRoot.typeLongLong;}
        } else if ( t.equals("i8") ) {
            {if (true) return symRoot.typeShort;}
        } else if ( t.equals("i16") ) {
            {if (true) return symRoot.typeInt;}
        } else if ( t.equals("i32") ) {
            {if (true) return symRoot.typeLong;}
        } else if ( t.equals("i64") ) {
            {if (true) return symRoot.typeLongLong;}
        } else if ( t.equals("v") ) {
            {if (true) return symRoot.typeVoid;}
        } else if ( t.equals("f") ) {
            {if (true) return symRoot.typeLongDouble;}
        } else if ( t.equals("f16") ) {
            {if (true) return symRoot.typeFloat;}
        } else if ( t.equals("f32") ) {
            {if (true) return symRoot.typeDouble;}
        } else if ( t.equals("f64") ) {
            {if (true) return symRoot.typeLongDouble;}
        } else if ( t.equals("u") ) {
            {if (true) return symRoot.typeU_LongLong;}
        } else if ( t.equals("u8") ) {
            {if (true) return symRoot.typeU_Short;}
        } else if ( t.equals("u16") ) {
            {if (true) return symRoot.typeU_Int;}
        } else if ( t.equals("u32") ) {
            {if (true) return symRoot.typeU_Long;}
        } else if ( t.equals("u64") ) {
            {if (true) return symRoot.typeU_LongLong;}
        } else if ( t.equals("b") ) {
            {if (true) return symRoot.typeBool;}
        } else if ( t.equals("s") ) {
            {if (true) return symRoot.typeU_Char;}
        } else {
            {if (true) return symRoot.typeAddress;}
        }
    throw new Error("Missing return statement in function");
  }

  final public void procedureDeclaration(BlockStmt lBlockStatement) throws ParseException {
    Token token;
    Subp lProcedure;
    token = jj_consume_token(PROCEDUREID);
                lProcedure = sym.defineSubp(token.image.intern(), symRoot.typeInt);
                symRoot.symTableCurrent.pushSymTable(lProcedure);
    parameterList(lBlockStatement, lProcedure);
    jj_consume_token(LPAREN);
    stetementList(lBlockStatement);
    jj_consume_token(RPAREN);
        lProcedure.closeSubpHeader();
        ioRoot.dbgHir.print(2, "subpDeclaration", lProcedure.toString());
  }

  final public void parameterList(BlockStmt lBlockStatement, Subp lSubprogram) throws ParseException {
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case UNDEFINEDID:
      jj_consume_token(UNDEFINEDID);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case REFERENCE:
      case DEFINEDID:
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case REFERENCE:
          jj_consume_token(REFERENCE);
          break;
        default:
          jj_la1[6] = jj_gen;
          ;
        }
        jj_consume_token(DEFINEDID);
        break;
      case PROCEDUREID:
        procedureDeclaration(lBlockStatement);
        break;
      default:
        jj_la1[7] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      break;
    default:
      jj_la1[8] = jj_gen;
      ;
    }
    label_3:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case 47:
        ;
        break;
      default:
        jj_la1[9] = jj_gen;
        break label_3;
      }
      jj_consume_token(47);
      jj_consume_token(UNDEFINEDID);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case REFERENCE:
      case DEFINEDID:
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case REFERENCE:
          jj_consume_token(REFERENCE);
          break;
        default:
          jj_la1[10] = jj_gen;
          ;
        }
        jj_consume_token(DEFINEDID);
        break;
      case PROCEDUREID:
        procedureDeclaration(lBlockStatement);
        break;
      default:
        jj_la1[11] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
    jj_consume_token(44);
  }

  final public void hoareCase(BlockStmt lBlockStatement) throws ParseException {
    Exp lExp;
    jj_consume_token(HOARE);
    jj_consume_token(UNDEFINEDID);
    lExp = expression();
    jj_consume_token(44);
    jj_consume_token(LPAREN);
    label_4:
    while (true) {
      jj_consume_token(48);
      jj_consume_token(DEFINEDID);
      jj_consume_token(LPAREN);
      stetementList(lBlockStatement);
      jj_consume_token(RPAREN);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case 48:
        ;
        break;
      default:
        jj_la1[12] = jj_gen;
        break label_4;
      }
    }
    jj_consume_token(RPAREN);
  }

  final public void selectiveDeclaration(BlockStmt lBlockStatement) throws ParseException {
    Subp lProcedure;
    jj_consume_token(SELECT);
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case UNDEFINEDID:
      variableDeclaration(lBlockStatement);
      break;
    case PROCEDUREID:
      token = jj_consume_token(PROCEDUREID);
            lProcedure = sym.defineSubp(token.image.intern(), symRoot.typeInt);
            symRoot.symTableCurrent.pushSymTable(lProcedure);
      parameterList(lBlockStatement, lProcedure);
      jj_consume_token(LPAREN);
      stetementList(lBlockStatement);
      jj_consume_token(RPAREN);
            lProcedure.closeSubpHeader();
            ioRoot.dbgHir.print(2, "subpDeclaration", lProcedure.toString());
      break;
    default:
      jj_la1[13] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  }

  final public Exp selectiveUpdate() throws ParseException {
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case ARRAYID:
      arrayAssignment();
        {if (true) return null;}
      break;
    case SELECTTHIS:
    case SELECTID:
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case SELECTTHIS:
        jj_consume_token(SELECTTHIS);
        break;
      case SELECTID:
        jj_consume_token(SELECTID);
        break;
      default:
        jj_la1[14] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case PROCEDUREID:
        procedureCall();
        break;
      case DEFINEDID:
        variableAssignment();
        break;
      case SELECTTHIS:
      case SELECTID:
      case ARRAYID:
        selectiveUpdate();
        break;
      default:
        jj_la1[15] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
        {if (true) return null;}
      break;
    default:
      jj_la1[16] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    throw new Error("Missing return statement in function");
  }

  final public void variableAssignment() throws ParseException {
    Exp lExp;
    jj_consume_token(DEFINEDID);
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case 51:
      lExp = assignment();
      break;
    case 49:
      jj_consume_token(49);
      break;
    case 50:
      jj_consume_token(50);
      break;
    default:
      jj_la1[17] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  }

  final public void arrayAssignment() throws ParseException {
    Exp lExp;
    jj_consume_token(ARRAYID);
    expression();
    jj_consume_token(46);
    lExp = assignment();
  }

  final public Exp assignment() throws ParseException {
    Exp lExp;
    jj_consume_token(51);
    lExp = expression();
        {if (true) return lExp;}
    throw new Error("Missing return statement in function");
  }

  final public Exp procedureCall() throws ParseException {
     Token id;
     Exp lExp;
    id = jj_consume_token(PROCEDUREID);
         String lSubpName = id.image.intern();
                               currentLine = id.beginLine;
                              Subp lSubp = (Subp)symRoot.symTableCurrent.search(lSubpName, Sym.KIND_SUBP);
                              if (lSubp == null) {
                                recoveredError("undeclared subprogram " + lSubpName, id.beginLine);
                                lSubp = sym.defineSubp(lSubpName, symRoot.typeInt);
                              }
                              IrList lParamList = hir.irList();
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case THIS:
    case PROCEDUREID:
    case SELECTTHIS:
    case SELECTID:
    case DEFINEDID:
    case NUM:
    case REALNUM:
    case STRING:
    case 61:
    case 62:
      lExp = expression();
                                      lParamList.add(lExp);
      label_5:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case 47:
          ;
          break;
        default:
          jj_la1[18] = jj_gen;
          break label_5;
        }
        jj_consume_token(47);
        lExp = expression();
                                           lParamList.add(lExp);
      }
      break;
    default:
      jj_la1[19] = jj_gen;
      ;
    }
    jj_consume_token(44);
                            {if (true) return hir.functionExp(hir.exp(HIR.OP_ADDR, hir.subpNode(lSubp)), lParamList);}
    throw new Error("Missing return statement in function");
  }

  final public void whileStatement(BlockStmt lBlockStatement) throws ParseException {
    jj_consume_token(WHILE);
    conditionalExpression();
    jj_consume_token(44);
    jj_consume_token(LPAREN);
    stetementList(lBlockStatement);
    jj_consume_token(RPAREN);
  }

  final public void forStatement(BlockStmt lBlockStatement) throws ParseException {
    jj_consume_token(FOR);
    jj_consume_token(44);
    jj_consume_token(LPAREN);
    stetementList(lBlockStatement);
    jj_consume_token(RPAREN);
  }

  final public void jump() throws ParseException {
    jj_consume_token(GOTO);
    jj_consume_token(DEFINEDID);
  }

  final public void returnStatement() throws ParseException {
    jj_consume_token(RETURN);
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case THIS:
    case PROCEDUREID:
    case SELECTTHIS:
    case SELECTID:
    case DEFINEDID:
    case NUM:
    case REALNUM:
    case STRING:
    case 61:
    case 62:
      expression();
      break;
    case EMPTYSTATEMENT:
      jj_consume_token(EMPTYSTATEMENT);
      break;
    default:
      jj_la1[20] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
  }

  final public void externalDecl() throws ParseException {
                   Subp lSubp; BlockStmt lBlockStmt; Stmt lStmt;
    if (jj_2_1(3)) {
      variableDecl();
    } else {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case DEFINEDID:
        lSubp = subpDeclarator();
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case EMPTYSTATEMENT:
          jj_consume_token(EMPTYSTATEMENT);
                               lSubp.setVisibility(Sym.SYM_EXTERN);
                               symRoot.symTableCurrent.popSymTable();
          break;
        case LPAREN:
          jj_consume_token(LPAREN);
          label_6:
          while (true) {
            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
            case UNDEFINEDID:
              ;
              break;
            default:
              jj_la1[21] = jj_gen;
              break label_6;
            }
            variableDecl();
          }
                                      lBlockStmt = hir.blockStmt(null);
          label_7:
          while (true) {
            switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
            case LPAREN:
            case WHILE:
            case RETURN:
            case PROCEDUREID:
            case SELECTTHIS:
            case SELECTID:
            case DEFINEDID:
            case IF:
              ;
              break;
            default:
              jj_la1[22] = jj_gen;
              break label_7;
            }
            lStmt = stmt();
                               lBlockStmt.addLastStmt(lStmt);
          }
                               lSubp.setVisibility(Sym.SYM_PUBLIC);
                               SubpDefinition lSubpDef
                                    = hir.subpDefinition(lSubp, symRoot.symTableCurrent);
                               lSubpDef.setHirBody(lBlockStmt);
                               ((Program)hirRoot.programRoot).addSubpDefinition(lSubpDef);
                               symRoot.symTableCurrent.popSymTable();
          jj_consume_token(RPAREN);
          break;
        default:
          jj_la1[23] = jj_gen;
          jj_consume_token(-1);
          throw new ParseException();
        }
        break;
      default:
        jj_la1[24] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
  }

  final public void variableDecl() throws ParseException {
                   Type t;
    jj_consume_token(UNDEFINEDID);
    t = typeId();
    varDecl(t);
    label_8:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case 47:
        ;
        break;
      default:
        jj_la1[25] = jj_gen;
        break label_8;
      }
      jj_consume_token(47);
      varDecl(t);
    }
    jj_consume_token(EMPTYSTATEMENT);
  }

  final public void varDecl(Type t) throws ParseException {
                    Token id, num; Var lVar; Type lType;
    id = jj_consume_token(ID);
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case 45:
      jj_consume_token(45);
      num = jj_consume_token(NUM);
      jj_consume_token(46);
                lType = sym.vectorType(t, Long.parseLong(num.image));
      break;
    default:
      jj_la1[26] = jj_gen;
                lType = t;
    }
                lVar = sym.defineVar(id.image.intern(), lType);
                lVar.setVisibility(Sym.SYM_PUBLIC);
                ioRoot.dbgHir.print(2, "variableDeclaration", lVar.toString() +
                        " " + lType.toString());
  }

  final public Subp subpDeclarator() throws ParseException {
                     Type t; Token id; Subp lSubp;
    t = typeId();
    id = jj_consume_token(ID);
                           lSubp = sym.defineSubp(id.image.intern(), t);
                                      symRoot.symTableCurrent.pushSymTable(lSubp);
    jj_consume_token(43);
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case DEFINEDID:
      paramDecl(lSubp);
      label_9:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case 47:
          ;
          break;
        default:
          jj_la1[27] = jj_gen;
          break label_9;
        }
        jj_consume_token(47);
        paramDecl(lSubp);
      }
      break;
    default:
      jj_la1[28] = jj_gen;
      ;
    }
    jj_consume_token(44);
                                       lSubp.closeSubpHeader();
                                       ioRoot.dbgHir.print(2, "subpDeclaration", lSubp.toString() +
                                       " " + t.toString());
                                       {if (true) return lSubp;}
    throw new Error("Missing return statement in function");
  }

  final public void paramDecl(Subp pSubp) throws ParseException {
                          Type t, lType; Token id;
    t = typeId();
    id = jj_consume_token(ID);
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case 45:
      jj_consume_token(45);
      jj_consume_token(46);
                     //lType = sym.pointerType(t); 
                     VectorType vType = sym.vectorTypeUnfixed(t, 0);
                     lType = sym.pointerType(vType);
      break;
    default:
      jj_la1[29] = jj_gen;
                     lType = t;
    }
                     Param lParam = sym.defineParam(id.image.intern(), lType);
                     pSubp.addParam(lParam);
                     ioRoot.dbgHir.print(2, "paramDeclaration", lParam.toString() +
                            " " + lType.toString());
  }

  final public Stmt stmt() throws ParseException {
           Token id; Stmt lStmt, lStmt2; Exp lExp, lExp2;
    if (jj_2_2(2)) {
      lExp = variable();
      jj_consume_token(51);
      lExp2 = expression();
      jj_consume_token(EMPTYSTATEMENT);
                                lStmt = hir.assignStmt(lExp, lExp2);
    } else {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case IF:
        id = jj_consume_token(IF);
        jj_consume_token(43);
        lExp = conditionalExpression();
        jj_consume_token(44);
        lStmt = stmt();
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case ELSE:
          jj_consume_token(ELSE);
          lStmt2 = stmt();
                                lStmt = hir.ifStmt(lExp, lStmt, lStmt2);
          break;
        default:
          jj_la1[30] = jj_gen;
                                lStmt = hir.ifStmt(lExp, lStmt, null);
        }
                                currentLine = id.beginLine;
        break;
      case WHILE:
        jj_consume_token(WHILE);
        jj_consume_token(43);
        lExp = conditionalExpression();
        jj_consume_token(44);
        lStmt = stmt();
                                lStmt = hir.whileStmt(lExp, lStmt);
        break;
      case LPAREN:
        jj_consume_token(LPAREN);
                                 BlockStmt lBlockStmt = hir.blockStmt(null);
        label_10:
        while (true) {
          switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
          case LPAREN:
          case WHILE:
          case RETURN:
          case PROCEDUREID:
          case SELECTTHIS:
          case SELECTID:
          case DEFINEDID:
          case IF:
            ;
            break;
          default:
            jj_la1[31] = jj_gen;
            break label_10;
          }
          lStmt = stmt();
                           lBlockStmt.addLastStmt(lStmt);
        }
        jj_consume_token(RPAREN);
                                  lStmt = lBlockStmt;
        break;
      case DEFINEDID:
        lExp = callExpr();
        jj_consume_token(EMPTYSTATEMENT);
                             lStmt = hir.expStmt(lExp);
        break;
      case RETURN:
        id = jj_consume_token(RETURN);
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case THIS:
        case PROCEDUREID:
        case SELECTTHIS:
        case SELECTID:
        case DEFINEDID:
        case NUM:
        case REALNUM:
        case STRING:
        case 61:
        case 62:
          lExp = expression();
                               lStmt = hir.returnStmt(lExp);
          break;
        default:
          jj_la1[32] = jj_gen;
                                lStmt = hir.returnStmt(null);
        }
        jj_consume_token(EMPTYSTATEMENT);
                                currentLine = id.beginLine;
        break;
      default:
        jj_la1[33] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
                                if (lStmt != null)
                                  ioRoot.dbgHir.print(2, "makeStmt", lStmt.toString());
                                lStmt.setLineNumber(currentLine);
                                currentLine = 0; // Set 0 so as it is set at ID processing.
                                {if (true) return lStmt;}
    throw new Error("Missing return statement in function");
  }

  final public Exp conditionalExpression() throws ParseException {
                            Exp lExp, lExp2; int op;
    lExp = expression();
    op = comparisonOperator();
    lExp2 = expression();
                             lExp = hir.exp(op, lExp, lExp2);
                             ioRoot.dbgHir.print(2, "makeConditionalExp", lExp.toString());
                             {if (true) return lExp;}
    throw new Error("Missing return statement in function");
  }

  final public int comparisonOperator() throws ParseException {
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case 55:
      jj_consume_token(55);
                         {if (true) return HIR.OP_CMP_EQ;}
      break;
    case 56:
      jj_consume_token(56);
                         {if (true) return HIR.OP_CMP_NE;}
      break;
    case 57:
      jj_consume_token(57);
                        {if (true) return HIR.OP_CMP_GT;}
      break;
    case 58:
      jj_consume_token(58);
                        {if (true) return HIR.OP_CMP_GE;}
      break;
    case 59:
      jj_consume_token(59);
                        {if (true) return HIR.OP_CMP_LT;}
      break;
    case 60:
      jj_consume_token(60);
                        {if (true) return HIR.OP_CMP_LE;}
      break;
    default:
      jj_la1[34] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    throw new Error("Missing return statement in function");
  }

  final public Exp expression() throws ParseException {
                 Exp lExp, lExp2;
    lExp = term();
    label_11:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case 61:
      case 62:
        ;
        break;
      default:
        jj_la1[35] = jj_gen;
        break label_11;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case 61:
        jj_consume_token(61);
        lExp2 = term();
                               lExp = hir.exp(HIR.OP_ADD, lExp, lExp2);
        break;
      case 62:
        jj_consume_token(62);
        lExp2 = term();
                                lExp = hir.exp(HIR.OP_SUB, lExp, lExp2);
        break;
      default:
        jj_la1[36] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
                                        {if (true) return lExp;}
    throw new Error("Missing return statement in function");
  }

  final public Exp term() throws ParseException {
           Exp lExp, lExp2;
    lExp = factor();
    label_12:
    while (true) {
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case 48:
      case 63:
        ;
        break;
      default:
        jj_la1[37] = jj_gen;
        break label_12;
      }
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case 48:
        jj_consume_token(48);
        lExp2 = factor();
                                 lExp = hir.exp(HIR.OP_MULT, lExp, lExp2);
        break;
      case 63:
        jj_consume_token(63);
        lExp2 = factor();
                                 lExp = hir.exp(HIR.OP_DIV, lExp, lExp2);
        break;
      default:
        jj_la1[38] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
    }
                                       {if (true) return lExp;}
    throw new Error("Missing return statement in function");
  }

  final public Exp factor() throws ParseException {
             Exp lExp; Token num; IntConst lConst; FloatConst fConst;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case 61:
      jj_consume_token(61);
      lExp = factor();
                              {if (true) return lExp;}
      break;
    case 62:
      jj_consume_token(62);
      lExp = factor();
                              {if (true) return hir.exp(HIR.OP_NEG, lExp);}
      break;
    case PROCEDUREID:
    case SELECTTHIS:
    case SELECTID:
    case DEFINEDID:
      lExp = variable();
                              {if (true) return lExp;}
      break;
    case THIS:
      jj_consume_token(THIS);
                     lConst = sym.intConst(12, symRoot.typeInt);
                                    {if (true) return hir.constNode(lConst);}
      break;
    case NUM:
      num = jj_consume_token(NUM);
                       lConst = sym.intConst(Long.parseLong(num.image), symRoot.typeInt);
                                    {if (true) return hir.constNode(lConst);}
      break;
    case REALNUM:
      num = jj_consume_token(REALNUM);
                      fConst = sym.floatConst(Double.parseDouble(num.image), symRoot.typeLongDouble);
                                    {if (true) return hir.constNode(fConst);}
      break;
    case STRING:
      num = jj_consume_token(STRING);
                     lConst = sym.intConst(0, symRoot.typeInt);
                                    {if (true) return hir.constNode(lConst);}
      break;
    default:
      jj_la1[39] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
    throw new Error("Missing return statement in function");
  }

  final public Exp variable() throws ParseException {
            Token id; Exp lExp;
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case PROCEDUREID:
      lExp = procedureCall();
      break;
    case SELECTTHIS:
    case SELECTID:
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case SELECTTHIS:
        jj_consume_token(SELECTTHIS);
        break;
      case SELECTID:
        jj_consume_token(SELECTID);
        break;
      default:
        jj_la1[40] = jj_gen;
        jj_consume_token(-1);
        throw new ParseException();
      }
      lExp = variable();
      break;
    case DEFINEDID:
      id = jj_consume_token(DEFINEDID);
                if (currentLine == 0) {
                             currentLine = id.beginLine;
                }
                Sym lSym = (Var)symRoot.symTableCurrent.search(id.image.intern());
                if (!(lSym instanceof Var)) {
                    recoveredError("undeclared variable " + id.image, id.beginLine);
                    lSym = sym.defineVar(id.image.intern(), symRoot.typeInt);
                }
                Exp lVarNode = hir.varNode((Var)lSym);
      switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
      case 45:
        jj_consume_token(45);
        lExp = expression();
        jj_consume_token(46);
                                 if (lSym.getSymType() instanceof PointerType)
                                       lExp = hir.subscriptedExp(hir.contentsExp(lVarNode), lExp);
                                  else
                                       lExp = hir.subscriptedExp(lVarNode, lExp);
        break;
      default:
        jj_la1[41] = jj_gen;
                                  if (lSym.getSymType() instanceof VectorType)
                                       lExp = hir.exp(HIR.OP_ADDR, lVarNode);
                                   else
                                       lExp = lVarNode;
      }
      break;
    default:
      jj_la1[42] = jj_gen;
      jj_consume_token(-1);
      throw new ParseException();
    }
                             ioRoot.dbgHir.print(4, "makeVariable",lExp.toString());
                              {if (true) return lExp;}
    throw new Error("Missing return statement in function");
  }

  final public Exp callExpr() throws ParseException {
               Token id; Exp lExp;
    id = jj_consume_token(DEFINEDID);
                     String lSubpName = id.image.intern();
                               currentLine = id.beginLine;
                              Subp lSubp = (Subp)symRoot.symTableCurrent.search(lSubpName, Sym.KIND_SUBP);
                              if (lSubp == null) {
                                recoveredError("undeclared subprogram " + lSubpName, id.beginLine);
                                lSubp = sym.defineSubp(lSubpName, symRoot.typeInt);
                              }
                              IrList lParamList = hir.irList();
    jj_consume_token(43);
    switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
    case THIS:
    case PROCEDUREID:
    case SELECTTHIS:
    case SELECTID:
    case DEFINEDID:
    case NUM:
    case REALNUM:
    case STRING:
    case 61:
    case 62:
      lExp = expression();
                                           lParamList.add(lExp);
      label_13:
      while (true) {
        switch ((jj_ntk==-1)?jj_ntk():jj_ntk) {
        case 47:
          ;
          break;
        default:
          jj_la1[43] = jj_gen;
          break label_13;
        }
        jj_consume_token(47);
        lExp = expression();
                                           lParamList.add(lExp);
      }
      break;
    default:
      jj_la1[44] = jj_gen;
      ;
    }
    jj_consume_token(44);
                            {if (true) return hir.functionExp(hir.exp(HIR.OP_ADDR, hir.subpNode(lSubp)), lParamList);}
    throw new Error("Missing return statement in function");
  }

  void recoveredError(String pMessage, int pLine) throws ParseException {
    if (pLine > 0)
      ioRoot.msgRecovered.put(pMessage + " line " + pLine);
    else
      ioRoot.msgRecovered.put(pMessage);
  }

  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_3R_18() {
    if (jj_3R_21()) return true;
    return false;
  }

  private boolean jj_3R_15() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_18()) {
    jj_scanpos = xsp;
    if (jj_3R_19()) {
    jj_scanpos = xsp;
    if (jj_3R_20()) return true;
    }
    }
    return false;
  }

  private boolean jj_3R_14() {
    if (jj_scan_token(UNDEFINEDID)) return true;
    if (jj_3R_16()) return true;
    if (jj_3R_17()) return true;
    return false;
  }

  private boolean jj_3R_34() {
    if (jj_scan_token(STRING)) return true;
    return false;
  }

  private boolean jj_3R_33() {
    if (jj_scan_token(REALNUM)) return true;
    return false;
  }

  private boolean jj_3R_32() {
    if (jj_scan_token(NUM)) return true;
    return false;
  }

  private boolean jj_3R_31() {
    if (jj_scan_token(THIS)) return true;
    return false;
  }

  private boolean jj_3R_30() {
    if (jj_3R_15()) return true;
    return false;
  }

  private boolean jj_3R_29() {
    if (jj_scan_token(62)) return true;
    return false;
  }

  private boolean jj_3R_27() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_28()) {
    jj_scanpos = xsp;
    if (jj_3R_29()) {
    jj_scanpos = xsp;
    if (jj_3R_30()) {
    jj_scanpos = xsp;
    if (jj_3R_31()) {
    jj_scanpos = xsp;
    if (jj_3R_32()) {
    jj_scanpos = xsp;
    if (jj_3R_33()) {
    jj_scanpos = xsp;
    if (jj_3R_34()) return true;
    }
    }
    }
    }
    }
    }
    return false;
  }

  private boolean jj_3R_28() {
    if (jj_scan_token(61)) return true;
    return false;
  }

  private boolean jj_3R_22() {
    if (jj_scan_token(45)) return true;
    return false;
  }

  private boolean jj_3_1() {
    if (jj_3R_14()) return true;
    return false;
  }

  private boolean jj_3R_24() {
    if (jj_3R_25()) return true;
    return false;
  }

  private boolean jj_3R_16() {
    if (jj_scan_token(DEFINEDID)) return true;
    return false;
  }

  private boolean jj_3R_26() {
    if (jj_3R_27()) return true;
    return false;
  }

  private boolean jj_3R_25() {
    if (jj_3R_26()) return true;
    return false;
  }

  private boolean jj_3R_20() {
    if (jj_scan_token(DEFINEDID)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_22()) {
    jj_scanpos = xsp;
    if (jj_3R_23()) return true;
    }
    return false;
  }

  private boolean jj_3R_21() {
    if (jj_scan_token(PROCEDUREID)) return true;
    Token xsp;
    xsp = jj_scanpos;
    if (jj_3R_24()) jj_scanpos = xsp;
    if (jj_scan_token(44)) return true;
    return false;
  }

  private boolean jj_3R_17() {
    if (jj_scan_token(ID)) return true;
    return false;
  }

  private boolean jj_3R_19() {
    Token xsp;
    xsp = jj_scanpos;
    if (jj_scan_token(29)) {
    jj_scanpos = xsp;
    if (jj_scan_token(30)) return true;
    }
    if (jj_3R_15()) return true;
    return false;
  }

  private boolean jj_3R_23() {
    return false;
  }

  private boolean jj_3_2() {
    if (jj_3R_15()) return true;
    if (jj_scan_token(51)) return true;
    return false;
  }

  /** Generated Token Manager. */
  public JostarParserTokenManager token_source;
  SimpleCharStream 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;
  /** Whether we are looking ahead. */
  private boolean jj_lookingAhead = false;
  private boolean jj_semLA;
  private int jj_gen;
  final private int[] jj_la1 = new int[45];
  static private int[] jj_la1_0;
  static private int[] jj_la1_1;
  static {
      jj_la1_init_0();
      jj_la1_init_1();
   }
   private static void jj_la1_init_0() {
      jj_la1_0 = new int[] {0xc000000,0xc000000,0xfff11f00,0xfff11f00,0x0,0x10024000,0x2000,0x10002000,0x8000000,0x0,0x2000,0x10002000,0x0,0x18000000,0x60000000,0xf0000000,0xe0000000,0x0,0x0,0x70008000,0x71008000,0x8000000,0x70520000,0x1020000,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x70520000,0x70008000,0x520000,0x0,0x0,0x0,0x0,0x0,0x70008000,0x60000000,0x0,0x70000000,0x0,0x70008000,};
   }
   private static void jj_la1_init_1() {
      jj_la1_1 = new int[] {0x0,0x0,0x1,0x1,0x81,0x2001,0x0,0x1,0x0,0x8000,0x0,0x1,0x10000,0x0,0x0,0x1,0x0,0xe0000,0x8000,0x60000087,0x60000087,0x0,0x200001,0x0,0x1,0x8000,0x2000,0x8000,0x1,0x2000,0x400000,0x200001,0x60000087,0x200001,0x1f800000,0x60000000,0x60000000,0x80010000,0x80010000,0x60000087,0x0,0x2000,0x1,0x8000,0x60000087,};
   }
  final private JJCalls[] jj_2_rtns = new JJCalls[2];
  private boolean jj_rescan = false;
  private int jj_gc = 0;

  /** Constructor with InputStream. */
  public JostarParser(java.io.InputStream stream) {
     this(stream, null);
  }
  /** Constructor with InputStream and supplied encoding */
  public JostarParser(java.io.InputStream stream, String encoding) {
    try { jj_input_stream = new SimpleCharStream(stream, encoding, 1, 1); } catch(java.io.UnsupportedEncodingException e) { throw new RuntimeException(e); }
    token_source = new JostarParserTokenManager(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 45; 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;
    jj_gen = 0;
    for (int i = 0; i < 45; i++) jj_la1[i] = -1;
    for (int i = 0; i < jj_2_rtns.length; i++) jj_2_rtns[i] = new JJCalls();
  }

  /** Constructor. */
  public JostarParser(java.io.Reader stream) {
    jj_input_stream = new SimpleCharStream(stream, 1, 1);
    token_source = new JostarParserTokenManager(jj_input_stream);
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 45; 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;
    jj_gen = 0;
    for (int i = 0; i < 45; 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 JostarParser(JostarParserTokenManager tm) {
    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 45; 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(JostarParserTokenManager tm) {
    token_source = tm;
    token = new Token();
    jj_ntk = -1;
    jj_gen = 0;
    for (int i = 0; i < 45; 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;
          }
        }
      }
      return token;
    }
    token = oldToken;
    jj_kind = kind;
    throw generateParseException();
  }

  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++;
    return token;
  }

/** Get the specific Token. */
  final public Token getToken(int index) {
    Token t = jj_lookingAhead ? jj_scanpos : 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() {
    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 jj_expentries = new java.util.ArrayList();
  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];
      }
      boolean exists = false;
      for (java.util.Iterator it = jj_expentries.iterator(); it.hasNext();) {
        int[] oldentry = (int[])(it.next());
        if (oldentry.length == jj_expentry.length) {
          exists = true;
          for (int i = 0; i < jj_expentry.length; i++) {
            if (oldentry[i] != jj_expentry[i]) {
              exists = false;
              break;
            }
          }
          if (exists) break;
        }
      }
      if (!exists) jj_expentries.add(jj_expentry);
      if (pos != 0) jj_lasttokens[(jj_endpos = pos) - 1] = kind;
    }
  }

  /** Generate ParseException. */
  public ParseException generateParseException() {
    jj_expentries.clear();
    boolean[] la1tokens = new boolean[64];
    if (jj_kind >= 0) {
      la1tokens[jj_kind] = true;
      jj_kind = -1;
    }
    for (int i = 0; i < 45; 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;
          }
        }
      }
    }
    for (int i = 0; i < 64; 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] = (int[])jj_expentries.get(i);
    }
    return new ParseException(token, exptokseq, tokenImage);
  }

  /** Enable tracing. */
  final public void enable_tracing() {
  }

  /** Disable tracing. */
  final public void disable_tracing() {
  }

  private void jj_rescan_token() {
    jj_rescan = true;
    for (int i = 0; i < 2; 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;
          }
        }
        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;
  }

}
