public class RESCharStream implements CharStream
{
/** Whether parser is static. */
  public static final boolean staticFlag = false;
  int bufsize;
   int available;
   int tokenBegin;
/** Position in buffer. */
   public int bufpos = -1;
   protected int bufline[];
   protected int bufcolumn[];
   protected String bufsourcefile[];

   protected int column = 0;
   protected int line = 1;
   protected String fileName="";

   protected boolean prevCharIsCR = false;
   protected boolean prevCharIsLF = false;
  
   protected java.io.Reader inputStream;

   protected char[] buffer;
   protected int maxNextCharInd = 0;
   protected int inBuf = 0;
   protected int tabSize = 8;

   protected void setTabSize(int i) { tabSize = i; }
   protected int getTabSize(int i) { return tabSize; }
 
  protected void ExpandBuff(boolean wrapAround)
  {
    char[] newbuffer = new char[bufsize + 2048];
    int newbufline[] = new int[bufsize + 2048];
    int newbufcolumn[] = new int[bufsize + 2048];
    String newbufsourcefile[] = new String[bufsize + 2048];

    try
    {
    	
      if (wrapAround)
      {
        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
        System.arraycopy(buffer, 0, newbuffer, bufsize - tokenBegin, bufpos);
        buffer = newbuffer;

        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
        System.arraycopy(bufline, 0, newbufline, bufsize - tokenBegin, bufpos);
        bufline = newbufline;

        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
        System.arraycopy(bufcolumn, 0, newbufcolumn, bufsize - tokenBegin, bufpos);
        bufcolumn = newbufcolumn;

        System.arraycopy(bufsourcefile, tokenBegin, newbufsourcefile, 0, bufsize - tokenBegin);
        System.arraycopy(bufsourcefile, 0, newbufsourcefile, bufsize - tokenBegin, bufpos);
        bufsourcefile = newbufsourcefile;

        maxNextCharInd = (bufpos += (bufsize - tokenBegin));
      }
      else
      {
        System.arraycopy(buffer, tokenBegin, newbuffer, 0, bufsize - tokenBegin);
        buffer = newbuffer;

        System.arraycopy(bufline, tokenBegin, newbufline, 0, bufsize - tokenBegin);
        bufline = newbufline;

        System.arraycopy(bufcolumn, tokenBegin, newbufcolumn, 0, bufsize - tokenBegin);
        bufcolumn = newbufcolumn;

        System.arraycopy(bufsourcefile, tokenBegin, newbufsourcefile, 0, bufsize - tokenBegin);
        bufsourcefile = newbufsourcefile;

        maxNextCharInd = (bufpos -= tokenBegin);
      }
    }
    catch (Throwable t)
    {
      throw new Error(t.getMessage());
    }


    bufsize += 2048;
    available = bufsize;
    tokenBegin = 0;
  }

  protected void FillBuff() throws java.io.IOException
  {
    if (maxNextCharInd == available)
    {
      if (available == bufsize)
      {
        if (tokenBegin > 2048)
        {
          bufpos = maxNextCharInd = 0;
          available = tokenBegin;
        }
        else if (tokenBegin < 0)
          bufpos = maxNextCharInd = 0;
        else
          ExpandBuff(false);
      }
      else if (available > tokenBegin)
        available = bufsize;
      else if ((tokenBegin - available) < 2048)
        ExpandBuff(true);
      else
        available = tokenBegin;
    }

    int i;
    try {
      if ((i = inputStream.read(buffer, maxNextCharInd, available - maxNextCharInd)) == -1)
      {
        inputStream.close();
        throw new java.io.IOException();
      }
      else
        maxNextCharInd += i;
      return;
    }
    catch(java.io.IOException e) {
      --bufpos;
      backup(0);
      if (tokenBegin == -1)
        tokenBegin = bufpos;
      throw e;
    }
  }

/** Start. */
  public char BeginToken() throws java.io.IOException
  {
	  tokenLength=0;
    tokenBegin = -1;
    char c = readChar();
    tokenBegin = bufpos;

    return c;
  }

  private char forceReadChar () throws IOException  {
	   if (++bufpos >= maxNextCharInd) {
		      FillBuff();
	   }
	   return buffer[bufpos];
	  
  }
  private  int tokenLength=0;
  private Pattern fileNamePattern =Pattern.compile("(/[^/:\\*\\?<>\\|]+[\\.\\w{2,6}]?)+|([A-Z]:\\\\[^/:\\*\\?<>\\|]+[\\.\\w{2,6}]?)");

  private  String sourceFileName=null;
  public  String getLastSourceFileName() {
	  return getBeginSourceFile();
  }
  protected void UpdateLineColumn(char c) throws java.io.IOException
  {
	  column++;
	    
	    if (prevCharIsLF)
	    {
	      prevCharIsLF = false;
	      line += (column = 1);
	    }
	    else if (prevCharIsCR)
	    {
	      prevCharIsCR = false;
	      if (c == '\n')
	      {
	        prevCharIsLF = true;
	      }
	      else
	        line += (column = 1);
	    }

	  preprocessorLineStart:	  
	  while(c=='#')  {//Preprocessor line containing line number and file
		  
		  boolean isPreProcessorError=false;
		  int prevBufpos=bufpos;
		  
		  char c2=forceReadChar();
		  
		   while(c2==' ') {
			   c2=forceReadChar();
		   };

		  int lineCalc=0;
		  while(c2>='0'&&c2<='9') {
			  lineCalc*=10;
			  switch(c2) {
			  case '0':break;
			  case '1':lineCalc+=1;break;
			  case '2':lineCalc+=2;break;
			  case '3':lineCalc+=3;break;
			  case '4':lineCalc+=4;break;
			  case '5':lineCalc+=5;break;
			  case '6':lineCalc+=6;break;
			  case '7':lineCalc+=7;break;
			  case '8':lineCalc+=8;break;
			  case '9':lineCalc+=9;break;
			  default: bufpos=prevBufpos;break preprocessorLineStart;
			  }
			  c2=forceReadChar();
		   } ;

		   while(c2==' ') {
			   c2=forceReadChar();
		   };

		   
		   StringBuffer fileName=new StringBuffer("");
		   int numQuote=0;
		   
		   while(c2!='\r'&&c2!='\n'){
			   if(numQuote>2){bufpos=prevBufpos;break preprocessorLineStart;}
			  switch(c2) {
			  case '\"':
				  ++numQuote;
				  break;
			  case ' ':break;
			  default:
				  if(numQuote==1)
						  fileName.append(c2);
				  else
					  isPreProcessorError=true;
			  }
			   c2=forceReadChar();
		   } ;
		   
		   
		   Matcher matcher = fileNamePattern.matcher(fileName.toString());
		   isPreProcessorError=!(matcher.matches());
		   if (isPreProcessorError||numQuote>2) {
			   bufpos=prevBufpos;break preprocessorLineStart;
		   }
		   
		   while(c2=='\r'||c2=='\n')
			   c2=forceReadChar();
		   if (bufpos >= prevBufpos) {
			  	  for(int pos=prevBufpos;bufpos > pos;++pos) {
			  		  deleteFromBuffer(pos);
			  	  }
	    	} else {
		  	  	for(int pos=prevBufpos;bufsize > pos;++pos) {
		  	  		deleteFromBuffer(pos);
		  	  	}
		  	  	for(int pos=0;bufpos > pos;++pos) {
		  	  		deleteFromBuffer(pos);
		  	  	}
		       
		   }
		   
		   c=buffer[bufpos];
		   line=lineCalc-1;
	       prevCharIsCR = false;
	       prevCharIsLF = false;
		   column=1;
		   sourceFileName=fileName.toString();
		   
	  }
	  

	  switch (c)
    {
      case '\r' :
        prevCharIsCR = true;
        break;
      case '\n' :
        prevCharIsLF = true;
        break;
      case '\t' :
        column--;
        column += (tabSize - (column % tabSize));
        break;
      default :
        break;
    }

    bufline[bufpos] = line;
    bufcolumn[bufpos] = column;
    bufsourcefile[bufpos] = sourceFileName;
  }
  public void deleteFromBuffer(int pos) {
	  buffer[pos]=0;
  }
  public void deleteLastReadFromBuffer(int posoffset) {
	  buffer[bufpos-posoffset]=0;
  }

/** Read a character. */
  public char readChar() throws java.io.IOException
  {

	 if(++tokenLength>4194303)
		 throw new Error();
    if (inBuf > 0)
    {
      --inBuf;

      if (++bufpos == bufsize)
        bufpos = 0;
      
      return buffer[bufpos];
    }
    
	
    if (++bufpos >= maxNextCharInd){
    		FillBuff();
    }

    char c = buffer[bufpos];

    UpdateLineColumn(c);
    c = buffer[bufpos];

    return c;
  }

  /**
   * @deprecated
   * @see #getEndColumn
   */

  public int getColumn() {
    return bufcolumn[bufpos];
  }

  /**
   * @deprecated
   * @see #getEndLine
   */

  public int getLine() {
    return bufline[bufpos];
  }

  /** Get token end column number. */
  public int getEndColumn() {
    return bufcolumn[bufpos];
  }

  /** Get token end source file. */
   public String getEndSourceFile() {
    return bufsourcefile[bufpos];
  }

  /** Get token end line number. */
  public int getEndLine() {
     return bufline[bufpos];
  }

  /** Get token beginning column number. */
  public int getBeginColumn() {
    return bufcolumn[tokenBegin];
  }

  /** Get token beginning column number. */
   public String getBeginSourceFile() {
    return bufsourcefile[tokenBegin];
  }
  /** Get token beginning line number. */
  public int getBeginLine() {
    return bufline[tokenBegin];
  }

  public  int getRESBeginLine() {
	    return bufline[tokenBegin];
  }
  
/** Backup a number of characters. */
  public void backup(int amount) {

    inBuf += amount;
    if ((bufpos -= amount) < 0)
      bufpos += bufsize;
  }

  /** Constructor. */
  public RESCharStream(java.io.Reader dstream, int startline,
  int startcolumn, int buffersize)
  {
   // if (inputStream != null)
      //throw new Error("\n   ERROR: Second call to the constructor of a static SimpleCharStream.\n" +
      //"       You must either use ReInit() or set the JavaCC option STATIC to false\n" +
      //"       during the generation of this class.");
    inputStream = dstream;
    line = startline;
    column = startcolumn - 1;

    available = bufsize = buffersize;
    buffer = new char[buffersize];
    bufline = new int[buffersize];
    bufcolumn = new int[buffersize];
    bufsourcefile = new String[buffersize];
  }

  /** Constructor. */
  public RESCharStream(java.io.Reader dstream, int startline,
                          int startcolumn)
  {
    this(dstream, startline, startcolumn, 4096);
  }

  /** Constructor. */
  public RESCharStream(java.io.Reader dstream)
  {
    this(dstream, 1, 1, 4096);
  }

  /** Reinitialise. *
  public void ReInit(java.io.Reader dstream, int startline,
  int startcolumn, int buffersize)
  {
    inputStream = dstream;
    line = startline;
    column = startcolumn - 1;

    if (buffer == null || buffersize != buffer.length)
    {
      available = bufsize = buffersize;
      buffer = new char[buffersize];
      bufline = new int[buffersize];
      bufcolumn = new int[buffersize];
      bufsourcefile = new String[buffersize];
    }
    prevCharIsLF = prevCharIsCR = false;
    tokenBegin = inBuf = maxNextCharInd = 0;
    bufpos = -1;
  }

  /** Reinitialise. *
  public void ReInit(java.io.Reader dstream, int startline,
                     int startcolumn)
  {
    ReInit(dstream, startline, startcolumn, 4096);
  }

  /** Reinitialise. *
  public void ReInit(java.io.Reader dstream)
  {
    ReInit(dstream, 1, 1, 4096);
  }
  /** Constructor. */
  public RESCharStream(java.io.InputStream dstream, String encoding, int startline,
  int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
  {
    this(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
  }

  /** Constructor. */
  public RESCharStream(java.io.InputStream dstream, int startline,
  int startcolumn, int buffersize)
  {
    this(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
  }

  /** Constructor. */
  public RESCharStream(java.io.InputStream dstream, String encoding, int startline,
                          int startcolumn) throws java.io.UnsupportedEncodingException
  {
    this(dstream, encoding, startline, startcolumn, 4096);
  }

  /** Constructor. */
  public RESCharStream(java.io.InputStream dstream, int startline,
                          int startcolumn)
  {
    this(dstream, startline, startcolumn, 4096);
  }

  /** Constructor. */
  public RESCharStream(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
  {
    this(dstream, encoding, 1, 1, 4096);
  }

  /** Constructor. */
  public RESCharStream(java.io.InputStream dstream)
  {
    this(dstream, 1, 1, 4096);
  }

  /** Reinitialise. *
  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
                          int startcolumn, int buffersize) throws java.io.UnsupportedEncodingException
  {
    ReInit(encoding == null ? new java.io.InputStreamReader(dstream) : new java.io.InputStreamReader(dstream, encoding), startline, startcolumn, buffersize);
  }

  /** Reinitialise. *
  public void ReInit(java.io.InputStream dstream, int startline,
                          int startcolumn, int buffersize)
  {
    ReInit(new java.io.InputStreamReader(dstream), startline, startcolumn, buffersize);
  }

  /** Reinitialise. *
  public void ReInit(java.io.InputStream dstream, String encoding) throws java.io.UnsupportedEncodingException
  {
    ReInit(dstream, encoding, 1, 1, 4096);
  }

  /** Reinitialise. *
  public void ReInit(java.io.InputStream dstream)
  {
    ReInit(dstream, 1, 1, 4096);
  }
  /** Reinitialise. *
  public void ReInit(java.io.InputStream dstream, String encoding, int startline,
                     int startcolumn) throws java.io.UnsupportedEncodingException
  {
    ReInit(dstream, encoding, startline, startcolumn, 4096);
  }
  /** Reinitialise. *
  public void ReInit(java.io.InputStream dstream, int startline,
                     int startcolumn)
  {
    ReInit(dstream, startline, startcolumn, 4096);
  }
  /** Get token literal value. */
  public String GetImage()
  {
	  StringBuffer image=new StringBuffer(32);
	 
	    	
	    if (bufpos >= tokenBegin) {
	  	  for(int pos=tokenBegin;bufpos >= pos;++pos) {
	  		  if(buffer[pos]==0) 
	  			  continue;
	  		  image.append(buffer[pos]);
	  	  }
	    	//return new String(buffer, tokenBegin, bufpos - tokenBegin + 1);
	    } else {
		  	  for(int pos=tokenBegin;bufsize > pos;++pos) {
		  		  if(buffer[pos]==0) 
		  			  continue;
		  		  image.append(buffer[pos]);
		  	  }
		  	  for(int pos=0;bufpos >= pos;++pos) {
		  		  if(buffer[pos]==0) 
		  			  continue;
		  		  image.append(buffer[pos]);
		  	  }
		       // return new String(buffer, tokenBegin, bufsize - tokenBegin) +
		        //	new String(buffer, 0, bufpos + 1);
	    }
	    return image.toString();
  }

  /** Get the suffix. */
  public char[] GetSuffix(int len)
  {
    char[] ret = new char[len];

    if ((bufpos + 1) >= len)
      System.arraycopy(buffer, bufpos - len + 1, ret, 0, len);
    else
    {
      System.arraycopy(buffer, bufsize - (len - bufpos - 1), ret, 0,
                                                        len - bufpos - 1);
      System.arraycopy(buffer, 0, ret, len - bufpos - 1, bufpos + 1);
    }

    return ret;
  }

  /** Reset buffer when finished. */
  public void Done()
  {
    buffer = null;
    bufline = null;
    bufcolumn = null;
    bufsourcefile=null;
  }

  /**
   * Method to adjust line and column numbers for the start of a token.
   */
  public void adjustBeginLineColumn(int newLine, int newCol)
  {
    int start = tokenBegin;
    int len;

    if (bufpos >= tokenBegin)
    {
      len = bufpos - tokenBegin + inBuf + 1;
    }
    else
    {
      len = bufsize - tokenBegin + bufpos + 1 + inBuf;
    }

    int i = 0, j = 0, k = 0;
    int nextColDiff = 0, columnDiff = 0;

    while (i < len && bufline[j = start % bufsize] == bufline[k = ++start % bufsize])
    {
      bufline[j] = newLine;
      nextColDiff = columnDiff + bufcolumn[k] - bufcolumn[j];
      bufcolumn[j] = newCol + columnDiff;
      columnDiff = nextColDiff;
      i++;
    }

    if (i < len)
    {
      bufline[j] = newLine++;
      bufcolumn[j] = newCol + columnDiff;

      while (i++ < len)
      {
        if (bufline[j = start % bufsize] != bufline[++start % bufsize])
          bufline[j] = newLine++;
        else
          bufline[j] = newLine;
      }
    }

    line = bufline[j];
    column = bufcolumn[j];
  }

}
 public class RESConfig implements Cloneable {

	public final String versionString = " alpha1.9(08/05/2010) ";
	private String programPackage;
	private String dataPackage ;
	private String outputDir=null;
	private String configFile="."+File.separatorChar+"Config.properties";
	private boolean longDataPackageName ;
	private boolean doListDir ;
	private boolean printCobolStatementsAsComments;
	private boolean retainCobolComments;
	private int optimizeAlgorithm=0;
	private boolean isEbcdicMachine=false;
	private boolean isFixedFormat=true;
	private boolean isBigEndian=true;
	private byte procedureFormat;//0-Use CobolMethod/Paragraph/Section classes;1-Switch-Case-Loop;2-Java Native Recursive
	private byte dataNameFormat;//0-first char upper for classes and lower for objects and fields, methods
	private boolean toMigrateVSAMISAM=false;
	private boolean toGenVSAMISAMDb=false;
	private boolean isOverwriteJavaFiles=false;
	private boolean isRenameJavaFiles=false;
	private boolean isInError=false;
	private boolean allSymbols=false;
	private boolean generateBeanInfo=false;
	private boolean exception_PrintStackTrace_On=false;
	private int inlineStatement=0;
	private int tabLength = 4;
	private int sqlDatabaseType = 0;
	private String tabSpaces = "    ";

	private static Properties config=null;
	
	public void loadDefaults() {
		try {
			config=new Properties();
			FileInputStream fis = new FileInputStream(new File(configFile));
			config.load(fis);
			programPackage =(String) config.getProperty("programPackage");
			dataPackage =(String) config.getProperty("dataPackage");
			outputDir = (String) config.getProperty("outputDir","");
			String s = (String)config.getProperty("printCobolStatementsAsComments","false");
			printCobolStatementsAsComments=false;
			s = (String)config.getProperty("retainCobolComments","false");
			retainCobolComments=false;
			s=config.getProperty("isEbcdicMachine","false");
			isEbcdicMachine=false;
			s=config.getProperty("isFixedFormat","true");
			isFixedFormat=true;
			s=config.getProperty("isBigEndian","true");
			isBigEndian=true;
			procedureFormat=0;
			s = (String)config.getProperty("dataNameFormat","0");
			dataNameFormat=new Byte(s.trim()).byteValue();
			s = (String)config.getProperty("isOverwriteJavaFiles","false");
			isOverwriteJavaFiles=new Boolean(s.trim()).booleanValue();
			s = config.getProperty("optimizeAlgorithm","0");
			optimizeAlgorithm=Integer.parseInt(s);
			s = config.getProperty("generateBeanInfo","false");
			generateBeanInfo=new Boolean(s.trim()).booleanValue();
			s = config.getProperty("exceptionPrintStackTraceOn","false");
			setExceptionPrintStackTraceOn(new Boolean(s.trim()).booleanValue());
			s = config.getProperty("tabLength","4");
			tabLength=Integer.parseInt(s);
			s = config.getProperty("sqlDatabaseType","1");
			sqlDatabaseType=Integer.parseInt(s);
			programPackage=applyNameValidation(programPackage);
			dataPackage=applyNameValidation(dataPackage);
		} catch(Exception e) {
			programPackage ="cobolprogramclasses";
			dataPackage ="coboldataclasses";
			outputDir="";
		}
		tabSpaces="";
		for(int i=0;i<tabLength;++i)
			tabSpaces+=' ';
	}
	
	private String applyNameValidation(String pkg) {
		StringBuffer pkgBuff=new StringBuffer(pkg);
		int i=0,j=0;
		while((j=pkgBuff.indexOf(".",i))>i) {
			pkgBuff.replace(i, j, NameUtil.convertCobolNameToJava(
					pkgBuff.substring(i, j), false).toLowerCase());
			i=j;
		}
		return pkgBuff.toString();
	}
	
	private static RESConfig resConfig=null;
	
	private RESConfig() {
	}
	
	public static RESConfig getInstance()  {
		if(resConfig==null){
			resConfig=new RESConfig();
			resConfig.loadDefaults();
		} 		
		return resConfig;
	}
	
	public void setDoListDir(boolean doListDir) {
		this.doListDir = doListDir;
	}

	public boolean isDoListDir() {
		return doListDir;
	}

	public boolean isFixedFormat() {
		return isFixedFormat;
	}

	public void setFixedFormat(boolean isFixedFormat) {
		this.isFixedFormat = isFixedFormat;
	}

	public boolean isEbcdicMachine() {
		return isEbcdicMachine;
	}
	public void setEbcdicMachine(boolean isEbcdicMachine) {
		this.isEbcdicMachine = isEbcdicMachine;
	}
	public String getProgramPackage() {
		return programPackage;
	}
	public void setProgramPackage(String programPackage) {
		this.programPackage = programPackage;
	}
	public String getDataPackage() {
		return dataPackage;
	}
	public void setDataPackage(String dataPackage) {
		this.dataPackage = dataPackage;
	}
	public boolean isPrintCobolStatementsAsComments() {
		return printCobolStatementsAsComments;
	}
	public void setPrintCobolStatementsAsComments(
			boolean printCobolStatementsAsComments) {
		this.printCobolStatementsAsComments = printCobolStatementsAsComments;
	}
	public boolean isRetainCobolComments() {
		return retainCobolComments;
	}
	public void setRetainCobolComments(boolean retainCobolComments) {
		this.retainCobolComments = retainCobolComments;
	}
	public byte getDataNameFormat() {
		return dataNameFormat;
	}
	public void setDataNameFormat(byte dataNameFormat) {
		this.dataNameFormat = dataNameFormat;
	}
	
	public void setBigEndian(boolean isBigEndian) {
		this.isBigEndian = isBigEndian;
	}

	public boolean isBigEndian() {
		return isBigEndian;
	}

	public void setProcedureFormat(byte procedureFormat) {
		this.procedureFormat = procedureFormat;
	}

	public byte getProcedureFormat() {
		return this.procedureFormat;
	}

	public void setInError(boolean isInError) {
		this.isInError = isInError;
	}

	public boolean isInError() {
		return isInError;
	}
	
	public boolean isOverwriteJavaFiles() {
		return isOverwriteJavaFiles;
	}

	public void setOverwriteJavaFiles(boolean isOverwriteJavaFiles) {
		this.isOverwriteJavaFiles = isOverwriteJavaFiles;
	}

	public boolean isRenameJavaFiles() {
		return isRenameJavaFiles;
	}

	public void setRenameJavaFiles(boolean isRenameJavaFiles) {
		this.isRenameJavaFiles = isRenameJavaFiles;
	}

	public void setOptimizeAlgorithm(int optimizeAlgorithm) {
		this.optimizeAlgorithm = optimizeAlgorithm;
	}

	public int getOptimizeAlgorithm() {
		return optimizeAlgorithm;
	}

	public void setLongDataPackageName(boolean longDataPackageName) {
		this.longDataPackageName = longDataPackageName;
	}

	public boolean isLongDataPackageName() {
		return longDataPackageName;
	}

	public void setToMigrateVSAMISAM(boolean toMigrateVSAMISAM) {
		this.toMigrateVSAMISAM = toMigrateVSAMISAM;
	}

	public boolean isToMigrateVSAMISAM() {
		return toMigrateVSAMISAM;
	}

	public void setToGenVSAMISAMDb(boolean toGenVSAMISAMDb) {
		this.toGenVSAMISAMDb = toGenVSAMISAMDb;
	}

	public boolean isToGenVSAMISAMDb() {
		return toGenVSAMISAMDb;
	}

	public void setAllSymbols(boolean allSymbols) {
		this.allSymbols = allSymbols;
	}

	public boolean isAllSymbols() {
		return allSymbols;
	}

	public void setInlineStatement(int inlineStatement) {
		this.inlineStatement = inlineStatement;
	}

	public int getInlineStatement() {
		return inlineStatement;
	}

	public void setTabLength(int tabLength) {
		this.tabLength = tabLength;
	}

	public int getTabLength() {
		return tabLength;
	}
	public String getTabSpaces() {
		return tabSpaces;
	}

	public void setTabSpaces(String tabSpaces) {
		this.tabSpaces = tabSpaces;
	}

	public void setGenerateBeanInfo(boolean generateBeanInfo) {
		this.generateBeanInfo = generateBeanInfo;
	}

	public boolean isGenerateBeanInfo() {
		return generateBeanInfo;
	}

	public void setOutputDir(String outputDir) {
		this.outputDir = outputDir;
	}

	public String getOutputDir() {
		return outputDir;
	}

	public boolean isUsePointers() {
		return false;
	}

	public void setExceptionPrintStackTraceOn(boolean exception_PrintStackTrace_On) {
		this.exception_PrintStackTrace_On = exception_PrintStackTrace_On;
	}

	public boolean isExceptionPrintStackTraceOn() {
		return exception_PrintStackTrace_On;
	}

	public void setConfigFile(String configFile) {
		this.configFile = configFile;
		loadDefaults();
	}

	public String getConfigFile() {
		return configFile;
	}

	public void setSqlDatabaseType(int sqlDatabaseType) {
		this.sqlDatabaseType = sqlDatabaseType;
	}

	public int getSqlDatabaseType() {
		return sqlDatabaseType;
	}

}
 public class RESContext {

	//Run related
	private String sourceFileName;
	private CobolParser parser=null;
	private RESCharStream charStream=null;
        private CobolFillTable cobolFillTable = null;
        private CobolRecode cobolRecode = null;
        private Cobol2Java cobol2Java = null;
	private Reader srcIn=null;
	private boolean sqlTranslated=false;
	private StringBuffer optionsVerbose=new StringBuffer();
	private boolean processVerbose=false;
	private boolean processPreprocessOnly=false;
	private boolean processParseOnly=false;
	private boolean traceOn=false;
	private int traceLevel=0;
	
	private String currencySign=null;
	private boolean decimalPointIsComma = false;
	
	public void setParser(CobolParser parser) {
		this.parser = parser;
	}
	public CobolParser getParser() {
		return parser;
	}
	public void setCharStream(RESCharStream charStream) {
		this.charStream = charStream;
	}
	public RESCharStream getCharStream() {
		return charStream;
	}
	public void setSourceFileName(String sourceFileName) {
		this.sourceFileName = sourceFileName;
	}
	public String getSourceFileName() {
		return sourceFileName;
	}
	public Reader getSourceFile() {
		return srcIn;
	}
	public void setSourceFile(Reader srcIn) {
		this.srcIn=srcIn;
	}
	public void setSqlTranslated(boolean sqlTranslated) {
		this.sqlTranslated = sqlTranslated;
	}
	public boolean isSqlTranslated() {
		return sqlTranslated;
	}
	public void setOptionsVerbose(StringBuffer optionsVerbose) {
		this.optionsVerbose = optionsVerbose;
	}
	public StringBuffer getOptionsVerbose() {
		return optionsVerbose;
	}
	public void setProcessVerbose(boolean processVerbose) {
		this.processVerbose = processVerbose;
	}
	public boolean isProcessVerbose() {
		return processVerbose;
	}
	public void setProcessPreprocessOnly(boolean processPreprocessOnly) {
		this.processPreprocessOnly = processPreprocessOnly;
	}
	public boolean isProcessPreprocessOnly() {
		return processPreprocessOnly;
	}
	public void setProcessParseOnly(boolean processParseOnly) {
		this.processParseOnly = processParseOnly;
	}
	public boolean isProcessParseOnly() {
		return processParseOnly;
	}
	public void setTraceOn(boolean traceOn) {
		this.traceOn = traceOn;
	}
	public boolean isTraceOn() {
		return traceOn;
	}
	public void setTraceLevel(int traceLevel) {
		this.traceLevel = traceLevel;
	}
	public int getTraceLevel() {
		return traceLevel;
	}
	public void setDecimalPointIsComma(boolean decimalPointIsComma) {
		this.decimalPointIsComma = decimalPointIsComma;
	}
	public boolean isDecimalPointIsComma() {
		return decimalPointIsComma;
	}
	public void setCurrencySign(String currencySign) {
		this.currencySign = currencySign;
	}
	public String getCurrencySign() {
		return currencySign;
	}

    public Cobol2Java getCobol2Java() {
        return cobol2Java;
    }

    public void setCobol2Java(Cobol2Java cobol2Java) {
        this.cobol2Java = cobol2Java;
    }

    public CobolFillTable getCobolFillTable() {
        return cobolFillTable;
    }

    public void setCobolFillTable(CobolFillTable cobolFillTable) {
        this.cobolFillTable = cobolFillTable;
    }

    public CobolRecode getCobolRecode() {
        return cobolRecode;
    }

    public void setCobolRecode(CobolRecode cobolRecode) {
        this.cobolRecode = cobolRecode;
    }
}
 @SuppressWarnings("unused")
public class Cobol2Java extends DepthFirstVisitor {

    private static Cobol2Java thiz = null;

    private Cobol2Java() {
    }
    private boolean doQualified = false;
    private boolean doLiteral = false;
    private boolean doingAcceptOption = false;
    private boolean doingSingleParagraph = false;
    private boolean doingNestedProgram = false;
    private Stack<String> condition = new Stack<String>();
    public int expressionType = 0;
    public String expressionString;
    public boolean isAll = false;
    public ExpressionString literal = new ExpressionString();
    public String lastTokenString = null;
    private Stack<String> qualified = new Stack<String>();
    private Stack<SymbolProperties> idProps = null;
    private Stack<String> optionStack = null;
    private SymbolProperties props = null;
    private SymbolProperties paragraphProps = null;
    private SymbolProperties sectionProps = null;
    private SymbolProperties procedureProps = null;
    private SymbolProperties procedureThruProps = null;
    private ArrayList<ExpressionString> idOrLiteralList;
    private Stack<StringBuilder> aLine = new Stack<StringBuilder>();
    private Stack<StringBuilder> bLine = new Stack<StringBuilder>();
    private Stack<StringBuilder> cLine = new Stack<StringBuilder>();
    private int callParmIdx = 0;
    private String paragraphName = null;
    private String sectionName = null;

    @SuppressWarnings("serial")
    public class ExpressionStack extends Stack<ExpressionString> {

        @Override
        public boolean empty() {
            return super.empty();
        }

        @Override
        public synchronized ExpressionString peek() {
            return super.peek();
        }

        public synchronized String peek3() {
            return super.peek().toString();
        }

        @Override
        public synchronized ExpressionString pop() {
            return super.pop();
        }

        public synchronized String pop3() {
            return super.pop().toString();
        }

        public ExpressionString push(String item) {
            return super.push(new ExpressionString(item, expressionType));
        }

        @Override
        public ExpressionString push(ExpressionString item) {
            return super.push(item);
        }

        public ExpressionString push(SymbolProperties item) {
            return super.push(new ExpressionString(item));
        }

        public boolean isAll() {
            return super.peek().isAll;
        }

        public void setAll(boolean b) {
            super.peek().isAll = b;
        }

        public int getType() {
            return super.peek().type;
        }

        public void setType(int b) {
            super.peek().type = b;
        }
    }
    public ExpressionStack expression = new ExpressionStack();

    @Override
    public void visit(CompilationUnit n) {
        super.visit(n);
    }

    @Override
    public void visit(NestedProgramUnit n) {
        doingNestedProgram = true;
        n.nestedIdentificationDivision.accept(this);
        n.nodeOptional1.accept(this);
        n.nodeOptional.accept(this);
        n.nodeOptional2.accept(this);
        n.nodeListOptional.accept(this);
        ClassFile.endProgramScope();
        dumper.printCobolComments(n.endProgramStatement.line);
        SymbolTable.getScope().endProgram();
        doingNestedProgram = false;
    }

    @Override
    public void visit(ProgramUnit n) {
        SymbolTable.getScope().setCloneOnLookup(true);
        n.identificationDivision.accept(this);
        n.nodeOptional1.accept(this);
        n.nodeOptional.accept(this);
        n.nodeOptional2.accept(this);
        dumper.printCobolComments(9999999);
        if (!SymbolTable.getScope().isCurrentProgramTopLevel()) {
            ClassFile.endProgramScope();
            SymbolTable.getScope().endProgram();
        }
        SymbolTable.getScope().setCloneOnLookup(false);
    }
    private boolean isDeclarative = false;

    @Override
    public void visit(Declaratives n) {
        isDeclarative = true;
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeSequence nodeseq = (NodeSequence) e.nextElement();
            ((SectionHeader) nodeseq.elementAt(0)).sectionName.accept(this);
            nodeseq.elementAt(2).accept(this);
            ClassFile.println("Section " + sectionProps.getJavaName1() + "=new Section(this,true) {");
            ClassFile.println("\tpublic CobolMethod run() {");
            ClassFile.tab();
            ClassFile.println("return super.run();");
            ClassFile.backTab();
            ClassFile.println("}};");

            nodeseq.elementAt(4).accept(this);
        }
        isDeclarative = false;
    }

    class UseCondition {

        boolean isError = false;
        String openCondition = null;

        public UseCondition(boolean e, String o, SymbolProperties sec) {
            isError = e;
            openCondition = o;
            section = sec;
        }
        SymbolProperties section = null;
    }
    private UseCondition useCondition = null;
    private ArrayList<UseCondition> useConditions = null;

    @Override
    public void visit(UseStatement n) {
        if (useConditions == null) {
            useConditions = new ArrayList<UseCondition>();
        }
        if (sectionProps == null) {
            return;
        }
        if (n.nodeChoice.which == 1) {
            NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
            NodeChoice nodech = (NodeChoice) nodeseq.elementAt(6);
            switch (nodech.which) {
                case 0:
                    NodeList filelist = (NodeList) nodech.choice;
                    for (Enumeration<Node> e = filelist.elements(); e.hasMoreElements();) {
                        e.nextElement().accept(this);
                        if (props == null) {
                            continue;
                        }
                        useConditions.add(new UseCondition(true, props.getDataName(), sectionProps));
                    }
                    break;
                case 1:
                case 2:
                case 3:
                case 4:
                    useConditions.add(new UseCondition(true, String.valueOf(nodech.which), sectionProps));
            }
        }
    }

    @Override
    public void visit(CurrencySignClause n) {
        n.literal.accept(this);
        context.setCurrencySign(formatLiteral(literal).toString());
    }

    @Override
    public void visit(DecimalPointClause n) {
        context.setDecimalPointIsComma(true);
    }
    private ArrayList<Node> delayedStatements = null;

    @Override
    public void visit(DataDescriptionEntry n) {

        if (n.nodeChoice.which == 5) {
            NodeChoice nodech = (NodeChoice) ((NodeSequence) n.nodeChoice.choice).elementAt(2);
            if (nodech.which == 3) {
                //DECLARE CURSOR
                if (delayedStatements == null) {
                    delayedStatements = new ArrayList<Node>();
                }
                delayedStatements.add(n);
            }
        }
        //super.visit(n);
    }
    private String returnLine = null;

    @Override
    public void visit(ProcedureDivision n) {

        if (SymbolTable.getScope().getCurrentProgram() == null) {
            return;
        }
        aLine.push(new StringBuilder());
        returnLine = null;
        isLastGotoStatement = false;
        ClassFile.doProgramScope(SymbolTable.getScope().getCurrentProgram(), false);
        ClassFile.tab();

        //Create Symbols and Accessors.
        SymbolTable.convert2Java();

        String className = (String) SymbolTable.getScope().getCurrentProgram().getJavaName2();
        if (SymbolTable.getScope().isCurrentProgramTopLevel()) {
            ClassFile.println("public static void main(String[] args) {");
            ClassFile.tab();
            ClassFile.println("__processCmdLineArgs(args);");
            ClassFile.println(className + " instance_ = new " + className + "();");
            ClassFile.println("instance_.execute(null); ");
            ClassFile.println("System.exit(instance_.__getReturnCode());");
            ClassFile.backTab();
            ClassFile.endMethodScope();
        }

        ClassFile.println("public void execute(ProgramEnv __env) {");
        ClassFile.tab();
        ClassFile.println("initialize(this); ");
        if (n.nodeOptional.present()) {
            NodeList nodelist = ((UsingArgs) ((NodeSequence) n.nodeOptional.node).elementAt(1)).nodeList;
            processUsingArgs1(nodelist);
        }
        if (delayedStatements != null) {
            for (Node nd : delayedStatements) {
                nd.accept(execSql2Java);
            }
        }
        if (n.procedureBody.paragraphs.nodeListOptional.present()) {
            n.procedureBody.paragraphs.nodeListOptional.accept(this);
        }
        if (!isLastGotoStatement) {
            ClassFile.println("doCobolGotoStart();");
        }
        if (n.nodeOptional.present()) {
            NodeList nodelist = ((UsingArgs) ((NodeSequence) n.nodeOptional.node).elementAt(1)).nodeList;
            processUsingArgs2(nodelist);
        }

        ClassFile.backTab();
        ClassFile.endMethodScope();

        aLine.pop();
        if (n.nodeOptional1.present()) {
            dumper.startAtNextToken();
            dumper.visit(n.nodeOptional1);
            n.nodeOptional1.accept(this);
        }
        if (n.procedureBody.paragraphs.nodeListOptional1.present()) {
            n.procedureBody.paragraphs.nodeListOptional1.accept(this);
        }
        if (n.procedureBody.nodeListOptional.present()) {
            n.procedureBody.nodeListOptional.accept(this);
        }
        doTail();

    }

    private void processUsingArgs2(NodeList nodelist) {
        aLine.peek().setLength(0);
        bLine.push(new StringBuilder());
        for (Enumeration<Node> e = nodelist.elements(); e.hasMoreElements();) {
            e.nextElement().accept(this);
            if (aLine.peek().length() > 0) {
                aLine.peek().append(',');
            }
            if (props != null) {
                // if (props.getIsFormat()) {
                //   line = NameUtil.getFormatName2(props, false).replace("%0", NameUtil.getJavaName(props, false));
                //} else {
                line = new ExpressionString(props).toString();
                //}
                aLine.peek().append(line);
            }
        }
        aLine.peek().append(bLine.peek());
        ClassFile.println(aLine.peek().insert(0, "doCobolReturn(").append(");").toString());
        returnLine = aLine.peek().toString();
        bLine.pop();
    }

    private void processUsingArgs1(NodeList nodelist) {
        ClassFile.println("__initializeCall(__env," + String.valueOf(nodelist.size())
                + ");");
        int i = 0;
        for (Enumeration<Node> e = nodelist.elements(); e.hasMoreElements();) {
            e.nextElement().accept(this);
            if (props != null) {
                if (props.isAChildHasDependingOn() || (props.isOccurs() && props.getDependingOnOccurs() != null)) {
                    aLine.peek().append(ClassFile.current.getTabs()).append(NameUtil.getJavaName(props, true).replace("%0",
                            ("__get" + SymbolConstants.getSQL(props.getIdentifierType()) + "Arg("
                            + String.valueOf(i++) + ((props.getIdentifierType() >= Constants.STRING)
                            ? ("," + String.valueOf(props.getLength())) : "") + ")")) + ';');
                } else {
                    ClassFile.println(NameUtil.getJavaName(props, true).replace("%0",
                            ("__get" + SymbolConstants.getSQL(props.getIdentifierType()) + "Arg("
                            + String.valueOf(i++) + ((props.getIdentifierType() >= Constants.STRING)
                            ? ("," + String.valueOf(props.getLength())) : "") + ")")) + ';');
                }
            }
        }
        ClassFile.println(aLine.peek().toString());
    }

    @Override
    public void visit(ExitProgramStatement n) {
        isLastExitStatement = true;
        ClassFile.println("return null;");
        super.visit(n);
    }

    @Override
    public void visit(StopStatement n) {
        //super.visit(n);
        ClassFile.println("System.exit(super.__getReturnCode());");
    }

    @Override
    public void visit(MoveStatement n) {

        expressionType = 0;
        switch (n.nodeChoice.which) {
            case 0:
                NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
                if (nodeseq.size() != 3) {
                    return;
                }
                NodeChoice choice2 = (NodeChoice) nodeseq.elementAt(0);
                ;
                choice2.accept(this);
                ExpressionString fromLit = null;
                SymbolProperties fromProps = null;
                if (choice2.which == 0) {
                    fromProps = props;
                    expressionType = props.getIdentifierType();
                } else {
                    fromLit = formatLiteral(literal);
                }

                int saveType = expressionType;
                if (nodeseq.elementAt(2) instanceof NodeList) {
                    for (Enumeration<Node> e = ((NodeList) nodeseq.elementAt(2)).elements();
                            e.hasMoreElements();) {
                        Node node = e.nextElement();
                        node.accept(this);
                        expressionType = saveType;
                        if (fromProps != null) {
                            doMove(fromProps, props);
                        } else {
                            doMove(fromLit, props);
                        }
                    }
                }
                break;
            case 1:
                nodeseq = (NodeSequence) n.nodeChoice.choice;
                nodeseq.elementAt(1).accept(this);
                fromProps = props;
                if (nodeseq.elementAt(3) instanceof NodeList) {
                    for (Enumeration<Node> e = ((NodeList) nodeseq.elementAt(3)).elements();
                            e.hasMoreElements();) {
                        Node node = e.nextElement();
                        node.accept(this);
                        doCorrespondingMove(fromProps, props, true);
                    }
                }
        }
    }

    private void doMove(ExpressionString from, SymbolProperties to) {

        boolean isAllLiteral = from.isAll;
        expression.push(from);
        ClassFile.println(TranslationTable.getInstance().getAssignString(to, null, isAllLiteral, true, true));
        expression.clear();
        initExpressionType();
        return;

    }

    private void doMove(SymbolProperties propsFrom, SymbolProperties to) {

        if (propsFrom.getType() == SymbolConstants.DUMMY) {
            propsFrom.setIsFormat(false);
        }
        ClassFile.println(TranslationTable.getInstance().getAssignString(to, propsFrom, false, true, true));
        expression.clear();
        initExpressionType();
        return;

    }

    private boolean doCorrespondingMove(SymbolProperties from, SymbolProperties to, boolean first) {
        if (first) {
            if (!isCorrespondingValid2(from, to)) {
                return false;
            }
        } else if (!isCorrespondingValid(from, to)) {
            return false;
        }
        if (from.getPictureString() != null || to.getPictureString() != null) {
            doMove(from, to);
            return true;
        } else {
            if (from.getChildren() != null && to.getChildren() != null) {
                for (int i = 0; i < from.getChildren().size(); ++i) {
                    for (int j = 0; j < to.getChildren().size(); ++j) {
                        from.getChildren().get(i).setIndexesWorkSpace(from.getIndexesWorkSpace());
                        to.getChildren().get(j).setIndexesWorkSpace(to.getIndexesWorkSpace());
                        if (doCorrespondingMove(from.getChildren().get(i), to.getChildren().get(j), false)) {
                            break;
                        }
                    }
                }
            }
            return false;
        }
    }

    public boolean isCorrespondingValid(SymbolProperties corrF, SymbolProperties corrT) {
        if (!corrF.getDataName().equalsIgnoreCase(corrT.getDataName())) {
            return false;
        }
        if (corrF == null || corrF.isOccurs() || corrF.getIsFiller() || corrF.getJavaType() == null
                || corrF.getIdentifierType() > Constants.GROUP
                || corrF.getRedefines() != null || corrF.hasRenames()) {
            return false;
        }
        if (corrT == null || corrT.isOccurs() || corrT.getIsFiller() || corrT.getJavaType() == null
                || corrT.getIdentifierType() > Constants.GROUP
                || corrT.getRedefines() != null || corrT.hasRenames()) {
            return false;
        }
        return true;
    }

    public boolean isCorrespondingValid2(SymbolProperties corrF, SymbolProperties corrT) {
        if (corrF == null || corrF.getLevelNumber() == 66
                || corrF.getLevelNumber() == 77 || corrF.getLevelNumber() == 88
                || corrF.getJavaType() == null || corrF.getIdentifierType() > Constants.GROUP) {
            return false;
        }
        if (corrT == null || corrT.getLevelNumber() == 66
                || corrT.getLevelNumber() == 77 || corrT.getLevelNumber() == 88
                || corrT.getJavaType() == null || corrT.getIdentifierType() > Constants.GROUP) {
            return false;
        }
        return true;
    }
    private final Pattern HEX_COBOL_PATTERN = Pattern.compile("[xX]\\\'[0-9a-fA-F]+\\\'|[xX]\\\"[0-9a-fA-F]+\\\"");
    private final Pattern HEX_PATTERN = Pattern.compile("0[xX][0-9a-fA-F]+|0[xX][0-9a-fA-F]+");
    private final Pattern INT_PATTERN = Pattern.compile("(\\+|\\-)?(\\d)+(\\,(\\d)+)*");
    private final Pattern DEC_PATTERN = Pattern.compile("(\\+|\\-)?(\\d)*(\\.[\\d]+)");
    private String line = "";

    public ExpressionString formatLiteral(String lit) {
        literal = new ExpressionString(lit);
        return formatLiteral(literal);
    }

    public ExpressionString formatLiteral(ExpressionString litP) {

        ExpressionString litC = new ExpressionString(litP);
        int j = 0;
        boolean isFunction = false;
        String lit = litC.raw = litC.toString();

        if (lit.equals("\"\\\"\""))//tell me why this?
        {
            expressionType = Constants.STRING;
        } else if ((lit.indexOf('\"') == 0 && (j = lit.lastIndexOf('\"')) >= 0)
                || lit.indexOf('\'') == 0
                && (j = lit.lastIndexOf('\'')) >= 0) {
            lit = '\"' + lit.substring(1, j).replace("\"\"", "\"").
                    replace("\\", "\\\\").
                    replace("\"", "\\\"").replace("\'", "\\\"") + '\"';
            expressionType = Constants.STRING;
        } else if (HEX_COBOL_PATTERN.matcher(lit).matches()) {
            lit = "0" + lit.replace("\'", "").replace("\"", "").replace('X', 'x');
            expressionType = Constants.INTEGER;
        } else if (HEX_PATTERN.matcher(lit).matches()) {
            expressionType = Constants.INTEGER;

        } else if (INT_PATTERN.matcher(lit).matches()) {
            lit = stripLeadingZeros(lit);
            expressionType = Constants.INTEGER;
            if (Long.parseLong(lit) > Integer.MAX_VALUE || Long.parseLong(lit) < Integer.MIN_VALUE) {
                lit += "L";//tell me why this?
            }
        } else if (DEC_PATTERN.matcher(lit).matches()) {
            lit = stripLeadingZeros(lit);
            expressionType = Constants.DOUBLE;
        } else if (lit.equalsIgnoreCase("ZERO") || lit.equalsIgnoreCase("ZEROS") || lit.equalsIgnoreCase("ZEROES")) {
            lit = litC.raw = "0";
            expressionType = Constants.INTEGER;
        } else if (lit.equalsIgnoreCase("SPACE") || lit.equalsIgnoreCase("SPACES")) {
            lit = "\" \"";
            litC.raw = null;
            expressionType = Constants.STRING;
        } else if (lit.equalsIgnoreCase("HIGH-VALUE") || lit.equalsIgnoreCase("HIGH-VALUES")) {
             litC.setString("__function__" + String.valueOf(50) + "__()",expressionType = Constants.CHAR);
            litC.raw = null;
            return formatFunction(litC);
        } else if (lit.equalsIgnoreCase("LOW-VALUE") || lit.equalsIgnoreCase("LOW-VALUES")) {
             litC.setString("__function__" + String.valueOf(51) + "__()",expressionType = Constants.CHAR);
            litC.raw = null;
            return formatFunction(litC);
        } else if (lit.equalsIgnoreCase("QUOTE") || lit.equalsIgnoreCase("QUOTES")) {
            lit = "\"\\\"\"";
            litC.raw = null;
            expressionType = Constants.STRING;
        } else if (litC.literal.indexOf("__function__") == 0) {
            return formatFunction(litC);
        } else {
            expressionType = litC.type;
            return litC;
        }
        litC.type = expressionType;
        litC.literal = new StringBuilder(lit);
        if (RESConfig.getInstance().isEbcdicMachine() && expressionType == Constants.STRING && !isFunction) {
            litC.literal.insert(0, "__normalizeLiteral(").append(')');
        }
        return litC;
    }

    private ExpressionString formatFunction(ExpressionString litC) throws NumberFormatException {
        int idx = Integer.parseInt(litC.literal.substring(12, litC.literal.indexOf("__", 12)));
        litC.literal = litC.literal.replace(0, litC.literal.indexOf("__", 12) + 2, SymbolConstants.getFunction(idx)).insert(0, "__function().");
        litC.raw = null;
        expressionType = Math.max(expressionType, Math.abs(SymbolConstants.getFunctionArgTypes(idx)[0]));
        litC.type = expressionType;
        return litC;
    }

    //Input is a valid number literal
    private String stripLeadingZeros(String lit) {

        return RunTimeUtil.getInstance().stripLeadingZeros(lit);

    }

    @Override
    public void visit(DisplayStatement n) {
        line = "";
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            Node node = e.nextElement();
            NodeSequence nodeseq = (NodeSequence) node;
            NodeChoice nodechoice = (NodeChoice) nodeseq.elementAt(0);
            nodechoice.accept(this);
            switch (nodechoice.which) {
                case 0:
                    if (props.getIdentifierType() == Constants.STRING) {
                        line += "getString(" + new ExpressionString(props) + ',' + String.valueOf(props.getLength()) + ")";
                    } else if (props.getIdentifierType() == Constants.GROUP) {
                        line += "getString(" + new ExpressionString(props) + ',' + String.valueOf(props.getLength()) + ")";
                    } else if (props.getIsFormat()) {
                        line += NameUtil.getFormatName2(props, false).replace("%0",
                                new ExpressionString(props).toString());
                    } else if (props.getPictureString() == null && props.getLevelNumber() == 1) {
                        String temp = new ExpressionString(props).toString();
                        line += temp.substring(0, temp.lastIndexOf('.') + 1) + props.getJavaName1() + ".toString()";
                    } else {
                        line += new ExpressionString(props).toString();
                    }
                    break;
                case 1:
                    line += formatLiteral(literal);
                    break;
                default:
            }
            if (e.hasMoreElements()) {
                line += "+";
            }
        }
        if (n.nodeOptional.present()) {
            n.nodeOptional.node.accept(this);
            if (!lastTokenString.equalsIgnoreCase("CONSOLE")) {
                ClassFile.println("__putEnvironment(" + formatLiteral(
                        new ExpressionString('\"' + RunTimeUtil.getInstance().stripQuotes(lastTokenString) + '\"')) + "," + line + ");");
                return;
            }
        }
        if (!n.nodeOptional1.present()) {
            ClassFile.println("Console.println(" + line + ");");
        } else {
            ClassFile.println("Console.print(" + line + ");");
        }
    }

    private void initExpressionType() {
        //TODO to isolate the inits may be removed later
        expressionType = Constants.BYTE;
    }

    private void initFunctionExpressionType() {
        //TODO to isolate the inits may be removed later
        expressionType = Constants.DOUBLE;
    }

    @Override
    public void visit(AddStatement n) {
        if (n.nodeOptional1.present() || n.nodeOptional.present()) {
            doArithTry();
        }
        n.addBody.accept(this);
        if (n.nodeOptional1.present() || n.nodeOptional.present()) {
            doCatchArith(n.nodeOptional, n.nodeOptional1);
        }
    }

    @Override
    public void visit(AddBody n) {
        initExpressionType();
        expression.clear();
        switch (n.nodeChoice.which) {
            case 1://Format 2
                NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
                nodeseq.elementAt(0).accept(this);
                for (Iterator<ExpressionString> e = idOrLiteralList.iterator(); e.hasNext();) {
                    ExpressionString o = e.next();
                    if (o.isIdSymbol) {

                        doIdOp(o.props, "+");
                    } else {
                        doLiteralOp(o.toString(), "+");
                    }
                }
                if (idOrLiteralList.size() < 1) {
                    break;
                }
                if (idOrLiteralList.size() > 1) {
                    //Create a temporary variable
                    expressionType = expression.peek().type;

                    String assign = TranslationTable.getInstance().getAssignString(null, null, false, true, true);
                    ClassFile.println(assign);
                    expression.push("temp" + String.valueOf(SymbolTable.tempVariablesMark - 1));
                } else {
                    //Here expression is on the stack
                }
                nodeseq.elementAt(2).accept(this);
                ExpressionString top = expression.pop();
                //int topType=expressionType;
                for (Iterator<ExpressionString> e = idOrLiteralList.iterator(); e.hasNext();) {
                    ExpressionString o = e.next();
                    expression.push(top);
                    expressionType = top.type;
                    doIdOp(o.Id(), "+");
                    if (o.isRounded) {
                        expression.peek().literal.insert(0, "__round(").append(",").append(
                                String.valueOf(o.Id().getJavaType().getMaxFractionLength())).append(")");
                        expression.peek().type=Constants.BIGDECIMAL;
                    }
                    if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                        expression.peek().setString(
                                doScaleLiteral(o.Id(), expression.peek().toString(), true),
                                Constants.BIGDECIMAL);
                    }
                    String assign = TranslationTable.getInstance().getAssignString(o.Id(), null, false, true, true);
                    ClassFile.println(assign);
                }
                break;
            case 0://Format 1
                nodeseq = (NodeSequence) n.nodeChoice.choice;
                nodeseq.elementAt(0).accept(this);
                nodeseq.elementAt(1).accept(this);
                for (Iterator<ExpressionString> e = idOrLiteralList.iterator(); e.hasNext();) {
                    ExpressionString o = e.next();
                    if (o.Id() != null) {
                        doIdOp(o.Id(), "+");
                    } else {
                        doLiteralOp(o.Lit(), "+");
                    }
                }
                if (idOrLiteralList.size() > 1) {
                    //Create a temporary variable
                    expressionType = expression.peek().type;
                    String assign = TranslationTable.getInstance().getAssignString(null, null, false, true, true);
                    ClassFile.println(assign);
                    expression.push("temp" + new Integer(SymbolTable.tempVariablesMark - 1).toString().trim());
                } else {
                    //Here expression is on the stack
                }
                nodeseq.elementAt(3).accept(this);
                top = expression.pop();
                //topType=expressionType;
                for (Iterator<ExpressionString> e = idOrLiteralList.iterator(); e.hasNext();) {
                    ExpressionString o = e.next();
                    if (o.IsRounded()) {
                        expression.push(
                                new ExpressionString("__round(" + top + "," + String.valueOf(o.Id().getJavaType().getMaxFractionLength()) + ")", top.type));
                        expression.peek().type=Constants.BIGDECIMAL;
                    } else {
                        expression.push(new ExpressionString(top));
                    }
                    expressionType = top.type;
                    if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                        expression.push(new ExpressionString(doScaleLiteral(o.Id(), expression.pop().toString(), true), Constants.BIGDECIMAL));
                    }/*
                    if(o.Id().getJavaType().getMaxScalingLength()!=0)
                    expression.push(doScaleLiteral(o.Id(),expression.pop().toString(),true));
                     * *
                     */
                    String assign = TranslationTable.getInstance().getAssignString(o.Id(), null, false, true, true);
                    ClassFile.println(assign);
                }
                break;
            case 2://Format 3
                nodeseq = (NodeSequence) n.nodeChoice.choice;
                nodeseq.elementAt(1).accept(this);
                SymbolProperties from = props;
                nodeseq.elementAt(3).accept(this);
                doCorrespondingOp(from, props, "+", false, true);
        }
        //super.visit(n);
    }

    @Override
    public void visit(MultiplyBody n) {
        initExpressionType();
        expression.clear();
        idOrLiteralList = new ArrayList<ExpressionString>();
        n.idOrLiteral.accept(this);
        switch (n.nodeChoice.which) {
            case 0://Format 1
                NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
                nodeseq.elementAt(0).accept(this);
                for (Iterator<ExpressionString> e = idOrLiteralList.iterator(); e.hasNext();) {
                    ExpressionString o = e.next();
                    if (o.Id() != null) {
                        doIdOp(o.Id(), "*");
                    } else {
                        doLiteralOp(o.Lit(), "*");
                    }
                }
                idOrLiteralList = new ArrayList<ExpressionString>();
                nodeseq.elementAt(2).accept(this);
                if (idOrLiteralList.size() > 1) {
                    expressionType = expression.peek().type;
                    String assign = TranslationTable.getInstance().getAssignString(null, null, false,true,true);
                    ClassFile.println(assign);
                    expression.push("temp" + new Integer(SymbolTable.tempVariablesMark - 1).toString().trim());
                } else {
                    //Here expression is on the stack
                }
                ExpressionString top = expression.pop();
                //int topType=expressionType;
                for (Iterator<ExpressionString> e = idOrLiteralList.iterator(); e.hasNext();) {
                    ExpressionString o = e.next();
                    if (o.IsRounded()) {
                        expression.push(new ExpressionString("__round(" + top + "," + String.valueOf(o.Id().getJavaType().getMaxFractionLength()) + ")", top.type));
                        expression.peek().type=Constants.BIGDECIMAL;
                    } else {
                        expression.push(top);
                    }
                    expressionType = top.type;
                    if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                        expression.push(new ExpressionString(doScaleLiteral(o.Id(), expression.pop().toString(), true), Constants.BIGDECIMAL));
                    }
                    String assign = TranslationTable.getInstance().getAssignString(o.Id(), null, false,true,true);
                    ClassFile.println(assign);
                }
                break;
            case 1:
                if (idOrLiteralList.size() != 1) {
                    break;
                }
                ExpressionString o = idOrLiteralList.get(0);
                if (o.Id() != null) {
                    doIdOp(o.Id(), "*");
                } else {
                    doLiteralOp(o.Lit(), "*");
                }
                idOrLiteralList = new ArrayList<ExpressionString>();
                n.nodeChoice.choice.accept(this);
                top = expression.pop();
                //topType=expressionType;
                for (Iterator<ExpressionString> e = idOrLiteralList.iterator(); e.hasNext();) {
                    o = e.next();
                    expression.push(top);
                    expressionType = top.type;
                    doIdOp(o.Id(), "*");
                    if (o.IsRounded()) {
                        expression.push(new ExpressionString("__round(" + expression.peek() + "," + String.valueOf(o.Id().getJavaType().getMaxFractionLength()) + ")", expression.pop().type));
                        expression.peek().type=Constants.BIGDECIMAL;
                    }
                    if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                        expression.push(new ExpressionString(doScaleLiteral(o.Id(), expression.pop().toString(), true), Constants.BIGDECIMAL));
                    }
                    String assign = TranslationTable.getInstance().getAssignString(o.Id(), null, false,true,true);
                    ClassFile.println(assign);
                }
                break;
        }
    }

    @Override
    public void visit(SubtractStatement n) {

        initExpressionType();
        if (n.nodeOptional1.present() || n.nodeOptional.present()) {
            doArithTry();
        }

        expression.clear();
        idOrLiteralList = new ArrayList<ExpressionString>();
        switch (n.nodeChoice.which) {
            case 0:
                NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
                nodeseq.elementAt(0).accept(this);
                for (Iterator<ExpressionString> e = idOrLiteralList.iterator(); e.hasNext();) {
                    ExpressionString o = e.next();
                    if (o.Id() != null) {
                        doIdOp(o.Id(), "+");
                    } else {
                        doLiteralOp(o.Lit(), "+");
                    }
                }
                if (idOrLiteralList.size() > 1) {
                    //Create a temporary variable
                    expressionType = expression.peek().type;
                    String assign = TranslationTable.getInstance().getAssignString(null, null, false,true,true);
                    ClassFile.println(assign);
                    expression.push("temp" + new Integer(SymbolTable.tempVariablesMark - 1).toString().trim());
                } else {
                    //Here expression is on the stack
                }
                NodeChoice nodech = (NodeChoice) nodeseq.elementAt(2);
                switch (nodech.which) {
                    case 0:
                        idOrLiteralList = new ArrayList<ExpressionString>();
                        NodeSequence nodeseq2 = (NodeSequence) nodech.choice;
                        nodeseq2.elementAt(0).accept(this);
                        ExpressionString top = expression.pop();
                        //int topType=expressionType;
                        if (idOrLiteralList.get(0).Id() != null) {
                            TranslationTable.getInstance().doOp(idOrLiteralList.get(0).Id(), "-");
                            TranslationTable.getInstance().doOp(top, "-");
                        } else if (idOrLiteralList.get(0).Lit() != null) {
                            TranslationTable.getInstance().doOp(idOrLiteralList.get(0).Lit(), "-");
                            TranslationTable.getInstance().doOp(top, "-");
                        }
                        idOrLiteralList = new ArrayList<ExpressionString>();
                        nodeseq2.elementAt(2).accept(this);
                        top = expression.pop();
                        //topType=expressionType;
                        for (Iterator<ExpressionString> e = idOrLiteralList.iterator(); e.hasNext();) {
                            ExpressionString o = e.next();
                            if (o.IsRounded()) {
                                expression.push(new ExpressionString("__round(" + top + "," + String.valueOf(o.Id().getJavaType().getMaxFractionLength()) + ")", top.type));
                                expression.peek().type=Constants.BIGDECIMAL;
                            } else {
                                expression.push(top);
                            }
                            //expressionType=topType;
                            if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                                expression.push(new ExpressionString(doScaleLiteral(o.Id(), expression.pop().toString(), true), Constants.BIGDECIMAL));
                            }
                            String assign = TranslationTable.getInstance().getAssignString(o.Id(), null, false,true,true);
                            ClassFile.println(assign);
                        }
                        break;
                    case 1:
                        idOrLiteralList = new ArrayList<ExpressionString>();
                        nodech.choice.accept(this);
                        top = expression.pop();
                        //topType=expressionType;
                        for (Iterator<ExpressionString> e = idOrLiteralList.iterator(); e.hasNext();) {
                            ExpressionString o = e.next();
                            /*
                            if(o.isRounded()) {
                            expression.push("__round("+top+"," +String.valueOf(o.Id().getJavaType().getMaxFractionLength())+")");
                            }
                            else expression.push(top);
                             */
                            expression.push(NameUtil.getJavaName(o.Id(), false));
                            expressionType = o.Id().getIdentifierType();
                            //doIdOp(o.Id(),"-");
                            TranslationTable.getInstance().doOp(top, "-");
                            if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                                expression.push(new ExpressionString(doScaleLiteral(o.Id(), expression.pop().toString(), true),Constants.BIGDECIMAL));
                            }
                            String assign = TranslationTable.getInstance().getAssignString(o.Id(), null, false,true,true);
                            ClassFile.println(assign);
                        }
                        break;
                }
                break;
            case 1:
                nodeseq = (NodeSequence) n.nodeChoice.choice;
                nodeseq.elementAt(1).accept(this);
                SymbolProperties from = props;
                nodeseq.elementAt(3).accept(this);
                doCorrespondingOp(from, props, "-", true, true);
        }
        if (n.nodeOptional1.present() || n.nodeOptional.present()) {
            doCatchArith(n.nodeOptional, n.nodeOptional1);
        }
    }

    private void doArithTry() {
        ClassFile.println("try {");
        ClassFile.tab();
        ClassFile.println("__enableExceptions();");
    }

    private void doTry() {
        ClassFile.println("try {");
        ClassFile.tab();
    }

    private void doCatchArith(Node n, NodeOptional n2) {
        ClassFile.println("__resetExceptions();");
        n2.accept(this);
        ClassFile.backTab();
        ClassFile.println("} catch(ArithmeticException ae) {");
        ClassFile.tab();
        ClassFile.println("__resetExceptions();");
        exceptionPrintStackTrace("ae");
        n.accept(this);
        ClassFile.backTab();
        ClassFile.println("}");
    }

    private void exceptionPrintStackTrace(String e) {
        if (RESConfig.getInstance().isExceptionPrintStackTraceOn()) {
            ClassFile.println("__printStackTrace(" + e + ");");
        }
    }

    @Override
    public void visit(MultiplyStatement n) {
        if (n.nodeOptional1.present() || n.nodeOptional.present()) {
            doArithTry();
        }
        n.multiplyBody.accept(this);
        if (n.nodeOptional1.present() || n.nodeOptional.present()) {
            doCatchArith(n.nodeOptional, n.nodeOptional1);
        }
    }

    @Override
    public void visit(DivideBody n) {

        initExpressionType();
        expression.clear();
        idOrLiteralList = new ArrayList<ExpressionString>();
        switch (n.nodeChoice.which) {
            case 0:
                NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
                if (!((NodeOptional) nodeseq.elementAt(3)).present()) {
                    nodeseq.elementAt(0).accept(this);
                    if (idOrLiteralList.get(0).Id() != null) {
                        doIdOp(idOrLiteralList.get(0).Id(), "/");
                    } else {
                        doLiteralOp(idOrLiteralList.get(0).Lit(), "/");
                    }
                    idOrLiteralList = new ArrayList<ExpressionString>();
                    nodeseq.elementAt(2).accept(this);
                    ExpressionString top = expression.pop();//from elementAt(0)
                    //int topType=expressionType;
                    expression.clear();
                    for (int i = 0; i < idOrLiteralList.size(); ++i) {
                        ExpressionString o = idOrLiteralList.get(i);
                        if (o.Id() != null) {
                            expression.push(top);
                            expressionType = top.type;
                            doIdOp(o.Id(), "/");
                            if (o.IsRounded()) {
                                expression.push(new ExpressionString("__round(" + expression.peek() + "," + String.valueOf(o.Id().getJavaType().getMaxFractionLength()) + ")", expression.pop().type));
                                expression.peek().type=Constants.BIGDECIMAL;
                            }
                            TranslationTable.getInstance().doOp(top, "/");
                            if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                                expression.push(new ExpressionString(doScaleLiteral(o.Id(), expression.pop().toString(), true), Constants.BIGDECIMAL));
                            }
                            String assign = TranslationTable.getInstance().getAssignString(o.Id(), null, false,true,true);

                            ClassFile.println(assign);
                        }
                    }
                } else {//Giving present
                    NodeSequence nodeseq2 = (NodeSequence) ((NodeOptional) nodeseq.elementAt(3)).node;
                    nodeseq.elementAt(0).accept(this);
                    if (idOrLiteralList.size() == 1) {
                        if (idOrLiteralList.get(0).Id() != null) {
                            doIdOp(idOrLiteralList.get(0).Id(), "/");
                        } else {
                            doLiteralOp(idOrLiteralList.get(0).Lit(), "/");
                        }
                    }
                    ExpressionString top2 = expression.peek();//These two for remainder calculation
                    //int type2=expressionType;
                    idOrLiteralList.clear();
                    nodeseq.elementAt(2).accept(this);
                    expression.clear();
                    if (idOrLiteralList.get(0).Id() != null) {
                        doIdOp(idOrLiteralList.get(0).Id(), "/");
                    } else {
                        doLiteralOp(idOrLiteralList.get(0).Lit(), "/");
                    }
                    ExpressionString top = expression.peek();//from elementAt(2)
                    //int topType=expressionType;
                    TranslationTable.getInstance().doOp(top2, "/");
                    idOrLiteralList.clear();
                    nodeseq2.elementAt(1).accept(this);
                    ExpressionString top3 = expression.pop();
                    //int type3=expressionType;
                    if (((NodeOptional) nodeseq2.elementAt(2)).present()) {//Also Remainder
                        ExpressionString o = idOrLiteralList.get(0);
                        if (o.Id() != null) {
                            if (o.IsRounded()) {
                                expression.push(new ExpressionString("__round(" + top3 + "," + String.valueOf(o.Id().getJavaType().getMaxFractionLength()) + ")", top3.type));
                                expression.peek().type=Constants.BIGDECIMAL;
                            } else {
                                expression.push(top3);
                            }
                            expressionType = top3.type;
                            if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                                expression.push(new ExpressionString(doScaleLiteral(o.Id(), expression.pop().toString(), true), Constants.BIGDECIMAL));
                            }
                            String assign = TranslationTable.getInstance().getAssignString(o.Id(), null, false,true,true);

                            ClassFile.println(assign);

                        }
                        if (idOrLiteralList.size() > 1) {
                            //TODO Syntax Error to be caught
                            return;
                        }
                        expression.clear();
                        expression.push(top);
                        expressionType = top.type;
                        TranslationTable.getInstance().doOp(top2, "%");
                        idOrLiteralList.clear();
                        nodeseq2.elementAt(2).accept(this);
                        if (idOrLiteralList.size() == 1) {
                            if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                                expression.push(new ExpressionString(doScaleLiteral(o.Id(), expression.pop().toString(), true),Constants.BIGDECIMAL));
                            }
                            String assign = TranslationTable.getInstance().getAssignString(idOrLiteralList.get(0).Id(),
                                    null, false,true,true);
                            ClassFile.println(assign);
                        }
                    } else {//Only Giving
                        for (int i = 0; i < idOrLiteralList.size(); ++i) {
                            ExpressionString o = idOrLiteralList.get(i);
                            if (o.Id() != null) {
                                if (o.IsRounded()) {
                                    expression.push(new ExpressionString("__round(" + top3 + "," + String.valueOf(o.Id().getJavaType().getMaxFractionLength()) + ")", top3.type));
                                    expression.peek().type=Constants.BIGDECIMAL;
                                } else {
                                    expression.push(top3);
                                }
                                expressionType = top3.type;
                                if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                                    expression.push(new ExpressionString(doScaleLiteral(o.Id(), expression.pop().toString(), true), Constants.BIGDECIMAL));
                                }
                                String assign = TranslationTable.getInstance().getAssignString(o.Id(),
                                        null, false,true,true);
                                ClassFile.println(assign);

                            }
                        }
                    }
                }
                break;
            case 1:
                nodeseq = (NodeSequence) n.nodeChoice.choice;
                nodeseq.elementAt(2).accept(this);
                if (idOrLiteralList.size() == 1) {
                    if (idOrLiteralList.get(0).Id() != null) {
                        doIdOp(idOrLiteralList.get(0).Id(), "/");
                    } else {
                        doLiteralOp(idOrLiteralList.get(0).Lit(), "/");
                    }
                }
                ExpressionString top2 = expression.peek();//These two for remainder calculation
                //int type2=expressionType;
                idOrLiteralList.clear();
                nodeseq.elementAt(0).accept(this);
                expression.clear();
                if (idOrLiteralList.size() == 1) {
                    if (idOrLiteralList.get(0).Id() != null) {
                        doIdOp(idOrLiteralList.get(0).Id(), "/");
                    } else {
                        doLiteralOp(idOrLiteralList.get(0).Lit(), "/");
                    }
                }
                ExpressionString top = expression.peek();//from elementAt(0)
                //int type1=expressionType;
                TranslationTable.getInstance().doOp(top2, "/");
                idOrLiteralList.clear();
                nodeseq.elementAt(4).accept(this);
                ExpressionString top3 = expression.pop();
                //int type3=expressionType;
                if (((NodeOptional) nodeseq.elementAt(5)).present()) {//Also Remainder
                    ExpressionString o = idOrLiteralList.get(0);
                    if (o.Id() != null) {
                        if (o.IsRounded()) {
                            expression.push(new ExpressionString("__round(" + top3 + "," + String.valueOf(o.Id().getJavaType().getMaxFractionLength()) + ")", top3.type));
                            expression.peek().type=Constants.BIGDECIMAL;
                        } else {
                            expression.push(top3);
                        }
                        expressionType = top3.type;
                        if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                            expression.push(new ExpressionString(doScaleLiteral(o.Id(), expression.pop().toString(), true), Constants.BIGDECIMAL));
                        }
                        String assign = TranslationTable.getInstance().getAssignString(o.Id(), null, false,true,true);
                        ClassFile.println(assign);

                    }
                    if (idOrLiteralList.size() > 1) {
                        return;
                    }
                    expression.clear();
                    expression.push(top);
                    TranslationTable.getInstance().doOp(top2, "%");
                    idOrLiteralList.clear();
                    nodeseq.elementAt(5).accept(this);
                    if (idOrLiteralList.size() == 1) {
                        if (idOrLiteralList.get(0).Id().getJavaType().getMaxScalingLength() != 0) {
                            expression.push(new ExpressionString(doScaleLiteral(idOrLiteralList.get(0).Id(), expression.pop().toString(), true), Constants.BIGDECIMAL));
                        }
                        String assign = TranslationTable.getInstance().getAssignString(idOrLiteralList.get(0).Id(), null, false,true,true);

                        ClassFile.println(assign);
                    }
                } else {//Only Giving
                    for (int i = 0; i < idOrLiteralList.size(); ++i) {
                        ExpressionString o = idOrLiteralList.get(i);
                        if (o.Id() != null) {
                            if (o.IsRounded()) {
                                expression.push("__round(" + top3 + "," + String.valueOf(o.Id().getJavaType().getMaxFractionLength()) + ")");
                                expression.peek().type=Constants.BIGDECIMAL;
                            } else {
                                expression.push(top3);
                            }
                            expressionType = top3.type;
                            if (o.Id().getJavaType().getMaxScalingLength() != 0) {
                                expression.push(new ExpressionString(doScaleLiteral(o.Id(), expression.pop().toString(), true), Constants.BIGDECIMAL));
                            }
                            String assign = TranslationTable.getInstance().getAssignString(o.Id(), null, false,true,true);
                            ClassFile.println(assign);

                        }
                    }
                }
                break;
        }
    }

    @Override
    public void visit(DivideStatement n) {
        if (n.nodeOptional1.present() || n.nodeOptional.present()) {
            doArithTry();
        }
        n.divideBody.accept(this);
        if (n.nodeOptional1.present() || n.nodeOptional.present()) {
            doCatchArith(n.nodeOptional, n.nodeOptional1);
        }
    }

    private boolean doCorrespondingOp(SymbolProperties from, SymbolProperties to, String op, boolean doReverseOp, boolean first) {
        if (first) {
            if (!isCorrespondingValid2(from, to)) {
                return false;
            }
        } else if (!isCorrespondingValid(from, to)) {
            return false;
        }
        if (from.getPictureString() != null && to.getPictureString() != null) {
            expression.clear();
            if (!doReverseOp) {
                doIdOp(from, op);
                doIdOp(to, op);
            } else {
                doIdOp(from, op);
                //int topType=expressionType;
                ExpressionString top = expression.pop();
                doIdOp(to, op);
                TranslationTable.getInstance().doOp(top, op);
            }
            if (to.getJavaType().getMaxScalingLength() != 0) {
                expression.push(new ExpressionString(doScaleLiteral(to, expression.pop().toString(), true), Constants.BIGDECIMAL));
            }
            String assign = TranslationTable.getInstance().getAssignString(to, null, false,true,true);
            ClassFile.println(assign);
            return true;
        }
        if (from.getChildren() != null && to.getChildren() != null) {
            for (int i = 0; i < from.getChildren().size(); ++i) {
                for (int j = 0; j < to.getChildren().size(); ++j) {
                    if (doCorrespondingOp(from.getChildren().get(i), to.getChildren().get(j), op, doReverseOp, false)) {
                        break;
                    }
                }
            }
        }
        return false;
    }
    /*
    private void doLiteralOp(ExpressionString lit,String op) {
    TranslationTable.getInstance().doLiteralOp(lit.toString(), op);
    }
     * *
     */

    private void doLiteralOp(String lit, String op) {
        TranslationTable.getInstance().doLiteralOp(lit, op);
    }

    private void doIdOp(SymbolProperties id, String op) {
        TranslationTable.getInstance().doIdOp(id, op);
    }

    @Override
    public void visit(ArithIdentifier n) {
        super.visit(n);
        if (idOrLiteralList != null) {
            idOrLiteralList.add(new ExpressionString(props, n.nodeOptional.present()));
        }

    }

    @Override
    public void visit(ArithIdentifierList n) {
        idOrLiteralList = new ArrayList<ExpressionString>();
        super.visit(n);
    }

    @Override
    public void visit(IdOrLiteral n) {
        super.visit(n);
        if (idOrLiteralList != null) {
            switch (n.nodeChoice.which) {
                case 0:
                    idOrLiteralList.add(new ExpressionString(props));
                    break;
                case 1:
                    idOrLiteralList.add(new ExpressionString(literal));
                    break;
            }
        }
    }

    @Override
    public void visit(IdOrLiteralList n) {
        idOrLiteralList = new ArrayList<ExpressionString>();
        super.visit(n);
    }

    @Override
    public void visit(ComputeStatement n) {
        if (n.nodeOptional1.present() || n.nodeOptional.present()) {
            doArithTry();
        }
        initExpressionType();
        Stack<ExpressionString> exprLHS = new Stack<ExpressionString>();
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeSequence nodeseq = (NodeSequence) e.nextElement();
            nodeseq.elementAt(0).accept(this);
            ExpressionString idr = new ExpressionString(props, ((NodeOptional) nodeseq.elementAt(1)).present());
            exprLHS.push(idr);
        }
        
        n.arithmeticExpression.accept(this);
        
        SymbolProperties props2 = null;
        for (Iterator<ExpressionString> e = exprLHS.iterator(); e.hasNext();) {
            ExpressionString idr = e.next();
            String assign = TranslationTable.getInstance().getAssignString(idr.Id(), props2, false, true, true);
            if (assign.length() > 0) {
                ClassFile.println(assign);
            }
            props2 = idr.Id();
        }
        if (n.nodeOptional1.present() || n.nodeOptional.present()) {
            doCatchArith(n.nodeOptional, n.nodeOptional1);
        }
    }
    public java.util.regex.Pattern numPattern = java.util.regex.Pattern.compile("[-+]?[0-9]*(\\.[0-9]+)?");
    private java.util.regex.Pattern ZERO_PATTERN = java.util.regex.Pattern.compile("[-+]?[0]*(\\.[0]+)?");

    @Override
    public void visit(ExitStatement n) {
        if (consolidationInProgress) {
            return;
        }
        isLastExitStatement = true;
        ClassFile.println("return doCobolExit();");
        //super.visit(n);
    }

    @Override
    public void visit(GotoStatement n) {
        super.visit(n);
        if (RESConfig.getInstance().getProcedureFormat() == (byte) 2)//TODO NATIVE JAVA  METHOD
        {
            return;
        }
        NodeOptional nodeopt = (NodeOptional) ((NodeSequence) n.nodeChoice.choice).elementAt(1);
        ((NodeSequence) n.nodeChoice.choice).elementAt(0).accept(this);
        if (nodeopt.present()) {
            NodeSequence nodeseq = (NodeSequence) nodeopt.node;
            nodeseq.elementAt(3).accept(this);
            if (props == null) {
                return;
            }
            ClassFile.println("switch(" + new ExpressionString(props).toString() + ") {");
            ClassFile.tab();
            ClassFile.print("case 1:");
            NodeListOptional nlo = (NodeListOptional) nodeseq.elementAt(0);
            printCobolGoto(procedureProps);
            int pc = 2;
            if (nlo.present()) {
                for (Enumeration<Node> e = nlo.elements(); e.hasMoreElements();) {
                    e.nextElement().accept(this);
                    ClassFile.print("case "
                            + String.valueOf(pc++)
                            + ":");
                    printCobolGoto(procedureProps);
                }
            }
            ClassFile.backTab();
            ClassFile.println("}");
        } else {
            printCobolGoto(procedureProps);
        }
    }

    private void printCobolGoto(SymbolProperties props) {
        //Integer paragraphMarkInteger=(Integer)props.getParagraphMark();
        //if(paragraphMarkInteger==null||paragraphMarkInteger.intValue()<=0) return;
        ClassFile.println("return " + props.getJavaName1() + ";");
    }

    @Override
    public void visit(ParagraphName n) {
        super.visit(n);
        paragraphProps = SymbolTable.getScope().lookup(lastTokenString, SymbolConstants.PARAGRAPH);
        if (paragraphProps == null) {
            sectionProps = SymbolTable.getScope().lookup(lastTokenString, SymbolConstants.SECTION);
            if (sectionProps == null) {
                reportError(n, "Undefined Procedure Name " + lastTokenString + "\n");
                return;
            }
            sectionName = lastTokenString;
            return;
        }
        paragraphName = lastTokenString;
    }

    @Override
    public void visit(SectionName n) {
        super.visit(n);
        sectionName = lastTokenString;
        sectionProps = SymbolTable.getScope().lookup(sectionName, SymbolConstants.SECTION);
    }

    @Override
    public void visit(ProcedureName n) {
        sectionName = paragraphName = null;
        procedureProps = paragraphProps = sectionProps = null;
        n.nodeChoice.choice.accept(this);
        if (paragraphName != null && sectionName != null) {
            paragraphProps = SymbolTable.getScope().lookup(paragraphName, sectionName);
            procedureProps = paragraphProps;
        } else if (sectionName != null) {
            procedureProps = sectionProps;
        } else if (paragraphName != null) {
            procedureProps = paragraphProps;
        }
        if (procedureProps == null) {
            reportError(n, "Unknown Paragraph " + paragraphName + ((sectionName != null) ? " IN " + sectionName : ""));
        }
    }

    @Override
    public void visit(ProcedureSection n) {

        n.sectionHeader.sectionName.accept(this);

        String declarative = "";
        if (isDeclarative) {
            declarative = ",true";
        }

        ClassFile.println("Section " + sectionProps.getJavaName1() + "=new Section(this" + declarative + ") {");
        ClassFile.println("public CobolMethod run() {");
        ClassFile.tab();
        n.paragraphs.nodeListOptional.accept(this);
        ClassFile.println("return super.run();");

        ClassFile.backTab();
        ClassFile.println("}};");
        n.paragraphs.nodeListOptional1.accept(this);

    }
    private boolean consolidationInProgress = false;
    private boolean isLastExitStatement = false;

    @Override
    public void visit(EntryStatement n) {

        n.literal.accept(this);
        paragraphProps = SymbolTable.getScope().lookup(
                paragraphName = RunTimeUtil.getInstance().stripQuotes(literal.toString(), true), SymbolConstants.PROGRAM);
        if (paragraphProps == null) {
            reportError(n, "Unknown Symbol :" + literal.toString());
            return;
        }

        ClassFile.println("public void " + paragraphProps.getJavaName1() + "Entry__(ProgramEnv __env) {");
        ClassFile.tab();
        ClassFile.println("initialize(this); ");
        if (n.nodeOptional.present()) {
            NodeList nodelist = ((UsingArgs) n.nodeOptional.node).nodeList;
            processUsingArgs1(nodelist);
        }
        ClassFile.println("doCobolGoto(" + paragraphProps.getJavaName1() + ");");
        if (n.nodeOptional.present()) {
            NodeList nodelist = ((UsingArgs) n.nodeOptional.node).nodeList;
            processUsingArgs2(nodelist);
        }
        ClassFile.backTab();
        ClassFile.endMethodScope();

        ClassFile.doProgramScope(paragraphProps, false);
        ClassFile.tab();
        ClassFile.println("public static void main(String[] args) {");
        ClassFile.tab();
        ClassFile.println("__processCmdLineArgs(args);");
        ClassFile.println("new " + SymbolTable.getScope().getFirstProgram().getJavaName2() + "()."
                + paragraphProps.getJavaName1() + "Entry__(null);");
        ClassFile.backTab();
        ClassFile.endMethodScope();

        ClassFile.println("public void execute(ProgramEnv __env) {");
        ClassFile.tab();
        ClassFile.println("new " + SymbolTable.getScope().getFirstProgram().getJavaName2() + "()."
                + paragraphProps.getJavaName1() + "Entry__(__env);");
        ClassFile.backTab();
        ClassFile.endMethodScope();
        ClassFile.backTab();
        ClassFile.println("");
        ClassFile.endProgramScope();

    }

    @Override
    @SuppressWarnings("CallToThreadDumpStack")
    public void visit(Paragraph n) {

        if ((paragraphProps = ((RESNode) n).props) == null) {
            n.nodeChoice.choice.accept(this);
        }
        //paragraphProps=SymbolTable.getScope().lookup(lastTokenString, SymbolTypes.PARAGRAPH);
        if (paragraphProps == null) {
            //paragraphProps=SymbolTable.getScope().lookup(lastTokenString, SymbolTypes.SECTION);
            if (paragraphProps == null) {
                try {
                    throw new Exception();
                } catch (Exception e) {
                    reportError(n, "Undefined Paragraph Name " + lastTokenString + "\n");
                    e.printStackTrace();
                    return;
                }
            }
        }

        if (paragraphProps.isAlteredParagraph()) {//Altered Go To
            ClassFile.println("CobolMethod " + paragraphProps.getJavaName1() + "Altered__=null;");
        }

        if (paragraphProps.isConsolidateParagraph() && !paragraphProps.isGotoTarget()) {
            return;
        }
        isLastExitStatement = false;
        String declarative = "";
        if (isDeclarative) {
            declarative = ",true";
        }
        if (paragraphProps.getParent() == null/*Entry*/ || paragraphProps.getParent().getType() == SymbolConstants.SECTION) {
            ClassFile.println("Paragraph " + paragraphProps.getJavaName1() + "=new Paragraph(this," + paragraphProps.getParent().getJavaName1()
                    + declarative + ") {");
        } else {
            ClassFile.println("Paragraph " + paragraphProps.getJavaName1() + "=new Paragraph(this" + declarative
                    + ") {");
        }
        ClassFile.println("public CobolMethod run() {");
        ClassFile.tab();
        if (paragraphProps.isAlteredParagraph()) {//Not Altered
            ClassFile.println("if(" + paragraphProps.getJavaName1() + "Altered__!=null)");
            ClassFile.println("\treturn " + paragraphProps.getJavaName1() + "Altered__;");
        }
        n.nodeChoice1.accept(this);
        if (!n.deadStatement && !isLastExitStatement) {
            ClassFile.println("return doCobolExit();");
        }
        ClassFile.backTab();
        ClassFile.println("}};");

    }

    @Override
    public void visit(AlterStatement n) {
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeSequence nodeseq = (NodeSequence) e.nextElement();
            nodeseq.elementAt(0).accept(this);
            SymbolProperties alt = procedureProps;
            nodeseq.elementAt(3).accept(this);
            ClassFile.println(alt.getJavaName1() + "Altered__=" + procedureProps.getJavaName1() + ";");
        }
    }

    @Override
    public void visit(Basis n) {
        boolean saveUMinus = doUMinus;
        int saveType = expressionType;
        n.nodeChoice.choice.accept(this);
        switch (n.nodeChoice.which) {
            case 0:
                if (doingRelationCondition) {
                    literal = new ExpressionString(props, props.getJavaType().getMaxScalingLength());
                } else {
                    literal = new ExpressionString(props);
                }
                if (doUMinus) {
                    if (props.getIdentifierType() < Constants.BIGDECIMAL) {
                        literal.literal.insert(0, '-');
                    } else {
                        literal.literal.append(".negate()");
                    }
                }
                //if(expressionType!=literal.type)
                //   expression.push(TranslationTable.getInstance().convertType(
                //		literal, expressionType=Math.max(literal.type, expressionType),
                //		literal.type));
                //else
                expressionType = Math.max(literal.type, expressionType);
                expression.push(literal);
                break;
            case 1:
                literal = formatLiteral(literal);
                if (doUMinus) {
                    literal.literal.insert(0, '-');
                }
                if (expressionType == Constants.FLOAT || expressionType == Constants.DOUBLE) {
                    expression.push(TranslationTable.getInstance().convertType(literal, Constants.BIGDECIMAL, expressionType));
                    expressionType = Constants.BIGDECIMAL;
                } else {
                    expressionType = Math.max(saveType, expressionType);
                }
                break;
            case 2:
                literal = expression.pop();
                literal.literal.insert(0, "(").append(")");
                if (saveUMinus) {
                    if (props.getIdentifierType() < Constants.BIGDECIMAL) {
                        literal.literal.insert(0, '-');
                    } else {
                        literal.literal.append(".negate()");
                    }
                }
                expression.push(literal);
                expressionType = Math.max(saveType, literal.type);
        }
        expression.push(literal);
        doUMinus = false;

    }

    @Override
    public void visit(Power n) {
        String exprString = "";
        doUMinus = false;
        if (n.nodeOptional.present()) {
            n.nodeOptional.node.accept(this);
            doUMinus = lastTokenString.charAt(0) == '-';
        }
        n.basis.accept(this);

        if (n.nodeListOptional.present()) {
            for (Enumeration<Node> e = n.nodeListOptional.elements(); e.hasMoreElements();) {
                Node node = e.nextElement();
                ExpressionString arg1 = getExpression();
                node.accept(this);
                ExpressionString arg2 = getExpression();
                expression.push(TranslationTable.getInstance().doOp(
                        TranslationTable.POW_OP, arg1, arg2));
            }
        }
    }

    @Override
    public void visit(ReturnStatement n) {
    }
    private boolean doingArithmeticExpression = false;

    @Override
    public void visit(ArithmeticExpression n) {
        doingArithmeticExpression = true;
        String exprString = "";
        n.timesDiv.accept(this);
        if (n.nodeListOptional.present()) {
            for (Enumeration<Node> e = n.nodeListOptional.elements(); e.hasMoreElements();) {
                Node node = e.nextElement();
                ((NodeSequence) node).elementAt(0).accept(this);
                String op = lastTokenString;
                ExpressionString arg1 = getExpression();
                node.accept(this);
                ExpressionString arg2 = getExpression();
                expression.push(TranslationTable.getInstance().doOp(op, arg1, arg2));
            }

        }
        doingArithmeticExpression = false;
    }

    @Override
    public void visit(TimesDiv n) {
        String exprString = "";
        n.power.accept(this);
        if (n.nodeListOptional.present()) {
            for (Enumeration<Node> e = n.nodeListOptional.elements(); e.hasMoreElements();) {
                Node node = e.nextElement();
                ((NodeSequence) node).elementAt(0).accept(this);
                String op = lastTokenString;
                ExpressionString arg1 = getExpression();
                ((NodeSequence) node).elementAt(1).accept(this);
                ExpressionString arg2 = getExpression();
                expression.push(TranslationTable.getInstance().doOp(op, arg1, arg2));
            }
        }
    }

    @Override
    public void visit(AcceptStatement n) {
        n.identifier.accept(this);
        String exprString = null;
        if (n.nodeOptional.present()) {
            NodeChoice nodech = (NodeChoice) n.nodeOptional.node;
            NodeSequence nodeseq = (NodeSequence) nodech.choice;
            if (nodech.which == 1) {
                return;
            }
            NodeChoice nodechoice = (NodeChoice) nodeseq.elementAt(1);
            switch (nodechoice.which) {
                case 0://Mnemonic
                case 1://Environment
                    nodechoice.accept(this);
                    if (!lastTokenString.equalsIgnoreCase("CONSOLE")) {
                        exprString = "__getEnvironment(" + formatLiteral(
                                new ExpressionString('\"' + RunTimeUtil.getInstance().stripQuotes(lastTokenString) + '\"')) + ")";
                    } else {
                        exprString = doOneAccept();
                    }
                    break;
                case 2://Date
                    if (((NodeOptional) ((NodeSequence) nodechoice.choice).elementAt(1)).present()) {
                        exprString = "Console.readDate2()";
                    } else {
                        exprString = "Console.readDate()";
                    }
                    break;
                case 3://Day
                    if (((NodeOptional) ((NodeSequence) nodechoice.choice).elementAt(1)).present()) {
                        exprString = "Console.readDay2()";
                    } else {
                        exprString = "Console.readDay()";
                    }
                    break;
                case 4://Day of Week
                    exprString = "Console.readDayOfWeek()";
                    break;
                case 5://time
                    exprString = "Console.readTime()";
                    break;
            }
            expression.push(exprString);
            expressionType = expression.peek().type = Constants.STRING;
            ClassFile.println(TranslationTable.getInstance().getAssignString(props, null, false,true,true));
            return;
        } else {
            exprString = doOneAccept();
        }

        if (exprString != null) {
            exprString = NameUtil.getJavaName(props, true).replace("%0", exprString);
            ClassFile.println(exprString + ";");
        }
    }

    private String doOneAccept() {
        String exprString = null;
        CobolSymbol sym = (CobolSymbol) props.getJavaType();
        if (sym != null) {
            switch (sym.getType()) {
                case Constants.BYTE:
                    exprString = "(byte) Console.readChar()";
                    break;
                case Constants.CHAR:
                    exprString = "Console.readChar()";
                    break;
                case Constants.SHORT:
                    exprString = "(short)Console.readInt()";
                    break;
                case Constants.INTEGER:
                    exprString = "Console.readInt()";
                    break;
                case Constants.LONG:
                    exprString = "Console.readLong()";
                    break;
                case Constants.FLOAT:
                    exprString = "(float) Console.readDouble()";
                    break;
                case Constants.DOUBLE:
                    exprString = "Console.readDouble()";
                    break;
                case Constants.BIGDECIMAL:
                    exprString = "new BigDecimal(Console.readDouble())";
                    break;
                case Constants.STRING:
                    exprString = "Console.readLine()";
                    break;
                case Constants.GROUP:
                    exprString = "Console.readBytes()";
                    break;
            }
        }
        return exprString;

    }

    @Override
    public void visit(Identifier n) {
        if (n.nodeChoice.which == 1) {
            props = SymbolTable.getScope().lookup("RETURN-CODE");
        } else {
            super.visit(n);
        }
        if (props.getSubstringWorkSpace() != null
                && props.getSubstringWorkSpace().size() > 0) {
            props.getSubstringWorkSpace().set(0, props.getSubstringWorkSpace().get(0).replace("%%", "-1"));
        }
    }

    @Override
    public void visit(IntrinsicFunction n) {
        int[] functionArgType = SymbolConstants.getFunctionArgTypes(((NodeChoice) n.nodeSequence.elementAt(1)).which);
        String exprString = "__function__" + String.valueOf(((NodeChoice) n.nodeSequence.elementAt(1)).which) + "__";
        doit:
        if (((NodeOptional) n.nodeSequence.elementAt(2)).present()) {

            NodeOptional nodeopt = (NodeOptional) ((NodeSequence) ((NodeOptional) n.nodeSequence.elementAt(2)).node).elementAt(1);
            if (nodeopt.present()) {
                NodeChoice nodechoice = (NodeChoice) nodeopt.node;
                NodeSequence nodeseq = (NodeSequence) nodechoice.choice;
                int saveType = expressionType = 0;
                nodeseq.elementAt(0).accept(this);
                saveType = Math.max(saveType, expressionType);
                if (nodechoice.which == 0) {
                    saveType = props.getIdentifierType();
                    if (functionArgType[0] < 0) {
                        exprString += SymbolConstants.getSQL(props.getIdentifierType());
                    } else if (functionArgType.length > 1) {
                        for (int i = 1; i < functionArgType.length; i++) {
                            if (functionArgType[i] >= saveType) {
                                saveType = functionArgType[i];
                                break;
                            }
                        }
                        if (saveType == Constants.BIGDECIMAL) {
                            saveType = Constants.DOUBLE;
                        }
                        exprString += SymbolConstants.getSQL(saveType);
                    }
                    expressionType = saveType;
                    exprString += "(";
                    if (props != null) {
                        StringBuilder indexes = new StringBuilder();
                        indexes.append("new __IndexAll(").
                                append(props.findNearestCobolBean().getCobolBeanName()).append(",\"").
                                append("get").append(props.getJavaName2()).append("\"");
                        for (SymbolProperties oc : props.getOccursParents()) {
                            indexes.append(',').append(oc.getMaxOccurs());
                        }
                        indexes.append(')');
                        exprString += indexes.toString();
                        exprString += ")";
                        break doit;
                    }
                } else {
                    exprString += "(";
                    ArrayList<ExpressionString> exprStrings = new ArrayList<ExpressionString>();             
                    exprStrings.add(getExpression());
                    saveType = expressionType;
                    if (((NodeListOptional) nodeseq.elementAt(1)).present()) {
                        for (Enumeration<Node> e = ((NodeListOptional) nodeseq.elementAt(1)).elements(); e.hasMoreElements();) {
                            expressionType = 0;
                            e.nextElement().accept(this);
                            saveType = Math.max(saveType, expressionType);
                            exprStrings.add(getExpression());
                        }
                    }
                    if (functionArgType.length > 1) {
                        for (int i = 1; i < functionArgType.length; i++) {
                            if (functionArgType[i] >= saveType) {
                                saveType = functionArgType[i];
                                break;
                            }
                        }
                        if (saveType == Constants.BIGDECIMAL) {
                            saveType = Constants.DOUBLE;
                        }
                        expressionType = saveType;
                        for (int i = 0; i < exprStrings.size(); ++i) {
                            exprString += TranslationTable.getInstance().convertType(
                                    exprStrings.get(i).toString(), saveType, exprStrings.get(i).type);
                            if (i < exprStrings.size() - 1) {
                                exprString += ",";
                            }
                        }
                    }
                }
                exprString += ")";
                if (functionArgType[0] > 0) {
                    expressionType = functionArgType[0];
                }
            } else {
                exprString += "()";
                expressionType = functionArgType[0];
            }
        } else {
            exprString += "()";
            expressionType = functionArgType[0];
        }
        expression.push(exprString);
        literal = getExpression();
    }

    @Override
    public void visit(FunctionArgument n) {
        super.visit(n);
        switch (n.nodeChoice.which) {
            case 0:
                expression.push(NameUtil.getJavaName(props, false));
                expressionType = props.getIdentifierType();
                break;
            case 1:
                expression.push(formatLiteral(literal));
                break;
        }
    }

    private String declareTemp(SymbolProperties pr) {
        String ret;
        ClassFile.println(SymbolConstants.get(props.getIdentifierType()) + " "
                + (ret = "temp" + String.valueOf(SymbolTable.tempVariablesMark++))
                + ";");
        return ret;
    }

    private String declareTempArr(SymbolProperties pr) {
        String ret;
        String modif = "";
        for (int i = props.getNoOccursSubscripts(); i > 0; --i) {
            modif += "[]";
        }
        ClassFile.println(SymbolConstants.get(props.getIdentifierType()) + modif + " "
                + (ret = "temp" + String.valueOf(SymbolTable.tempVariablesMark++))
                + ";");
        return ret;
    }

    @Override
    public void visit(SpecialRegister n) {
        switch (n.nodeChoice.which) {
            case 2:
            case 3:
            case 4:
            case 5:
            case 6:
            case 7:
            case 8:
                n.nodeChoice.choice.accept(this);
                props = SymbolTable.getScope().lookup(lastTokenString, SymbolConstants.DATA);
                if (props != null) {
                    literal = new ExpressionString(new ExpressionString(props).toString());
                    literal.type = Constants.STRING;
                    break;
                }
            default:
                literal = new ExpressionString(0);
                break;
            case 1:
                n.nodeChoice.choice.accept(this);
                literal = new ExpressionString(props.getLength());
                break;
        }
    }

    @Override
    public void visit(NodeToken n) {
        //super.visit(n);
        lastTokenString = n.tokenImage;
        if (doNumericConstant) {
            numericConstant += n.tokenImage;
        }
        if (doQualified) {
            if (qualified == null) {
                qualified = new Stack<String>();
            }
            if (n.tokenImage != null) {
                if (n.tokenImage.equalsIgnoreCase("IN")
                        || n.tokenImage.equalsIgnoreCase("OF")); else {
                    qualified.push(n.tokenImage);
                }
            }
        } else if (doLiteral) {
            literal.literal.append(n.tokenImage);
        } else if (doingAcceptOption) {
            if (optionStack == null) {
                optionStack = new Stack<String>();
            }
            optionStack.push(n.tokenImage);
        } /*else
        if (doingRelationalOp){
        switch(n.kind) {
        case CobolParserConstants.NOT: break;
        case CobolParserConstants.GREATER: break;
        case CobolParserConstants.LESS: break;
        case CobolParserConstants.EQUAL: break;
        case CobolParserConstants.MORETHANCHAR: break;
        case CobolParserConstants.MORETHANOREQUAL: break;
        case CobolParserConstants.LESSTHANCHAR: case CobolParserConstants.LESSTHANOREQUAL: break;
        case CobolParserConstants.EQUALCHAR: default:break;
        }
        }*/
    }

    @Override
    public void visit(QualifiedDataName n) {
        qualified.clear();
        doQualified = true;
        super.visit(n);
        processQualifiedStack(n);
        doQualified = false;
    }

    private void processQualifiedStack(Node n) {

        SymbolProperties props2 = null;
        props = null;
        if (qualified == null || qualified.size() <= 0) {
            return;
        }
        String curr = null;
        String prev = null;
        curr = (String) qualified.pop();
        do {
            if (qualified.size() > 0) {
                prev = curr;
                curr = (String) qualified.pop();
                if (props2 != null) {
                    props2 = findChild(props2, curr);
                } else {
                    props2 = SymbolTable.getScope().lookup(curr, prev);
                }
                if (props2 == null) {
                    reportError(n, "Unknown Symbol : " + curr + " IN " + prev);
                    break;
                }
            } else {
                props2 = SymbolTable.getScope().lookup(curr);
                if (props2 == null) {
                    reportError(n, "Unknown Symbol : " + curr);
                    break;
                }
            }

            if (props2.isVaryingArray() && props2.getParent().isVarying()) {
                props2 = props2.getParent();
            }

        } while (qualified != null && qualified.size() > 0);


        try {
            props = (SymbolProperties) props2.clone();
        } catch (CloneNotSupportedException e) {
            reportError(n, e.getMessage());
        }
        props.setIndexesWorkSpace(null);//subscripts will fill this
        props.setSubstringWorkSpace(null);//LeftMost... and Length will fill this
        props.setIdentifierType(props.getJavaType().getType());
        expressionType = props.getIdentifierType();

    }

    private SymbolProperties findChild(SymbolProperties props, String name) {
        if (props.getChildren() == null || props.getChildren().size() <= 0) {
            return null;
        }
        for (SymbolProperties ch : props.getChildren()) {
            if (ch.getDataName().equalsIgnoreCase(name)) {
                return ch;
            }
        }
        SymbolProperties ret = null;
        for (SymbolProperties ch : props.getChildren()) {
            ret = findChild(ch, name);
            if (ret != null) {
                return ret;
            }
        }
        return ret;
    }

    private SymbolProperties findProgram(SymbolProperties props) {
        if (props == null) {
            return null;
        }
        do {
            props = props.getParent();
        } while (props != null && !props.isProgram());
        return props;
    }

    @Override
    public void visit(Subscript n) {
        SymbolProperties propsDataName = props;

        if (props.getIndexesWorkSpace() == null) {
            props.setIndexesWorkSpace(new ArrayList<String>());
        }

        switch (n.nodeChoice.which) {
            case 0:
                n.nodeChoice.choice.accept(this);
                int i = 0,
                 j = 0;
                do {
                    if ((j = literal.literal.indexOf(",", i)) < 0) {
                        j = literal.literal.length();
                    }
                    propsDataName.getIndexesWorkSpace().add(stripLeadingZeros(literal.literal.substring(i, j)));
                    i = j + 1;
                } while (i < literal.toString().length());
                break;
            case 1:
                NodeSequence seq = (NodeSequence) n.nodeChoice.choice;
                seq.elementAt(0).accept(this);
                String sub = new ExpressionString(props).toString();
                CobolSymbol sym = props.getJavaType();
                if (sym != null) {
                    if (sym.getType() == Constants.LONG) {
                        sub = "(int)" + sub;
                    } else if (sym.getType() == Constants.BIGDECIMAL) {
                        sub += ".intValue()";
                    }
                }
                if (((NodeOptional) seq.elementAt(1)).present()) {
                    NodeSequence seq2 = (NodeSequence) ((NodeOptional) seq.elementAt(1)).node;
                    NodeChoice ch2 = (NodeChoice) seq2.elementAt(0);
                    switch (ch2.which) {
                        case 0:
                            sub += "+";
                            break;
                        case 1:
                            sub += "-";
                            break;
                    }
                    seq2.elementAt(1).accept(this);
                    i = j = 0;
                    do {
                        if ((j = literal.literal.indexOf(",", i)) < 0) {
                            j = literal.literal.length();
                            sub += stripLeadingZeros(literal.literal.substring(i, j));
                            break;
                        }
                        propsDataName.getIndexesWorkSpace().
                                add(stripLeadingZeros(literal.literal.substring(i, j)));
                        //literal.literal.replace(i, j, stripLeadingZeros(literal.literal.substring(i,j)).toString());
                        i = j + 1;
                    } while (i < literal.toString().length());
                    //sub+=literal.toString();
                }
                propsDataName.getIndexesWorkSpace().add(sub);
                break;
            case 2:
        }
        //}
        //propsDataName.setIndexesWorkSpace(a);
        props = propsDataName;
        //super.visit(n);
    }

    @Override
    public void visit(LeftmostCharacterPosition n) {
        SymbolProperties propsDataName = props;
        initExpressionType();
        super.visit(n);
        if (expression.size() > 0 && expressionType < Constants.BIGDECIMAL) {//TODO REPORT ERROR ON NOT INTEGER SUBSCRIPT
            propsDataName.setSubstringWorkSpace(new ArrayList<String>());
            if (numPattern.matcher(expression.peek3()).matches()) {
                propsDataName.getSubstringWorkSpace().add(
                        new BigDecimal(stripLeadingZeros(expression.pop3())).subtract(BigDecimal.ONE).toPlainString());
            } else {
                propsDataName.getSubstringWorkSpace().add(expression.pop3() + "%%");
            }
        }
        props = propsDataName;
        expressionType = Constants.STRING;
    }

    @Override
    public void visit(Length n) {
        SymbolProperties propsDataName = props;
        initExpressionType();
        super.visit(n);
        if (propsDataName.getSubstringWorkSpace() == null) {
            propsDataName.setSubstringWorkSpace(new ArrayList<String>());
            propsDataName.getSubstringWorkSpace().add("0");
        }
        if (expression.size() > 0 && expressionType < Constants.BIGDECIMAL) {//TODO REPORT ERROR ON NOT INTEGER SUBSCRIPT
            if (numPattern.matcher(propsDataName.getSubstringWorkSpace().get(0)).matches()) {
                if (numPattern.matcher(expression.peek3()).matches()) {
                    propsDataName.getSubstringWorkSpace().add(
                            new BigDecimal(propsDataName.getSubstringWorkSpace().get(0)).add(new BigDecimal(stripLeadingZeros(expression.pop3()))).toPlainString());
                } else {
                    propsDataName.getSubstringWorkSpace().add(
                            propsDataName.getSubstringWorkSpace().get(0).replace("%%", "-1")
                            + "+" + stripLeadingZeros(expression.pop3()));
                }
            } else if (numPattern.matcher(expression.peek3()).matches()) {
                propsDataName.getSubstringWorkSpace().add(
                        propsDataName.getSubstringWorkSpace().get(0).replace("%%", "")
                        + "+" + new BigDecimal(stripLeadingZeros(expression.pop3())).subtract(BigDecimal.ONE).toPlainString());
            } else {
                propsDataName.getSubstringWorkSpace().add(
                        propsDataName.getSubstringWorkSpace().get(0).replace("%%", "-1")
                        + "+" + stripLeadingZeros(expression.pop3()));
            }
        }
        props = propsDataName;
    }

    @Override
    public void visit(ProgramIdParagraph n) {
        SymbolProperties pgm = SymbolTable.getScope().lookup(n.programName.cobolWord.nodeToken.tokenImage, SymbolConstants.PROGRAM);
        if (pgm == null) {
            reportError(n, "Fatal Error: Cobol2Java.visit(ProgramIdParagraph):"
                    + n.programName.cobolWord.nodeToken.tokenImage);
        }
        SymbolTable.getScope().startProgram(pgm);
        super.visit(n);
    }

    @Override
    public void visit(NestedProgramIdParagraph n) {
        SymbolProperties pgm = SymbolTable.getScope().lookup(n.programName.cobolWord.nodeToken.tokenImage, SymbolConstants.PROGRAM);
        if (pgm == null) {
            reportError(n, "Fatal Error: Cobol2Java.visit(ProgramIdParagraph):"
                    + n.programName.cobolWord.nodeToken.tokenImage);
        }
        SymbolTable.getScope().startProgram(pgm);
        super.visit(n);
    }

    @Override
    public void visit(Literal n) {
        literal = new ExpressionString();
        if (n.nodeChoice.which == 3) {
            n.nodeChoice.choice.accept(this);
        } else if (n.nodeChoice.which == 4) {
            n.nodeChoice.choice.accept(this);
        } else if (n.nodeChoice.which == 5) {
            NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
            if (((NodeOptional) nodeseq.elementAt(1)).present()) {
                ((NodeOptional) nodeseq.elementAt(1)).accept(this);
            } else {
                props = null;
                for (SymbolProperties f : SymbolTable.getScope().getCurrentProgram().getChildren()) {
                    if (f.isFile()) {
                        props = f;
                        break;
                    }

                }
            }
            if (props == null || !props.isFile()) {
                reportError(n, "Unknown LINAGE-COUNTER either file name missing or invalid.");
                return;
            }
            literal = new ExpressionString(props.getJavaName1() + ".linageCounter()");
            literal.setType(Constants.INTEGER);
        } else {
            doLiteral = true;
            n.nodeChoice.choice.accept(this);
            doLiteral = false;
        }

        if (n.nodeOptional.present() && (n.nodeChoice.which == 0 || n.nodeChoice.which == 1)) {
            literal.isAll = true;
        }
    }
    private String numericConstant = "";
    private boolean doNumericConstant = false;

    @Override
    public void visit(NumericConstant n) {
        numericConstant = "";
        doNumericConstant = true;
        super.visit(n);
        literal = new ExpressionString(numericConstant);
        doNumericConstant = false;
    }
    private boolean isPreviousRelationCondition = false;
    private ExpressionString previousRelationSubject = null;
    private int previousRelationOp = 0;
    private int relop = 0;

    @Override
    public void visit(Condition n) {
        isPreviousRelationCondition = false;
        n.combinableCondition.accept(this);
        if (n.nodeListOptional.present()) {
            for (int i = 0; i < n.nodeListOptional.size(); ++i) {
                NodeSequence nodeseq = (NodeSequence) n.nodeListOptional.elementAt(i);
                NodeChoice nodechoice = (NodeChoice) nodeseq.elementAt(0);
                nodeseq.elementAt(1).accept(this);
                int op = 0;
                switch (nodechoice.which) {
                    case 0:
                        op = TranslationTable.AND_CONDITION;
                        break;
                    case 1:
                    default:
                        op = TranslationTable.OR_CONDITION;
                        break;
                }
                ExpressionString temp = new ExpressionString(condition.pop()); //For reversing the order
                condition.push(TranslationTable.getInstance().doCondition(
                        op,
                        new ExpressionString(condition.pop()),
                        temp,
                        doReverseCondition));
            }
        }
    }

    @Override
    public void visit(RelationalOperator n) {
        super.visit(n);
        boolean isNot = n.nodeOptional1.present() ? !doReverseCondition : doReverseCondition;
        mapRelOp(n.nodeChoice.which, isNot);
    }

    private int mapRelOp(int which, boolean isNot) {
        relop = TranslationTable.EQ_CONDITION;
        switch (which) {
            case 0:
            case 1:
                relop = TranslationTable.GE_CONDITION;
                break;
            case 2:
            case 3:
                relop = TranslationTable.LE_CONDITION;
                break;
            case 4:
            case 5:
                relop = TranslationTable.GT_CONDITION;
                break;
            case 6:
            case 7:
                relop = TranslationTable.LT_CONDITION;
                break;
            case 8:
            case 9:
                relop = TranslationTable.EQ_CONDITION;
                break;
            case 10:
                relop = TranslationTable.NE_CONDITION;
                break;
            default:
        }
        return relop = TranslationTable.getInstance().getReverseOp(relop, isNot);
    }

    //private  int conditionType=0;
    @Override
    public void visit(AbbreviationLeaf n) {
        super.visit(n);
    }

    @Override
    public void visit(AbbreviationRest n) {
        if (!isPreviousRelationCondition) {
            return;//TODO Syntax error reporting
        }
        for (int i = 0; i < n.nodeList.size(); ++i) {
            NodeSequence seq = (NodeSequence) n.nodeList.elementAt(i);

            if (((NodeOptional) seq.elementAt(1)).present()) {
                if (((NodeOptional) seq.elementAt(0)).present()) {
                    doReverseCondition = !doReverseCondition;//for formatComparison
                }
                seq.elementAt(1).accept(this);
                if (((NodeOptional) seq.elementAt(0)).present()) {
                    doReverseCondition = !doReverseCondition;//Restore
                }
            } else {
                relop = mapRelOp(relop, ((NodeOptional) seq.elementAt(0)).present());
            }
            seq.elementAt(2).accept(this);
            String top = TranslationTable.getInstance().doCondition(relop, previousRelationSubject, getExpression(), false);
            //while(condition.size()>0)
            //top=condition.pop()+top;
            condition.push(top);
        }
    }
    private boolean doingRelationCondition = false;

    @Override
    public void visit(RelationCondition n) {
        isPreviousRelationCondition = true;
        doingRelationCondition = true;
        initExpressionType();
        n.arithmeticExpression.accept(this);
        previousRelationSubject = getExpression();
        initExpressionType();
        n.nodeChoice.accept(this);
        if (n.nodeChoice.which == 0) {
            String top = TranslationTable.getInstance().doCondition(relop, previousRelationSubject,
                    getExpression(), false);
            //while(condition.size()>0)
            //top=condition.pop()+top;
            condition.push(top);
        }
        doingRelationCondition = false;
    }

    private String formatCompareToRelop(int relopInt) {
        switch (relopInt) {
            case 0:
                return " < 0";
            case 1:
                return " <= 0";
            case 2:
                return " > 0";
            case 3:
                return " >= 0";
            case 4:
                return " == 0";
            case 5:
                return " !=0";
        }
        return "";
    }

    @Override
    public void visit(CombinableCondition n) {
        if (n.nodeOptional.present()) {
            doReverseCondition = !doReverseCondition;
        }
        super.visit(n);
        if (n.nodeOptional.present()) {
            doReverseCondition = !doReverseCondition;
        }
    }

    @Override
    public void visit(ClassCondition n) {
        isPreviousRelationCondition = false;
        n.identifier.accept(this);
        StringBuilder name = new StringBuilder(new ExpressionString(props).toString());
        int begin = name.lastIndexOf(".") + 1;
        int end = name.indexOf("(");
        switch (n.nodeChoice.which) {
            case 0:
                if (props.isNumericTested()) {
                    condition.push(name.replace(begin, end, "is" + props.getJavaName2() + "Numeric").toString());
                } else {
                    condition.push(name.toString());
                }
                break;
            case 1:
                if (props.isAlphabeticTested()) {
                    condition.push(name.replace(begin, end, "is" + props.getJavaName2() + "Alphabetic").toString());
                } else {
                    condition.push(name.toString());
                }
                break;
            case 2:
                if (props.isAlphabeticTested()) {
                    condition.push(name.replace(begin, end, "is" + props.getJavaName2() + "AlphabeticLower").toString());
                } else {
                    condition.push(name.toString());
                }
                break;
            case 3:
                if (props.isAlphabeticTested()) {
                    condition.push(name.replace(begin, end, "is" + props.getJavaName2() + "AlphabeticUpper").toString());
                } else {
                    condition.push(name.toString());
                }
                break;
            case 4:
            case 5:
            case 6:
                condition.push(name.toString());
        }
        if (n.nodeOptional1.present()) {
            condition.push("!" + condition.pop());
        }
    }

    @Override
    public void visit(SignCondition n) {
        isPreviousRelationCondition = false;
        super.visit(n);
        boolean isNot = n.nodeOptional1.present() ? !doReverseCondition : doReverseCondition;
        int op = 0;
        switch (n.nodeChoice.which) {
            case 0:
                op = TranslationTable.POSITIVE_CONDITION;
                break;
            case 1:
                op = TranslationTable.NEGATIVE_CONDITION;
                break;
            case 2:
                op = TranslationTable.ZERO_CONDITION;
        }
        if (isNot) {
            condition.push('!' + TranslationTable.getInstance().doCondition(op,
                    previousRelationSubject, false));
        } else {
            condition.push(TranslationTable.getInstance().doCondition(op,
                    previousRelationSubject, false));
        }
        expressionType = Constants.INTEGER;
    }

    @Override
    public void visit(ConditionNameCondition n) {
        props = null;
        isPreviousRelationCondition = false;
        super.visit(n);
        String top = ((doReverseCondition) ? "!(%0)" : "%0");
        if (props == null) {
            return;
        }
        if (props.getLevelNumber() == 88 || previousRelationSubject == null) {
            top = top.replace("%0", new ExpressionString(props).toString());
        } else {
            expression.push(new ExpressionString(props).toString());
            expressionType = props.getIdentifierType();
            top = top.replace("%0",
                    TranslationTable.getInstance().
                    doCondition(relop, previousRelationSubject, getExpression(), false));
        }
        condition.push(top);
    }

    @Override
    public void visit(ConditionNameReference n) {
        qualified.clear();
        doQualified = true;
        n.conditionName.accept(this);
        switch (n.nodeChoice.which) {
            case 0:
                NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
                nodeseq.elementAt(0).accept(this);
                nodeseq.elementAt(1).accept(this);
                doQualified = false;
                processQualifiedStack(n);
                nodeseq.elementAt(2).accept(this);
                break;
            case 1:
                n.nodeChoice.choice.accept(this);
                doQualified = false;
                processQualifiedStack(n);
        }
    }

    @Override
    public void visit(SimpleCondition n) {
        switch (n.nodeChoice.which) {
            case 3:
                if (n.nodeChoice.choice instanceof NodeSequence) {
                    //String top="";
                    //if (condition.size()>0)
                    //top=condition.pop();
                    NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
                    nodeseq.elementAt(1).accept(this);
                    condition.push("(" + condition.pop() + ")");
                }
                break;
            case 1:
            case 2:
            case 0:
                n.nodeChoice.choice.accept(this);
        }
    }
    private boolean doReverseCondition = false;
    private boolean doUMinus = false;

    @Override
    public void visit(IfStatement n) {

        initExpressionType();
        doReverseCondition = false;
        condition = new Stack<String>();
        n.condition.accept(this);
        doReverseCondition = false;
        ClassFile.println("if(" + condition.pop() + ") {");
        ClassFile.tab();
        switch (n.nodeChoice.which) {
            case 0:
                NodeSequence seq = (NodeSequence) n.nodeChoice.choice;
                seq.elementAt(0).accept(this);
                break;
            case 1:
            default:
        }
        //n.statementList.accept(this);

        ClassFile.backTab();
        if (n.nodeOptional1.present()) {
            ClassFile.println("} else {");
            ClassFile.tab();
            if (n.nodeOptional1.node instanceof NodeSequence) {
                NodeSequence seq2 = (NodeSequence) n.nodeOptional1.node;
                NodeChoice choice = (NodeChoice) seq2.elementAt(1);
                switch (choice.which) {
                    case 0:
                        NodeSequence seq = (NodeSequence) choice.choice;
                        seq.elementAt(0).accept(this);
                        break;
                    case 1:
                    default:
                }
            }
            ClassFile.backTab();
            ClassFile.println("}");
        } else {
            ClassFile.println("}");
        }
    }

    @Override
    public void visit(PerformBody arg0) {
        //super.visit(arg0);
        switch (arg0.nodeChoice.which) {
            case 1:
                if (arg0.nodeChoice.choice instanceof NodeSequence) {
                    NodeSequence nodeseq = (NodeSequence) arg0.nodeChoice.choice;
                    if (nodeseq.nodes.size() == 2) {
                        nodeseq.accept(this);//do the descent for both
                        if (procedureProps == null) {
                            return;
                        }
                        if (!someOrAllConsolidated(procedureProps, procedureThruProps)) {
                            ClassFile.println("doCobolPerform(" + procedureProps.getJavaName1() + ((procedureThruProps == null) ? "" : ("," + procedureThruProps.getJavaName1())) + ");");
                        }
                        if (((NodeOptional) nodeseq.elementAt(1)).present()
                                && endBlockScopeCriterion != null && endBlockScopeCriterion.size() > 0) {
                            Stack<String> st = endBlockScopeCriterion.pop();
                            while (st.size() > 0) {
                                String endScope = st.pop();
                                if (endScope.charAt(0) == '}') {
                                    ClassFile.backTab();
                                }
                                ClassFile.println(endScope);
                            }
                        }
                    }
                }
                break;
            case 0:
                if (arg0.nodeChoice.choice instanceof NodeSequence) {
                    NodeSequence nodeseq = (NodeSequence) arg0.nodeChoice.choice;
                    nodeseq.elementAt(0).accept(this);//do the descent for both
                    nodeseq.elementAt(1).accept(this);
                    if (endBlockScopeCriterion != null && endBlockScopeCriterion.size() > 0) {
                        Stack<String> st = endBlockScopeCriterion.pop();
                        while (st.size() > 0) {
                            String endScope = st.pop();
                            if (endScope.charAt(0) == '}') {
                                ClassFile.backTab();
                            }
                            ClassFile.println(endScope);
                        }
                    }
                }
                break;
            default:
        }
    }

    private boolean someOrAllConsolidated(SymbolProperties from, SymbolProperties thru) {
        /*
        if(thru==null) thru=from;
        if(thru.getParagraphMark()>=from.getParagraphMark()) {
        SymbolProperties sectionF=null,paraF=null,sectionT=null,paraT=null;
        if(from.getType()==SymbolConstants.PARAGRAPH) {
        sectionF=from.getParent();
        paraF=from;
        } else {
        sectionF=from;
        paraF=from.getChildren().get(0);
        }
        if(thru.getType()==SymbolConstants.PARAGRAPH) {
        sectionT=thru.getParent();
        paraT=thru;
        } else {
        sectionT=thru;
        paraT=thru.getChildren().get(0);
        }
        allUnConsolidated: {
        someConsolidated: {
        if(!sectionF.getDataName().equalsIgnoreCase(sectionT.getDataName())) {
        props=sectionF.getChildren().get(sectionF.getChildren().size()-1);
        } else {
        props=paraT;
        }
        for(paragraphProps=paraF;paragraphProps!=null&&paragraphProps.getParagraphMark()<=props.getParagraphMark();paragraphProps=paragraphProps.getSibling()) {
        if(paragraphProps.isConsolidateParagraph()&&!paragraphProps.isGotoTarget()) break someConsolidated;
        }
        if(!sectionF.getDataName().equalsIgnoreCase(sectionT.getDataName())) {
        paragraphProps=sectionT.getChildren().get(0);
        } else {
        break allUnConsolidated;
        }
        for(;paragraphProps!=null&&paragraphProps.getParagraphMark()<=paraT.getParagraphMark();paragraphProps=paragraphProps.getSibling()) {
        if(paragraphProps.isConsolidateParagraph()&&!paragraphProps.isGotoTarget()) break someConsolidated;
        }
        }
        //Some Consolidated
        if(!sectionF.getDataName().equalsIgnoreCase(sectionT.getDataName())) {
        unConsolidate(paraF,sectionF.getChildren().get(sectionF.getChildren().size()-1));
        } else {
        unConsolidate(paraF,paraT);
        }
        if(!sectionF.getDataName().equalsIgnoreCase(sectionT.getDataName())) {
        if(!sectionF.getDataName().equalsIgnoreCase(sectionT.getDataName())) {
        paragraphProps=sectionT.getChildren().get(0);
        unConsolidate(paragraphProps,paraT);
        } else {
        }
        } else {
        }
        return true;
        }
        //allUnConsolidation
        }*/
        return false;
    }
    /*
    private void unConsolidate(SymbolProperties paraF,SymbolProperties thru) {
    consolidationInProgress=true;
    if(thru==null) thru=paraF;
    SymbolProperties temp=null,temp2=null;boolean lastOneToBePrnted=false;
    for(props=paraF;props!=null&&props.getParagraphMark()<=thru.getParagraphMark();props=props.getSibling()) {
    if(props.isConsolidateParagraph()&&!props.isGotoTarget()) {
    if(lastOneToBePrnted) {

    ClassFile.println("doCobolPerform("+temp.getJavaName1()+","+((temp2==null)?"null":temp2.getJavaName1())+");");
    temp=temp2=null;lastOneToBePrnted=false;
    }
    ((Node)props.getOtherData2()).accept(this);
    } else {
    if(temp==null)
    temp=props;
    else
    temp2=props;
    lastOneToBePrnted=true;
    }
    }
    if(lastOneToBePrnted) {
    ClassFile.println("doCobolPerform("+temp.getJavaName1()+","+((temp2==null)?"null":temp2.getJavaName1())+");");
    temp=temp2=null;lastOneToBePrnted=false;
    }
    consolidationInProgress=false;
    }
     */

    @Override
    public void visit(PerformOption arg0) {
        //super.visit(arg0);
        Stack<String> st = new Stack<String>();
        switch (arg0.nodeChoice.which) {
            case 0:
                String timesVar = null;
                if (arg0.nodeChoice.choice instanceof NodeSequence) {
                    NodeSequence nodeseq = (NodeSequence) arg0.nodeChoice.choice;
                    nodeseq.accept(this);
                    if (nodeseq.elementAt(0) instanceof NodeChoice) {
                        switch (((NodeChoice) nodeseq.elementAt(0)).which) {
                            case 0:
                                timesVar = new ExpressionString(props).toString();
                                expressionType = props.getIdentifierType();
                                break;//out of ((NodeChoice)nodeseq.elementAt(0)).which
                            case 1:
                                timesVar = formatLiteral(literal).toString();
                                break;//out of ((NodeChoice)nodeseq.elementAt(0)).which
                            default:
                        }
                        timesVar = TranslationTable.getInstance().convertType(timesVar, Constants.INTEGER, expressionType);
                        String tempVar = "i" + new Integer(SymbolTable.tempVariablesMark++).toString().trim();
                        ClassFile.println("for(int " + tempVar + "=" + timesVar
                                + ";" + tempVar + ">0;" + "--" + tempVar + ") {");
                        ClassFile.tab();
                        st.push("}");
                    }
                }
                break;
            case 1:
                if (arg0.nodeChoice.choice instanceof NodeSequence) {
                    NodeSequence nodeseq = (NodeSequence) arg0.nodeChoice.choice;
                    NodeOptional nodeOpt = (NodeOptional) nodeseq.elementAt(0);
                    beforeOrAfter = 0;
                    if (nodeOpt.present()) {
                        nodeOpt.accept(this);
                    }
                    doReverseCondition = true;
                    condition = new Stack<String>();
                    nodeseq.elementAt(2).accept(this);
                    if (condition != null && condition.size() > 0) {
                        if (beforeOrAfter == 0) {	//Before
                            ClassFile.println("while(" + condition.pop() + ") {");
                            ClassFile.tab();
                            st.push("}");
                        } else {	//After
                            ClassFile.println("do {");
                            ClassFile.tab();
                            st.push("} while(" + condition.pop() + ");");
                        }
                    }
                }
                break;
            case 2:
                if (arg0.nodeChoice.choice instanceof NodeSequence) {
                    endBlockScopeCriterion.push(st);//pushed ahead and returns instead of break
                    NodeSequence nodeseq = (NodeSequence) arg0.nodeChoice.choice;
                    NodeOptional nodeOpt = (NodeOptional) nodeseq.elementAt(0);
                    beforeOrAfter = 0;
                    if (nodeOpt.present()) {
                        nodeOpt.accept(this);
                    }
                    nodeseq.elementAt(2).accept(this);
                    return;
                }
            default:
        }
        endBlockScopeCriterion.push(st);
    }
    private Stack<Stack<String>> endBlockScopeCriterion = new Stack<Stack<String>>();

    @Override
    public void visit(PerformProcedure arg0) {
        if (arg0.nodeOptional.present()) {
            arg0.nodeOptional.accept(this);
            procedureThruProps = procedureProps;
        } else {
            procedureThruProps = null;
        }
        arg0.procedureName.accept(this);
    }

    @Override
    public void visit(PerformStatement n) {
        super.visit(n);
    }

    @Override
    public void visit(PerformTest arg0) {
        super.visit(arg0);
    }
    private int beforeOrAfter = 0;

    @Override
    public void visit(BeforeOrAfter n) {
        beforeOrAfter = n.nodeChoice.which;
    }

    @Override
    public void visit(PerformVarying arg0) {

        arg0.identifier.accept(this);
        saveProps = props;
        idOrLiteralList = new ArrayList<ExpressionString>();
        String fromVar, byVar;
        arg0.idOrLiteral.accept(this);
        ExpressionString o = idOrLiteralList.get(0);
        if (o.Id() != null) {
            fromVar = new ExpressionString(o.Id()).toString();
            expressionType = o.Id().getIdentifierType();
        } else {
            fromVar = formatLiteral(new ExpressionString(o.Lit())).toString();
        }
        expression.push(fromVar);
        String init = TranslationTable.getInstance().getAssignString(saveProps, null, false, false);
        idOrLiteralList = new ArrayList<ExpressionString>();
        arg0.idOrLiteral1.accept(this);
        o = idOrLiteralList.get(0);

        if (o.Id() != null) {
            byVar = new ExpressionString(o.Id()).toString();
            expressionType = o.Id().getIdentifierType();
        } else {
            byVar = formatLiteral(new ExpressionString(o.Lit())).toString();
        }

        expression.push(byVar);
        TranslationTable.getInstance().doIdOp(saveProps, "+");
        String incr = TranslationTable.getInstance().getAssignString(saveProps, null, false, false);

        if (beforeOrAfter == 0) {
            doReverseCondition = true;
            condition = new Stack<String>();
            arg0.condition.accept(this);
            ClassFile.println("for(" + init + ";" + condition.pop() + ";" + incr + ") {");
            ClassFile.tab();
            endBlockScopeCriterion.peek().add("}");
        } else {
            doReverseCondition = false;
            condition = new Stack<String>();
            arg0.condition.accept(this);
            ClassFile.println(init + ";");
            ClassFile.println("do {");
            ClassFile.tab();
            endBlockScopeCriterion.peek().add("} while(true);");
            endBlockScopeCriterion.peek().add(incr + ";");
            endBlockScopeCriterion.peek().add("if(" + condition.pop() + ") break;");
        }
    }

    @Override
    public void visit(IntegerConstant n) {
        if (doLiteral || doNumericConstant) {
            super.visit(n);
        } else {
            literal = new ExpressionString(((NodeToken) n.nodeChoice.choice).tokenImage);
        }
    }

    @Override
    public void visit(NonNumericConstant n) {
        switch (n.nodeChoice.which) {
            case 0:
                literal = new ExpressionString(((NodeToken) n.nodeChoice.choice).tokenImage);
                break;
            case 1:
                literal = new ExpressionString(((NodeToken) n.nodeChoice.choice).tokenImage);
                literal = new ExpressionString("0" + literal.toString().replace("\'", "").replace("\"", ""));
        }
    }

    @Override
    public void visit(FigurativeConstant n) {
        String lit = null;
        switch (n.nodeChoice.which) {
            case 0:
            case 1:
            case 2:
                lit = "0";
                break;
            case 3:
            case 4:
                lit = "SPACES";
                break;
            case 5:
            case 6:
                lit = "__function__" + String.valueOf(50) + "__()";
                expressionType = Constants.CHAR;
                break;
            case 7:
            case 8:
                lit = "__function__" + String.valueOf(51) + "__()";
                expressionType = Constants.CHAR;
                break;
            case 9:
            case 10:
                lit = "\"\\\"\"";
                break;
            case 11:
            case 12:
            default:
                lit = "0";
                break;
        }
        if (doLiteral) {
            literal.literal.append(lit);
        } else {
            literal = new ExpressionString(lit);
        }
    }

    @Override
    public void visit(PerformVaryingList arg0) {
        //super.visit(arg0);
        arg0.performVarying.accept(this);
        for (int i = 0; ((i < 4) && arg0.nodeListOptional.present()
                && i < arg0.nodeListOptional.size()); ++i) {
            NodeSequence nodeseq = (NodeSequence) arg0.nodeListOptional.elementAt(i);
            nodeseq.elementAt(1).accept(this);
        }
    }

    @Override
    public void visit(StringStatement n) {

        StringBuilder cLine = new StringBuilder("");
        StringBuilder single = new StringBuilder("");
        n.identifier.accept(this);
        if (props == null) {
            return;
        }
        saveProps = props;
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            ExpressionString delimitedBy = null;
            NodeSequence nodeseq = (NodeSequence) e.nextElement();
            if (((NodeOptional) nodeseq.elementAt(1)).present()) {
                NodeSequence opt = (NodeSequence) ((NodeOptional) nodeseq.elementAt(1)).node;
                NodeChoice nodech = (NodeChoice) opt.elementAt(2);
                nodech.accept(this);
                switch (nodech.which) {
                    case 0:
                        delimitedBy = new ExpressionString(props);
                        break;
                    case 1:
                        delimitedBy = formatLiteral(literal);
                        break;
                    default:
                        delimitedBy = null;
                }
            }
            for (Enumeration<Node> e2 = ((NodeList) nodeseq.elementAt(0)).elements(); e2.hasMoreElements();) {
                props = null;
                literal = null;
                NodeChoice nodechoice = (NodeChoice) e2.nextElement();
                nodechoice.accept(this);
                switch (nodechoice.which) {
                    case 0:
                        single.append(TranslationTable.getInstance().
                                convertType(new ExpressionString(props),Constants.STRING,props.getIdentifierType()));
                        break;
                    case 1:
                        single.append(TranslationTable.getInstance().convertType(
                                formatLiteral(literal),
                                Constants.STRING, expressionType));
                }

                if (delimitedBy != null) {
                    cLine.append("__delimitedBy(").append(single).append(',').append(delimitedBy.toString()).append(')');
                } else {
                    cLine.append(single);
                }
                if (e2.hasMoreElements()) {
                    cLine.append('+');
                }
                single.setLength(0);
            }
            if (e.hasMoreElements()) {
                cLine.append('+');
            }
        }
        if (cLine.length() > 0) {
            expression.push(cLine.toString());
            expressionType = Constants.STRING;
            ClassFile.println(TranslationTable.getInstance().getAssignString(saveProps, null, false));
        }
    }
    private SymbolProperties inspectSourceSym = null;
    private SymbolProperties inspectCounterSym = null;
    //These two lists should match

    @Override
    public void visit(InspectStatement n) {
        n.identifier.accept(this);
        inspectSourceSym = props;
        super.visit(n);
    }

    /*
     *
    <REPLACING>
    (
    <CHARACTERS> <BY>
    ( Identifier() | Literal() ) ( BeforeAfterPhrase() )*
    | ( <ALL> | <LEADING> | <FIRST> )
    ( ( Identifier() | Literal() )
    <BY> ( Identifier() | Literal() )
    ( BeforeAfterPhrase() )*
    )+
    )+
     */

    /*
    <TALLYING>
    ( Identifier() <FOR> ( <CHARACTERS> ( BeforeAfterPhrase() )*  |
    ( <ALL> | <LEADING> )
    (
    ( Identifier() | Literal() ) ( BeforeAfterPhrase() )*
    )+
    )+
    )+
     */
    @Override
    public void visit(TallyingPhrase n) {
        aLine.push(new StringBuilder());
        for (Enumeration<?> e = n.nodeList.elements(); e.hasMoreElements();) {
            aLine.peek().append("new CobolString(").append(new ExpressionString(inspectSourceSym).toString() + ")");
            NodeSequence seq = (NodeSequence) e.nextElement();
            seq.elementAt(0).accept(this);
            inspectCounterSym = props;
            NodeList nodelist = (NodeList) seq.elementAt(2);
            //String tempLine=aLine;
            for (Enumeration<?> e2 = nodelist.elements(); e2.hasMoreElements();) {
                NodeChoice nodechoice = (NodeChoice) e2.nextElement();
                if (nodechoice.which == 0) {
                    nodechoice.choice.accept(this);
                    aLine.peek().append(".tally()");
                } else {
                    String thisChar = "";
                    NodeSequence seq2 = (NodeSequence) nodechoice.choice;
                    NodeChoice allLeading = (NodeChoice) seq2.elementAt(0);
                    switch (allLeading.which) {
                        case 0:
                            aLine.peek().append(".all()");
                            break;
                        case 1:
                            aLine.peek().append(".leading()");
                            break;
                        default:
                            continue;
                    }
                    NodeList list = (NodeList) seq2.elementAt(1);
                    for (Enumeration<?> e3 = list.elements(); e3.hasMoreElements();) {
                        NodeSequence seq3 = (NodeSequence) e3.nextElement();
                        seq3.elementAt(1).accept(this);
                        thisChar = doInspectPhrase1(seq3.elementAt(0));
                        aLine.peek().append(".tally(").append(thisChar).append(")");
                    }
                }
            }
            aLine.peek().append(".tallyCount()");
            aLine.peek().append("+").append(new ExpressionString(inspectCounterSym).toString());
            line = NameUtil.getJavaName(inspectCounterSym, true).replace("%0", aLine.peek().toString()) + ";";
            ClassFile.println(line);
            aLine.peek().setLength(1);
            aLine.peek().setCharAt(0, '\t');
        }
        aLine.pop();
        n.nodeOptional.accept(this);
    }

    @Override
    public void visit(ReplacingPhrase n) {
        String byChar, thisChar;
        aLine.push(new StringBuilder());
        aLine.peek().append("new CobolString(").append(new ExpressionString(inspectSourceSym).toString()).append(")");
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeChoice nodechoice = (NodeChoice) e.nextElement();
            NodeSequence seq = (NodeSequence) nodechoice.choice;
            if (nodechoice.which == 0) {
                byChar = doInspectPhrase1(seq.elementAt(2));
                nodechoice.choice.accept(this);
                aLine.peek().append(".replace(").append(byChar).append(")");
            } else {
                NodeSequence seq2 = (NodeSequence) nodechoice.choice;
                NodeChoice allLeading = (NodeChoice) seq2.elementAt(0);
                switch (allLeading.which) {
                    case 0:
                        aLine.peek().append(".all()");
                        break;
                    case 1:
                        aLine.peek().append(".leading()");
                        break;
                    case 2:
                        aLine.peek().append(".first()");
                        break;
                    default:
                        continue;
                }
                NodeList list = (NodeList) seq2.elementAt(1);
                for (Enumeration<Node> e2 = list.elements(); e2.hasMoreElements();) {
                    NodeSequence seq3 = (NodeSequence) e2.nextElement();
                    seq3.elementAt(3).accept(this);
                    thisChar = doInspectPhrase1(seq3.elementAt(0));
                    byChar = doInspectPhrase1(seq3.elementAt(2));
                    aLine.peek().append(".replace(").append(thisChar).append(',').append(byChar).append(")");
                }
            }
        }
        expression.push(aLine.peek().append(".toString()").toString());
        expressionType = Constants.STRING;
        line = TranslationTable.getInstance().getAssignString(inspectSourceSym, null, false, true);
        ClassFile.println(line);
        aLine.pop();
    }

    @Override
    public void visit(ConvertingPhrase n) {
        String from = doInspectPhrase1(n.nodeChoice);
        String to = doInspectPhrase1(n.nodeChoice1);
        aLine.push(new StringBuilder());
        aLine.peek().append("new CobolString(").append(new ExpressionString(inspectSourceSym)).append(")");
        n.nodeListOptional.accept(this);
        aLine.peek().append(".convert(").append(from).append(',').append(to).append(')').append(".toString()");
        line = NameUtil.getJavaName(inspectSourceSym, true).replace("%0", aLine.peek().toString()) + ";";
        ClassFile.println(line);
        aLine.pop();
    }

    //private String inspectLine=null;
    private String doInspectPhrase1(Node n) {
        props = null;
        literal = null;
        n.accept(this);
        if (props != null) {
            return TranslationTable.getInstance().convertType(
                    new ExpressionString(props).toString(),
                    Constants.STRING,
                    props.getIdentifierType());
        } else if (literal != null) {
            literal = formatLiteral(literal);
            return TranslationTable.getInstance().convertType(
                    literal.toString(),
                    Constants.STRING,
                    expressionType);
        }
        return "";
    }

    @Override
    public void visit(BeforeAfterPhrase n) {
        if (aLine == null) {
            return;
        }
        props = null;
        literal = null;
        n.nodeChoice1.accept(this);
        if (n.nodeChoice.which == 0) {
            aLine.peek().append(".before(");
        } else {
            aLine.peek().append(".after(");
        }
        if (props != null) {
            aLine.peek().append(new ExpressionString(props).toString());
        } else {
            if (literal != null) {
                aLine.peek().append(formatLiteral(literal).toString());
            }
        }
        aLine.peek().append(")");
    }

    @Override
    public void visit(SetStatement n) {
        saveProps = null;
        props = null;
        literal = null;
        for (Enumeration<Node> e0 = n.nodeList.elements(); e0.hasMoreElements();) {
            NodeSequence nodeSequence  = (NodeSequence) e0.nextElement();
            nodeSequence.elementAt(1).accept(this);
            saveProps = props;
            for (Enumeration<Node> e = ((NodeList)nodeSequence.elementAt(0))
                    .elements(); e.hasMoreElements();) {
                e.nextElement().accept(this);
                if (props == null) {
                    continue;
                }
               
                switch (((NodeChoice)nodeSequence.elementAt(1)).which) {
                    case 0:
                        NodeChoice nodech = (NodeChoice) ((NodeSequence) ((NodeChoice)nodeSequence.elementAt(1)).choice).elementAt(1);
                        switch (nodech.which) {
                            case 0://Identifier
                                if (saveProps == null) {
                                    continue;
                                }
                                context.getCobol2Java().expression.push(new ExpressionString(saveProps));
                                expressionType = saveProps.getIdentifierType();
                                ClassFile.println(TranslationTable.getInstance().getAssignString(props, null, false,true,true));
                                continue;
                            case 1://True
                                if (props.getLevelNumber() == 88) {
                                    if (props.getValues().get(0).value1 != null) {
                                        expression.push(context.getCobol2Java().formatLiteral(props.getValues().get(0).value1));
                                        ClassFile.println(TranslationTable.getInstance().getAssignString(props.getParent(), null,
                                                props.getParent().getIdentifierType() == Constants.STRING || props.getIdentifierType() == Constants.GROUP,true,true));
                                    }
                                }
                                continue;
                            case 2://False - Not given Enterprise Cobol
                            case 3://On
                            case 4://Of
                            case 5://Literal
                                if (literal == null) {
                                    continue;
                                }
                                context.getCobol2Java().expression.push(context.getCobol2Java().
                                        formatLiteral(literal));
                                ClassFile.println(TranslationTable.getInstance().getAssignString(props, null, false));
                                continue;
                        }
                    case 1:
                        NodeSequence nodeseq = (NodeSequence) ((NodeChoice)nodeSequence.elementAt(1)).choice;
                        String op = null;
                        switch (((NodeChoice) nodeseq.elementAt(0)).which) {
                            case 0:
                                op = "+";
                                break;
                            case 1:
                                op = "-";
                        }
                        if (op == null) {
                            return;
                        }
                        expression.push(new ExpressionString(props));
                        switch (((NodeChoice) nodeseq.elementAt(2)).which) {
                            case 0:
                                if (saveProps == null) {
                                    continue;
                                }
                                doIdOp(saveProps,op);
                                //context.getCobol2Java().expressionType = saveProps.getIdentifierType();
                                ClassFile.println(TranslationTable.getInstance().getAssignString(props, null, false));
                                continue;
                            case 1:
                                if (literal == null) {
                                    continue;
                                }
                                doLiteralOp(formatLiteral(literal).toString(),op);
                               // context.getCobol2Java().expression.push(context.getCobol2Java().
                                        //.toString() + op + new ExpressionString(props).toString());
                                ClassFile.println(TranslationTable.getInstance().getAssignString(props, null, false));
                                continue;
                        }
                }
            }
        }
        //super.visit(n);
    }
    private TreeToCommentFormatter dumper = new TreeToCommentFormatter(false);
    public boolean isLastGotoStatement = false;

    @Override
    public void visit(StatementList n) {
        isLastGotoStatement = false;
        super.visit(n);
    }

    @Override
    public void visit(GobackStatement n) {
        if (returnLine != null) {
            ClassFile.println("return " + returnLine);
        }
    }

    @Override
    public void visit(Statement n) {
        initExpressionType();
        if (n.deadStatement) {
            return;
        }
        isLastGotoStatement = n.nodeChoice.choice instanceof GotoStatement
                || n.nodeChoice.choice instanceof GobackStatement;
        isLastExitStatement = false;
        if (RESConfig.getInstance().isPrintCobolStatementsAsComments()
                || RESConfig.getInstance().isRetainCobolComments()) {
            dumper.startAtNextToken();
            dumper.visit(n);
            if (RESConfig.getInstance().isPrintCobolStatementsAsComments()) {
                ClassFile.println("");
            }
            if (execSql2Java != null) {
                execSql2Java.setStatementNode(n);
            }
        }
        super.visit(n);
    }
    private ExecSql2Java execSql2Java = new ExecSql2Java(this);

    @Override
    public void visit(ExecSqlStatement n) {
        execSql2Java.visit(n);
        //super.visit(n);
    }

    @Override
    public void visit(OpenStatement n) {
        doTry();
        boolean inp = false, op = false, iop = false, ext = false;
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeChoice nodech = (NodeChoice) e.nextElement();
            NodeSequence nodeseq = (NodeSequence) nodech.choice;
            switch (((NodeToken) nodeseq.elementAt(0)).kind) {
                case CobolParserConstants.INPUT:
                    inp = true;
                    break;
                case CobolParserConstants.OUTPUT:
                    op = true;
                    break;
                case CobolParserConstants.INPUT_OUTPUT:
                case CobolParserConstants.I_O:
                    iop = true;
                    break;
                case CobolParserConstants.EXTEND:
                    ext = true;
                    break;
                default:
            }
            for (Enumeration<Node> e2 = ((NodeList) nodeseq.elementAt(1)).elements();
                    e2.hasMoreElements();) {
                e2.nextElement().accept(this);
                if (props == null) {
                    continue;
                }
                if (inp) {
                    ClassFile.println(props.getJavaName1() + ".openInput();");
                }
                if (op) {
                    ClassFile.println(props.getJavaName1() + ".openOutput();");
                }
                if (iop) {
                    ClassFile.println(props.getJavaName1() + ".openIO();");
                }
                if (ext) {
                    ClassFile.println(props.getJavaName1() + ".openExtend();");
                }

            }
            inp = op = iop = ext = false;
        }
        printFileStatus(props);
        ClassFile.backTab();
        ClassFile.println("} catch(java.io.IOException ioe) {");
        printFileStatus(props);
        exceptionPrintStackTrace("ioe");
        String declConditions = props.getDataName();
        if (props.isFileOpenedInput()) {
            declConditions += ",1";
        }
        if (props.isFileOpenedOutput()) {
            declConditions += ",2";
        }
        if (props.isFileOpenedIO()) {
            declConditions += ",3";
        }
        if (props.isFileOpenedExtend()) {
            declConditions += ",4";
        }
        doDeclaratives(declConditions.split(","));
        ClassFile.println("}");
    }

    private void doDeclaratives(String... declConditions) {
        if (!isDeclarative && useConditions != null) {
            for (UseCondition u : useConditions) {
                for (String s : declConditions) {
                    if ((u.openCondition != null && u.openCondition.equalsIgnoreCase(s) && u.isError)) {
                        ClassFile.println("doCobolPerform(" + u.section.getJavaName1() + ",null);");
                        return;
                    }
                }
            }
        }
    }

    @Override
    public void visit(ReadStatement n) {
        n.fileName.accept(this);
        if (props == null) {
            return;
        }
        SymbolProperties fileProps = props;

        if (fileProps.getChildren() == null || fileProps.getChildren().size() <= 0) {
            return;
        }
        SymbolProperties record = null;
        if (fileProps.isIndexedFile()) {
            record = findIndexedRecord(fileProps);
        } else {
            record = fileProps.getChildren().get(0);
        }
        if (record == null || record.getLevelNumber() != 1) {
            return;
        }
        doTry();
        String assign = fileProps.getJavaName1() + ".read";
        if (fileProps.isIndexedFile()) {
            indFile:
            {
                if (n.nodeOptional.present() && fileProps.getOtherData1() == Constants.DYNAMIC_ACCESS) {
                    assign += "Next";
                } else {
                    if (n.nodeOptional3.present()) {
                        ((NodeSequence) n.nodeOptional3.node).elementAt(2).accept(this);
                        if (props != null && record != null) {
                            SymbolProperties pk = (SymbolProperties) fileProps.getOtherData2();
                            String keyStr = record.getJavaName1() + ".primaryKey()";
                            if (pk == null || !(pk.getOffset() == props.getOffset())) {
                                keyStr = TranslationTable.getInstance().convertType(
                                        new ExpressionString(props), Constants.STRING, props.getIdentifierType()).toString();
                                keyStr += "," + String.valueOf(props.getOffset()) + "," + String.valueOf(props.getLength());
                            } else if (pk.getLength() != props.getLength()) {
                                keyStr += "," + String.valueOf(props.getLength());
                            }
                            assign += "(" + keyStr + ")";
                            break indFile;
                        }
                    }
                }
                assign += "()";
            }
        } else {
            if (record.is01Group()) {
                assign = assign + "(" + record.getJavaName1();
            } else {
                assign = assign + "(super.getProgram().get()," + record.getOffset() + ',' + record.getLength();
            }
            if (fileProps.getOtherData2() != null) {
                assign += ","
                        + NameUtil.getJavaName((SymbolProperties) fileProps.getOtherData2(), false);
            }
            assign += ")";
        }
        ClassFile.println(assign + ";");
        if (n.nodeOptional2.present()) {
            props = null;
            n.nodeOptional2.accept(this);
            if (props != null) {
                ClassFile.println(TranslationTable.getInstance().getAssignString(props, record, false));
            }
        }
        printFileStatus(fileProps);
        n.nodeOptional5.accept(this);
        n.nodeOptional7.accept(this);
        ClassFile.backTab();
        String declConditions = fileProps.getDataName();
        if (fileProps.isFileOpenedInput()) {
            declConditions += ",1";
        }
        if (fileProps.isFileOpenedIO()) {
            declConditions += ",3";
        }
        ClassFile.println("} catch(java.io.EOFException ioe) {");
        ClassFile.tab();
        exceptionPrintStackTrace("ioe");
        printFileStatus(fileProps);
        if (!n.nodeOptional6.present()) {
            doDeclaratives(declConditions.split(","));
        } else {
            n.nodeOptional6.accept(this);
        }
        ClassFile.backTab();
        ClassFile.println("} catch(InvalidKeyException ike) {");
        ClassFile.tab();
        exceptionPrintStackTrace("ike");
        printFileStatus(fileProps);
        if (n.nodeOptional4.present()) {
            n.nodeOptional4.accept(this);
        } else {
            doDeclaratives(declConditions.split(","));
        }
        ClassFile.backTab();
        ClassFile.println("} catch(java.io.IOException ioe) {");
        ClassFile.tab();
        exceptionPrintStackTrace("ioe");
        doDeclaratives(declConditions.split(","));
        ClassFile.backTab();
        ClassFile.println("}");
    }

    private SymbolProperties findIndexedRecord(SymbolProperties fileProps) {
        SymbolProperties record = null;
        for (SymbolProperties k : fileProps.getChildren()) {
            if (!k.isIndexedFileRecord()) {
                continue;
            }
            record = k;
            break;
        }
        return record;
    }
    private SymbolProperties saveProps = null;

    @Override
    public void visit(WriteStatement n) {
        n.recordName.accept(this);
        if (props == null) {
            return;
        }
        SymbolProperties fileProps = props.getParent();
        saveProps = props;
        if (!fileProps.isFile()) {
            return;
        }
        doTry();
        if (n.nodeOptional.present()) {
            saveProps = props;
            props = null;
            literal = null;
            n.nodeOptional.accept(this);
            if (props != null) {
                ClassFile.println(TranslationTable.getInstance().getAssignString(saveProps, props, false));
            } else {
                literal = formatLiteral(literal);
                expression.push(literal.toString());
                ClassFile.println(TranslationTable.getInstance().getAssignString(saveProps, null, false));
            }
        }
        props = saveProps;
        if (fileProps.isIndexedFile()) {
            ClassFile.println(fileProps.getJavaName1() + ".write();");
        } else {
            if (n.nodeOptional1.present() && ((AdvancingPhrase) n.nodeOptional1.node).nodeChoice.which == 1) {
                n.nodeOptional1.accept(this);
            }
            if (n.nodeOptional.present()) {
                props = null;
                literal = null;
                n.nodeOptional.accept(this);
            }
            if (props != null || literal != null) {
                String assign;
                if (props == null) {
                    assign = formatLiteral(literal).toString();
                    assign = TranslationTable.getInstance().convertType(assign, Constants.GROUP, expressionType);
                } else {
                    assign = new ExpressionString(props).toString();
                    assign = TranslationTable.getInstance().convertType(assign, Constants.GROUP, props.getIdentifierType());
                }
                ClassFile.println(fileProps.getJavaName1() + ".write(" + assign + ");");
            }
            if (n.nodeOptional1.present() && ((AdvancingPhrase) n.nodeOptional1.node).nodeChoice.which == 0) {
                n.nodeOptional1.accept(this);
            }
        }
        printFileStatus(fileProps);
        n.nodeOptional5.accept(this);
        String declConditions = fileProps.getDataName();
        if (fileProps.isFileOpenedOutput()) {
            declConditions += ",2";
        }
        if (fileProps.isFileOpenedIO()) {
            declConditions += ",3";
        }
        if (fileProps.isFileOpenedExtend()) {
            declConditions += ",4";
        }

        ClassFile.backTab();
        ClassFile.println("} catch(InvalidKeyException ike) {");
        ClassFile.tab();
        exceptionPrintStackTrace("ike");
        printFileStatus(fileProps);
        if (!n.nodeOptional4.present()) {
            doDeclaratives(declConditions.split(","));
        } else {
            n.nodeOptional4.accept(this);
        }
        ClassFile.backTab();
        ClassFile.println("} catch(java.io.IOException ioe) {");
        ClassFile.tab();
        exceptionPrintStackTrace("ioe");
        printFileStatus(fileProps);
        doDeclaratives(declConditions.split(","));
        ClassFile.backTab();
        ClassFile.println("}");
    }

    @Override
    public void visit(AdvancingPhrase n) {
        if (saveProps == null) {
            return;
        }
        switch (n.nodeChoice1.which) {
            case 0:
                ClassFile.println(saveProps.getParent().getJavaName1() + ".advancePage();");
                break;
            case 1:
                props = null;
                n.nodeChoice1.choice.accept(this);
                if (props != null) {
                    expression.push(new ExpressionString(props).toString());
                    expressionType = props.getIdentifierType();
                } else {
                    expression.push(formatLiteral(literal).toString());
                }
                ClassFile.println(saveProps.getParent().getJavaName1() + ".advanceLines("
                        + TranslationTable.getInstance().convertType(expression.pop3(), Constants.INTEGER, expressionType) + ");");
                props = saveProps;
                break;
            case 2:
                n.nodeChoice1.accept(this);
                literal = formatLiteral(literal);
                ClassFile.println(saveProps.getParent().getJavaName1() + ".advanceLines(" + literal.toString()
                        + ");");
                break;
        }
    }

    @Override
    public void visit(RewriteStatement n) {

        n.recordName.accept(this);
        if (props == null) {
            return;
        }
        SymbolProperties fileProps = props.getParent();
        props = fileProps.getChildren().get(0);
        if (!fileProps.isFile()) {
            return;
        }
        if (n.nodeOptional.present()) {
            props = null;
            literal = null;
            n.nodeOptional.accept(this);
            if (props == null && literal == null) {
                return;
            }
        }
        doTry();
        String assign;
        assign = "";
        if (fileProps.isIndexedFile()) {
            assign = "";
            if (!fileProps.getChildren().get(0).getDataName().equalsIgnoreCase(props.getDataName())) {
                expression.push(new ExpressionString(props));
                ClassFile.println(TranslationTable.getInstance().getAssignString(fileProps.getChildren().get(0), null, false));
            }
        } else if (props == null) {
            assign = formatLiteral(literal).toString();
            assign = TranslationTable.getInstance().convertType(assign, Constants.GROUP, expressionType);
        } else {
            assign = new ExpressionString(props).toString();
            assign = TranslationTable.getInstance().convertType(assign, Constants.GROUP, props.getIdentifierType());
        }
        ClassFile.println(fileProps.getJavaName1() + ".rewrite(" + assign + ");");
        printFileStatus(fileProps);
        n.nodeOptional2.accept(this);
        ClassFile.backTab();
        String declConditions = fileProps.getDataName();
        if (fileProps.isFileOpenedOutput()) {
            declConditions += ",2";
        }
        if (fileProps.isFileOpenedIO()) {
            declConditions += ",3";
        }
        if (props.isFileOpenedExtend()) {
            declConditions += ",4";
        }
        ClassFile.println("} catch(InvalidKeyException ike) {");
        ClassFile.tab();
        exceptionPrintStackTrace("ike");
        printFileStatus(fileProps);
        if (!n.nodeOptional1.present()) {
            doDeclaratives(declConditions.split(","));
        } else {
            n.nodeOptional1.accept(this);
        }
        ClassFile.backTab();
        ClassFile.println("} catch(java.io.IOException ioe) {");
        ClassFile.tab();
        exceptionPrintStackTrace("ioe");
        printFileStatus(fileProps);
        doDeclaratives(declConditions.split(","));
        ClassFile.backTab();
        ClassFile.println("}");
    }

    @Override
    public void visit(StartStatement n) {
        doTry();
        n.fileName.accept(this);
        if (props == null) {
            return;
        }
        SymbolProperties fileProps = props;
        props = null;
        if (n.nodeOptional.present()) {
            SymbolProperties record = findIndexedRecord(fileProps);
            ((NodeSequence) n.nodeOptional.node).elementAt(3).accept(this);
            if (props != null && record != null) {
                SymbolProperties pk = (SymbolProperties) fileProps.getOtherData2();
                String keyStr = record.getJavaName1() + ".primaryKey()";
                if (pk == null || !(pk.getOffset() == props.getOffset())) {
                    keyStr = TranslationTable.getInstance().convertType(
                            new ExpressionString(props), Constants.STRING, props.getIdentifierType()).toString();
                    keyStr += "," + String.valueOf(props.getOffset()) + "," + String.valueOf(props.getLength());
                } else if (pk.getLength() != props.getLength()) {
                    keyStr += "," + String.valueOf(props.getLength());
                }
                NodeChoice nodechoice = (NodeChoice) ((NodeSequence) n.nodeOptional.node).elementAt(2);
                switch (nodechoice.which) {
                    case 0:
                    case 1:
                        ClassFile.println(fileProps.getJavaName1() + ".startEq(" + keyStr + ");");
                        break;
                    case 2://ge
                    case 7://>=
                    case 5://Not LESS
                    case 6://Not <
                        ClassFile.println(fileProps.getJavaName1() + ".startGe(" + keyStr + ");");
                        break;
                    case 3://gt
                    case 4://>
                        ClassFile.println(fileProps.getJavaName1() + ".startGt(" + keyStr + ");");
                        break;
                    default:
                        ClassFile.println(fileProps.getJavaName1() + ".start();");
                }
            } else {
                ClassFile.println(fileProps.getJavaName1() + ".start();");
            }
        } else {
            ClassFile.println(fileProps.getJavaName1() + ".start();");
        }

        printFileStatus(fileProps);
        String declConditions = fileProps.getDataName();
        if (fileProps.isFileOpenedOutput()) {
            declConditions += ",2";
        }
        if (fileProps.isFileOpenedIO()) {
            declConditions += ",3";
        }
        if (fileProps.isFileOpenedExtend()) {
            declConditions += ",4";
        }
        ClassFile.backTab();
        ClassFile.println("} catch(InvalidKeyException e) {");
        ClassFile.tab();
        exceptionPrintStackTrace("e");
        printFileStatus(fileProps);
        if (n.nodeOptional1.present()) {
            n.nodeOptional1.accept(this);
        } else {
            doDeclaratives(declConditions.split(","));
        }
        ClassFile.backTab();
        ClassFile.println("} catch(java.io.IOException e) {");
        ClassFile.tab();
        exceptionPrintStackTrace("e");
        printFileStatus(fileProps);
        ClassFile.backTab();
        ClassFile.println("}");

    }

    @Override
    public void visit(DeleteStatement n) {
        doTry();
        n.fileName.accept(this);
        if (props == null) {
            return;
        }
        String arg = "";
        if (!props.isIndexedFile()) {
            arg = NameUtil.getJavaName((SymbolProperties) props.getOtherData2(), false);
        }
        ClassFile.println(props.getJavaName1() + ".delete(" + arg + ");");
        n.nodeOptional2.accept(this);
        printFileStatus(props);
        String declConditions = props.getDataName();
        if (props.isFileOpenedOutput()) {
            declConditions += ",2";
        }
        if (props.isFileOpenedIO()) {
            declConditions += ",3";
        }
        if (props.isFileOpenedExtend()) {
            declConditions += ",4";
        }
        ClassFile.backTab();
        ClassFile.println("} catch(InvalidKeyException e) {");
        ClassFile.tab();
        exceptionPrintStackTrace("e");
        printFileStatus(props);
        if (n.nodeOptional1.present()) {
            n.nodeOptional1.accept(this);
        } else {
            doDeclaratives(declConditions.split(","));
        }
        ClassFile.backTab();
        ClassFile.println("} catch(java.io.IOException e) {");
        ClassFile.tab();
        exceptionPrintStackTrace("e");
        printFileStatus(props);
        ClassFile.backTab();
        ClassFile.println("}");
    }

    private void printFileStatus(SymbolProperties fileProps) {

        if (fileProps.getFileStatus() == null || fileProps.getFileStatus().size() <= 0) {
            return;
        }
        SymbolProperties fs = null;
        doit:
        {
            for (SymbolProperties s : fileProps.getFileStatus()) {
                if (findProgram(s).equals(SymbolTable.getScope().getCurrentProgram())) {
                    fs = s;
                    break doit;
                }
            }
            return;
        }
        fs.setIdentifierType(fs.getJavaType().getType());
        expression.push(new ExpressionString(fileProps.getJavaName1() + ".getFileStatus()", expressionType = Constants.STRING));
        doMove(getExpression(), fs);
    }

    @Override
    public void visit(CloseStatement n) {
        boolean doExceptions = false;

        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            ((NodeSequence) e.nextElement()).elementAt(0).accept(this);
            if (props != null) {
                if (!doExceptions) {
                    doTry();
                }
                doExceptions = true;
                ClassFile.println(props.getJavaName1() + ".close();");
                printFileStatus(props);
            }
        }
        if (doExceptions) {
            ClassFile.backTab();
            ClassFile.println("} catch(java.io.IOException ioe) {");
            ClassFile.tab();
            exceptionPrintStackTrace("ioe");
            printFileStatus(props);
            String declConditions = props.getDataName();
            if (props.isFileOpenedInput()) {
                declConditions += ",1";
            }
            if (props.isFileOpenedOutput()) {
                declConditions += ",2";
            }
            if (props.isFileOpenedIO()) {
                declConditions += ",3";
            }
            if (props.isFileOpenedExtend()) {
                declConditions += ",4";
            }
            doDeclaratives(declConditions.split(","));
            ClassFile.backTab();
            ClassFile.println("}");
        }
    }

    @Override
    public void visit(FileName n) {
        props = SymbolTable.getScope().lookup(n.cobolWord.nodeToken.tokenImage, SymbolConstants.FILE);
    }

    public void reportError(Node n, String msg) {
        System.out.println("@CobolSourceFile(\"" + ((RESNode) n).sourceFile + "\"," + ((RESNode) n).line + "):" + msg);
        System.exit(0);
    }

    public void reportError(Node n, String msg, boolean exit) {
        System.out.println("@CobolSourceFile(\"" + ((RESNode) n).sourceFile + "\"," + ((RESNode) n).line + "):" + msg);
        if (exit) {
            System.exit(0);
        }
    }

    public SymbolProperties getCurrentProgram() {
        return SymbolTable.getScope().getCurrentProgram();
    }

    public String getAssignString(TranslationTable translationTable,
            SymbolProperties lhs, SymbolProperties rhs) {
        return translationTable.getAssignString(lhs, rhs, false);
    }

    public void doTail() {
        initializeSymbols();
        ClassFile.backTab();
    }

    @Override
    public void visit(CallStatement n) {
        doTry();
        if (idOrLiteralList != null) {
            idOrLiteralList.clear();
        } else {
            idOrLiteralList = new ArrayList<ExpressionString>();
        }
        StringBuilder line = new StringBuilder("doCobolCall(");
        bLine.push(new StringBuilder());
        cLine.push(new StringBuilder());
        callParmIdx = 0;
        n.nodeChoice.choice.accept(this);
        switch (n.nodeChoice.which) {
            case 0:
                expression.push(new ExpressionString(props).toString());
                expressionType = props.getIdentifierType();
                break;
            case 1:
                expression.push(formatLiteral(literal).toString());
                break;
        }
        line.append(TranslationTable.getInstance().
                convertType(expression.pop3(), Constants.STRING, expressionType));
        n.nodeOptional.accept(this);
        for (Iterator<ExpressionString> e = idOrLiteralList.iterator(); e.hasNext();) {
            line.append(',');
            line.append(e.next().toString());
        }
        line.append(");");
        ClassFile.println(line.toString());
        bLine.peek().append(cLine.peek().toString());
        ClassFile.println(bLine.peek().toString());
        n.nodeOptional3.accept(this);
        ClassFile.backTab();
        bLine.pop();
        cLine.pop();
        ClassFile.println("} catch(Exception e) {");
        ClassFile.tab();
        exceptionPrintStackTrace("e");
        n.nodeOptional1.accept(this);
        n.nodeOptional2.accept(this);
        ClassFile.backTab();
        ClassFile.println("}");
    }

    @Override
    public void visit(CancelStatement n) {
        aLine.push(new StringBuilder());
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            String exprString = null;
            props = null;
            literal = null;
            e.nextElement().accept(this);
            if (props != null) {
                exprString = TranslationTable.getInstance().convertType(
                        NameUtil.getJavaName(props, false), Constants.STRING, props.getIdentifierType());
            } else {
                literal = formatLiteral(literal);
                exprString = TranslationTable.getInstance().convertType(
                        literal.toString(), Constants.STRING, expressionType);
            }
            if (aLine.peek().length() > 0) {
                aLine.peek().append(',');
            }
            aLine.peek().append(exprString);
        }
        if (aLine.peek().length() > 0) {
            ClassFile.println("doCobolCancel(" + aLine.peek().toString() + ");");
        }
        aLine.pop();
    }

    @Override
    public void visit(CallByContentArgs n) {
        switch (n.nodeChoice.which) {
            case 0:
                n.nodeChoice.choice.accept(this);
                if (props == null) {
                    idOrLiteralList.add(new ExpressionString("null"));
                } else if (((NodeOptional) ((NodeSequence) n.nodeChoice.choice).elementAt(0)).present()) {
                    idOrLiteralList.add(new ExpressionString(String.valueOf(props.getLength())));
                } else {
                    idOrLiteralList.add(new ExpressionString(new ExpressionString(props).toString()));
                }
                break;
            case 1:
                idOrLiteralList.add(new ExpressionString("null"));
                break;
            case 2:
                n.nodeChoice.choice.accept(this);
                idOrLiteralList.add(new ExpressionString(formatLiteral(literal).toString()));
        }
        callParmIdx++;
    }

    @Override
    public void visit(CallByReferenceArgs n) {

        switch (n.nodeChoice.which) {
            case 0:
            case 2:
                n.nodeChoice.choice.accept(this);
                if (props == null) {
                    idOrLiteralList.add(new ExpressionString("null"));
                } else {
                    idOrLiteralList.add(new ExpressionString(props));
                }
                expression.push("__get" + SymbolConstants.getSQL(props.getIdentifierType()) + "Result("
                        + String.valueOf(callParmIdx) + ")");
                expressionType = props.getIdentifierType();
                if (props.isAChildHasDependingOn() || (props.isOccurs() && props.getDependingOnOccurs() != null)) {
                    cLine.peek().append(TranslationTable.getInstance().getAssignString(props, null, false, true, true));
                } else {
                    bLine.peek().append(TranslationTable.getInstance().getAssignString(props, null, false, true, true));
                }
                break;
            case 1:
                idOrLiteralList.add(new ExpressionString("null"));
                break;
        }
        callParmIdx++;
    }
    private HashMap<Integer, ExpressionString> replacingValues;

    @Override
    public void visit(InitializeStatement n) {

        replacingValues = new HashMap<Integer, ExpressionString>();
        if (n.nodeOptional.present()) {
            NodeSequence nodeseq = (NodeSequence) n.nodeOptional.node;
            for (Enumeration<Node> e = ((NodeList) nodeseq.elementAt(1)).elements(); e.hasMoreElements();) {
                props = null;
                literal = null;
                ExpressionString replacingVal = null;
                NodeSequence nodeseq2 = (NodeSequence) e.nextElement();
                nodeseq2.elementAt(3).accept(this);
                if (props != null) {
                    replacingVal = new ExpressionString(props);
                } else if (literal != null) {
                    replacingVal = formatLiteral(literal);
                }
                if (replacingVal == null) {
                    continue;
                }
                replacingValues.put(((NodeChoice) nodeseq2.elementAt(0)).which, replacingVal);
            }
        }
        aLine.push(new StringBuilder());
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            e.nextElement().accept(this);
            if (props == null) {
                continue;
            }
            if (props.isOccurs() && props.getIndexesWorkSpace() == null) {
                reportError(n, "Warning: A table may not be directly specified with INITIALIZE verb without subscript.", false);
            }
            int i = 0;
            if (props.isOccurs() || props.isAParentInOccurs() && props.getIndexesWorkSpace() == null) {
                for (SymbolProperties occursPar : props.getOccursParents()) {
                    i++;
                    if (aLine.peek().length() > 0) {
                        aLine.peek().append(',');
                    }
                    String idx = "idx" + String.valueOf(i + 1);
                    aLine.peek().append(idx);
                    ClassFile.println("for(int " + idx + "=1;" + idx + "<=" + String.valueOf(occursPar.getMaxOccurs()) + ";++" + idx + ") {");
                    ClassFile.tab();
                }
            }
            doInitializeVerb(props, i);
            if (props.isOccurs() || props.isAParentInOccurs()) {
                for (i = 0; i < props.getOccursParents().size(); ++i) {
                    ClassFile.backTab();
                    ClassFile.println("}");
                }
            }
        }
        aLine.pop();

    }

    private void doInitializeVerb(ArrayList<SymbolProperties> a, int idx) {
        if (a == null || a.size() <= 0) {
            return;
        }
        int saveIdx = idx, i = idx;
        for (SymbolProperties ch : a) {
            if (ch.isOccurs()) {
                for (; i < ch.getOccursParents().size(); ++i) {
                    SymbolProperties occursPar = ch.getOccursParents().get(i);
                    if (aLine.peek().length() > 0) {
                        aLine.peek().append(',');
                    }
                    String ix = "idx" + String.valueOf(i + 1);
                    aLine.peek().append(ix);
                    ClassFile.println("for(int " + ix + "=1;" + ix + "<="
                            + String.valueOf(occursPar.getMaxOccurs()) + ";++" + ix + ") {");
                    ClassFile.tab();

                }
            }
            if (!ch.isElementData()) {
                doInitializeVerb(ch.getChildren(), i);
            } else {
                doInitializeVerb(ch, i);
            }
            if (ch.isOccurs()) {
                for (; i > saveIdx; --i) {
                    if (aLine.peek().length() > 0) {
                        int temp;
                        aLine.peek().delete((((temp = aLine.peek().lastIndexOf(",")) < 0) ? 0 : temp), aLine.peek().length());
                    }
                    ClassFile.backTab();
                    ClassFile.println("}");
                }
            }
        }
    }

    private void doInitializeVerb(SymbolProperties p, int idx) {
        int saveIdx = idx, i = idx;
        if (p.isOccurs()) {
            for (; i < p.getOccursParents().size(); ++i) {
                SymbolProperties occursPar = p.getOccursParents().get(i);
                if (aLine.peek().length() > 0) {
                    aLine.peek().append(',');
                }
                String ix = "idx" + String.valueOf(i + 1);
                aLine.peek().append(ix);
                ClassFile.println("for(int " + ix + "=1;" + ix + "<="
                        + String.valueOf(occursPar.getMaxOccurs()) + ";++" + ix + ") {");
                ClassFile.tab();
            }
        }
        if (!p.isElementData()) {
            doInitializeVerb(p.getChildren(), i);
        } else {
            p.setIndexesWorkSpace(new ArrayList<String>());
            p.getIndexesWorkSpace().add(aLine.peek().toString());
            switch (p.getIdentifierType()) {
                case Constants.CHAR:
                    expression.push(new ExpressionString("\' \'", expressionType = Constants.CHAR));
                    ClassFile.println(TranslationTable.getInstance().getAssignString(p, null, false, true));
                    break;
                case Constants.BYTE:
                case Constants.SHORT:
                case Constants.INTEGER:
                case Constants.LONG:
                    expression.push(new ExpressionString("0", expressionType = Constants.INTEGER));
                    ClassFile.println(TranslationTable.getInstance().getAssignString(p, null, false, true));
                    break;
                case Constants.FLOAT:
                case Constants.DOUBLE:
                    expression.push(new ExpressionString("0.00", expressionType = Constants.FLOAT));
                    ClassFile.println(TranslationTable.getInstance().getAssignString(p, null, false, true));
                    break;
                case Constants.BIGDECIMAL:
                    expression.push(new ExpressionString("BigDecimal.ZERO", expressionType = Constants.BIGDECIMAL));
                    ClassFile.println(TranslationTable.getInstance().getAssignString(p, null, false, true));
                    break;
                case Constants.STRING:
                    expression.push(new ExpressionString("\" \"", expressionType = Constants.STRING));
                    ClassFile.println(TranslationTable.getInstance().getAssignString(p, null, false, true));
                    break;
                case Constants.GROUP:
                    if (p.hasChildren()) {
                        doInitializeVerb(p.getChildren(), idx);
                    }
                    break;
                default:
                    ClassFile.println(NameUtil.getJavaName(p, true).replace("%0", "null") + ';');
                    break;
            }
        }
        if (p.isOccurs()) {
            for (; i > saveIdx; --i) {
                if (aLine.peek().length() > 0) {
                    int temp;
                    aLine.peek().delete((((temp = aLine.lastIndexOf(",")) < 0) ? 0 : temp), aLine.peek().length());
                }
                ClassFile.backTab();
                ClassFile.println("}");
            }
        }
    }

    @Override
    public void visit(EvaluateStatement n) {

        if (evaluateValue != null) {
            evaluateValue.clear();
        }
        n.evaluateValue.accept(this);
        n.nodeListOptional.accept(this);
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {//WHEN...ALSO..Statement()+
            NodeSequence node = (NodeSequence) e.nextElement();
            evaluateValueIndex = 0;
            aLine.push(new StringBuilder());
            aLine.peek().append("if(");
            for (Enumeration<Node> e2 = ((NodeList) node.elementAt(0)).elements(); e2.hasMoreElements();) {//WHEN
                NodeSequence nodeseq = (NodeSequence) e2.nextElement();
                nodeseq.elementAt(2).accept(this);
                if (((NodeListOptional) nodeseq.elementAt(3)).present()) {//ALSO LIST
                    for (Enumeration<Node> e3 = ((NodeListOptional) nodeseq.elementAt(3)).elements(); e3.hasMoreElements();) {
                        aLine.peek().append("&&");
                        evaluateValueIndex++;
                        e3.nextElement().accept(this);
                    }
                }
                if (e2.hasMoreElements()) {
                    aLine.peek().append("||");
                }
            }
            aLine.peek().append(") {");
            ClassFile.println(aLine.peek().toString());
            ClassFile.tab();
            node.elementAt(1).accept(this);
            ClassFile.backTab();
            if (e.hasMoreElements()) {
                ClassFile.println("} else ");
            } else {
                ClassFile.println("}");
            }
            aLine.pop();
        }
        if (n.nodeOptional.present()) {
            ClassFile.println("else {");
            ClassFile.tab();
            n.nodeOptional.accept(this);
            ClassFile.backTab();
            ClassFile.println("}");
        }

    }
    private ArrayList<ExpressionString> evaluateValue = null;
    private int evaluateValueIndex = 0;

    @Override
    public void visit(EvaluatePhrase n) {

        switch (n.nodeChoice.which) {
            case 0:
                aLine.peek().append("true");
                return;
            case 3:
                aLine.peek().append("");
                break;
            case 4:
                aLine.peek().append("!");
                break;
            case 2:
                doReverseCondition = false;
                n.nodeChoice.choice.accept(this);
                aLine.peek().append(condition.pop()).append("==");
                break;
            case 1:
                StringBuilder subphrase = new StringBuilder();
                NodeSequence nodeSeq = (NodeSequence) n.nodeChoice.choice;
                ((NodeOptional) (nodeSeq.elementAt(0))).present();//Not
                NodeChoice nodech1 = ((NodeChoice) (nodeSeq.elementAt(1)));
                nodech1.accept(this);
                switch (nodech1.which) {
                    case 0:
                        expressionType = props.getIdentifierType();
                        expression.push(new ExpressionString(props));
                        break;
                    case 1:
                        expression.push(formatLiteral(literal).toString());
                        break;
                    case 2:
                }
                String top = "";
                ExpressionString expr1 = getExpression();
                if (((NodeOptional) nodeSeq.elementAt(2)).present()) {
                    expression.push(appendEvaluateValue());
                    top = TranslationTable.getInstance().doCondition(
                            TranslationTable.LE_CONDITION,
                            expr1, getExpression(), false);
                    ;
                    subphrase.append(top).append("&&");
                    NodeSequence nodeseq2 = (NodeSequence) ((NodeOptional) nodeSeq.elementAt(2)).node;
                    NodeChoice nodech2 = ((NodeChoice) (nodeseq2.elementAt(1)));
                    nodech2.accept(this);
                    switch (nodech2.which) {
                        case 0:
                            expressionType = props.getIdentifierType();
                            expression.push(new ExpressionString(props));
                            break;
                        case 1:
                            expression.push(formatLiteral(literal).toString());
                            break;
                        case 2:
                    }
                    expr1 = getExpression();
                    expression.push(appendEvaluateValue());
                    top = TranslationTable.getInstance().doCondition(
                            TranslationTable.GE_CONDITION,
                            expr1, getExpression(), false);
                    subphrase.append(top);
                } else {
                    if (appendEvaluateValue().equals("true")) {
                        subphrase.append(expr1.toString());
                    } else if (appendEvaluateValue().equals("false")) {
                        subphrase.append('!').append(expr1.toString());
                    } else {
                        expression.push(appendEvaluateValue());
                        top = TranslationTable.getInstance().doCondition(TranslationTable.EQ_CONDITION,
                                expr1, getExpression(), false);
                        subphrase.append(top);
                    }
                }
                if (((NodeOptional) (nodeSeq.elementAt(0))).present()) {
                    aLine.peek().append("!(").append(subphrase).append(')');
                } else {
                    aLine.peek().append(subphrase);
                }
                return;
        }
        aLine.peek().append(appendEvaluateValue());
    }

    private String appendEvaluateValue() {
        if (evaluateValueIndex >= 0 && evaluateValueIndex < evaluateValue.size()) {


            // if (evaluateValue.get(evaluateValueIndex) instanceof ExpressionString) {
            expressionType = evaluateValue.get(evaluateValueIndex).type;
            return evaluateValue.get(evaluateValueIndex).toString();
            // }
            // return (String) evaluateValue.get(evaluateValueIndex);
        }
        return "0";
    }

    @Override
    public void visit(EvaluateValue n) {
        if (evaluateValue == null) {
            evaluateValue = new ArrayList<ExpressionString>();
        }
        n.nodeChoice.accept(this);

        switch (n.nodeChoice.which) {
            case 2:
                literal = new ExpressionString(expression.pop());
                literal.type = expressionType;
                evaluateValue.add(literal);
                break;
            case 0:
                evaluateValue.add(new ExpressionString(props));
                break;
            case 3:
                evaluateValue.add(formatLiteral(literal));
                break;
            case 1:
                evaluateValue.add(new ExpressionString(condition.pop()));
                ;
                break;
            case 4:
                evaluateValue.add(new ExpressionString("true"));
                break;
            case 5:
                evaluateValue.add(new ExpressionString("false"));
                break;
        }
        //super.visit(n);
    }

    public SymbolProperties getLastVisitedIdentifer() {
        return props;
    }

    public void setLastVisitedIdentifer(SymbolProperties props) {
        this.props = props;
    }
    private static RESContext context = null;

    public static Cobol2Java getInstance(RESContext ctx) {
        if (thiz == null) {
            context = ctx;
            thiz = new Cobol2Java();
        }
        return thiz;
    }

    public static void clear() {
        thiz = null;
        context = null;
    }

    @Override
    public void visit(UnstringStatement n) {
        if (n.nodeOptional3.present() || n.nodeOptional4.present()) {
            doTry();
        }
        n.identifier.accept(this);
        if (props == null) {
            return;
        }
        aLine.push(new StringBuilder());
        bLine.push(new StringBuilder());
        aLine.peek().append("new CobolString(").append(new ExpressionString(props).toString()).append(')');
        if (n.nodeOptional.present()) {
            props = null;
            literal = null;
            NodeSequence nodeseq = (NodeSequence) n.nodeOptional.node;
            nodeseq.elementAt(3).accept(this);
            bLine.peek().append('.').append("delimitedBy(");
            if (props != null) {
                bLine.peek().append(new ExpressionString(props).toString());
            } else {
                bLine.peek().append(formatLiteral(literal).toString());
            }
            if (((NodeOptional) nodeseq.elementAt(2)).present()) {
                bLine.peek().append(",true");
            }
            bLine.peek().append(')');
            NodeListOptional orList = (NodeListOptional) nodeseq.elementAt(4);
            if (orList.present()) {
                for (Enumeration<Node> e = orList.elements(); e.hasMoreElements();) {
                    NodeSequence nodeseq2 = (NodeSequence) e.nextElement();
                    nodeseq2.elementAt(2).accept(this);
                    bLine.peek().append('.').append("delimitedBy(");
                    if (props != null) {
                        bLine.peek().append(new ExpressionString(props).toString());
                    } else {
                        bLine.peek().append(formatLiteral(literal).toString());
                    }
                    if (((NodeOptional) nodeseq2.elementAt(1)).present()) {
                        bLine.peek().append(",true");
                    }
                    bLine.peek().append(')');
                }
            }
        }
        aLine.peek().append(bLine.peek()).append(".unString();");
        String tempVar = "temp" + String.valueOf(SymbolTable.tempVariablesMark++);
        aLine.peek().insert(0, "CobolString " + tempVar + " = ");
        ClassFile.println(aLine.peek().toString());
        int i = 0;
        for (Enumeration<Node> e2 = n.nodeList.elements(); e2.hasMoreElements();) {
            NodeSequence nodeseq3 = (NodeSequence) e2.nextElement();
            nodeseq3.elementAt(0).accept(this);
            bLine.push(new StringBuilder());
            expressionType = Constants.STRING;
            expression.push(bLine.peek().append(tempVar).append(".getUnString()").toString());
            ClassFile.println(TranslationTable.getInstance().getAssignString(props, null, false));
            NodeOptional opt = (NodeOptional) nodeseq3.elementAt(1);
            if (opt.present()) {
                bLine.push(new StringBuilder());
                opt.accept(this);
                expression.push(bLine.peek().append(tempVar).append(".getUnStringDelimiter()").toString());
                ClassFile.println(TranslationTable.getInstance().getAssignString(props, null, false));
            }
            opt = (NodeOptional) nodeseq3.elementAt(2);
            if (opt.present()) {
                expressionType = Constants.INTEGER;
                bLine.push(new StringBuilder());
                opt.accept(this);
                expression.push(bLine.peek().append(tempVar).append(".getUnStringCount()").toString());
                ClassFile.println(TranslationTable.getInstance().getAssignString(props, null, false));
            }
            i++;
        }
        if (n.nodeOptional1.present()) {
            bLine.push(new StringBuilder());
            bLine.peek().append(tempVar).append(".getUnStringPointer()");
            n.nodeOptional1.accept(this);
            expression.push(bLine.peek().toString());
            expressionType = Constants.INTEGER;
            ClassFile.println(TranslationTable.getInstance().getAssignString(props, null, false));
        }
        bLine.push(new StringBuilder());
        bLine.peek().append(tempVar).append(".getUnStringTally()");
        if (n.nodeOptional2.present()) {
            n.nodeOptional2.accept(this);
            expression.push(bLine.peek().toString());
            expressionType = Constants.INTEGER;
            ClassFile.println(TranslationTable.getInstance().getAssignString(props, null, false));
        }

        aLine.pop();
        bLine.pop();

        if (n.nodeOptional3.present() || n.nodeOptional4.present()) {
            //ClassFile.println("__assertException();");
            if (n.nodeOptional4.present()) {//Not On OverFlow
                n.nodeOptional4.accept(this);
            }
            ClassFile.backTab();
            ClassFile.println("} catch(OverflowException ofe) {");
            ClassFile.tab();
            exceptionPrintStackTrace("ofe");
            if (n.nodeOptional3.present()) {//On OverFlow
                n.nodeOptional3.accept(this);
            }
            ClassFile.backTab();
            ClassFile.println("}");
        }
    }

    @Override
    public void visit(SearchStatement n) {
        n.qualifiedDataName.accept(this);
        if (!props.isOccurs()) {
            reportError(n, "Search Statement is valid only on tables with Occurs clause.");
        }
        if (props.getMajorIndex() == null) {
            reportError(n, "Search Statement is valid only on tables with INDEXED BY.");
        }
        SymbolProperties table = props;
        props = null;
        n.nodeOptional1.accept(this);
        SymbolProperties varying = props;
        ClassFile.println("do {");
        ClassFile.tab();
        ClassFile.println("if(" + NameUtil.getJavaName(table.getMajorIndex(), false) + ">"
                + table.getMaxOccurs() + ") {");
        ClassFile.tab();
        n.nodeOptional2.accept(this);
        if (!isLastGotoStatement) {
            ClassFile.println(" break;");
        }
        ClassFile.backTab();
        ClassFile.println("}");
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeSequence nodeseq = (NodeSequence) e.nextElement();
            nodeseq.elementAt(1).accept(this);
            ClassFile.println("if(" + condition.pop() + ") {");
            ClassFile.tab();
            NodeChoice nodech = (NodeChoice) nodeseq.elementAt(2);
            if (nodech.which == 0) {
                nodech.accept(this);
                if (!isLastGotoStatement) {
                    ClassFile.println(" break;");
                }
            } else {
                ClassFile.println(" break;");
            }
            ClassFile.backTab();
            ClassFile.println("}");
        }
        ClassFile.println(getIncrement(table.getMajorIndex()) + ";");
        if (varying != null && !varying.equals(table.getMajorIndex())) {
            ClassFile.println(getIncrement(varying) + ";");
        }
        ClassFile.backTab();
        ClassFile.println("} while(true);");
    }

    public String getIncrement(SymbolProperties props2) {
        return NameUtil.getJavaName(props2, true).replace("%0", NameUtil.getJavaName(props2, false) + "+1");
    }

    /*****************************************************************************
    Copyright 2009 Venkat Krishnamurthy
    This file is part of RES.

    RES is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    RES is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with RES.  If not, see <http://www.gnu.org/licenses/>.

    @author VenkatK mailto: open.cobol.to.java at gmail.com
     ******************************************************************************/
    public class ExpressionString implements Cloneable {

        public StringBuilder literal;
        public String raw;
        public SymbolProperties props = null;
        public int type = -1;
        public boolean isAll = false;
        public boolean isJustRight = false;
        public int length = -1;
        public boolean isIdSymbol = false;
        public boolean isRounded = false;

        public String toString() {
            return literal.toString();
        }
       public String toString(boolean isO) {
           if(isO)
               return super.toString();
            return literal.toString();
        }

        public ExpressionString(SymbolProperties sym) {
            this(sym, 0);
        }

        public ExpressionString(SymbolProperties sym, int scale) {
            this(sym, scale, false);
        }

        public ExpressionString(SymbolProperties sym, int scale, boolean isPlainGet) {
            if (sym == null) {
                literal = new StringBuilder("");
            } else {
                isIdSymbol = true;
                literal = new StringBuilder(NameUtil.getJavaName(props = sym, false));
                type = sym.getIdentifierType();
                if (scale != 0) {
                    if (scale < 0) {

                        literal.insert(0, "__scale(").append(',').append(scale - sym.getJavaType().getMaxIntLength()).append(')');
                    } else if (scale > 0) {

                        literal.insert(0, "__scale(").append(',').append(scale).append(')');
                    }
                    type = Constants.BIGDECIMAL;
                }

                length = sym.getLength();
            }
        }

        public ExpressionString(SymbolProperties sym, boolean isRnd) {
            this(sym, 0);
            isRounded = isRnd;
        }

        public ExpressionString(String lit) {
            if (lit == null) {
                lit = "";
            }
            literal = new StringBuilder(lit);
        }

        public ExpressionString(String lit, int type) {
            this(lit);
            this.type = type;
        }

        public ExpressionString(ExpressionString lit) {            
            isJustRight = lit.isJustRight;
            literal = lit.literal;

            raw = lit.raw;
            props = lit.props;
            literal = new StringBuilder(lit.literal);

            length = lit.length;
            isAll = lit.isAll;
            type = lit.type;
            props = lit.props;
            isIdSymbol = lit.isIdSymbol;
            isRounded = lit.isRounded;
        }

        public ExpressionString() {
            literal = new StringBuilder();
        }

        public ExpressionString(int lit) {
            this(String.valueOf(lit));
        }

        public ExpressionString set(String lit) {
            literal = new StringBuilder(lit);
            return this;
        }

        public ExpressionString set(int lit) {
            literal = new StringBuilder(String.valueOf(lit));
            return this;
        }

        public ExpressionString setAll(boolean b) {
            isAll = b;
            return this;
        }

        public ExpressionString setType(int t) {
            type = t;
            return this;
        }

        public ExpressionString setLength(int l) {
            length = l;
            return this;
        }

        public void setString(String str) {
            literal = new StringBuilder(str);
        }

        public void setString(String str, int type) {
            literal = new StringBuilder(str);
            this.type = type;
        }

        public void setString(StringBuilder str) {
            literal = str;
        }

        //The Three Methods below for upward compatibility with old IdOrLit class.
        public SymbolProperties Id() {
            return props;
        }

        public String Lit() {
            return literal.toString();
        }

        public boolean IsRounded() {
            return isRounded;
        }

        public ExpressionString append(String s) {
            if (literal != null) {
                literal.append(s);
            }
            return this;
        }

        public ExpressionString insert(int i, String s) {
            if (literal != null) {
                literal.insert(i, s);
            }
            return this;
        }

        public ExpressionString replace(int i, int j, String s) {
            if (literal != null) {
                literal.replace(i, j, s);
            }
            return this;
        }
    }

    public ExpressionString getExpression() {
        ExpressionString thz = expression.pop();
        if (thz.type < 0) {
            thz.type = expressionType;
        }
        return thz;
    }

    public void initializeSymbols() {

        ClassFile.doMethodScope("public " + SymbolTable.getScope().getCurrentProgram().getJavaName2()
                + "() {");
        if (SymbolTable.getScope().getCurrentProgram().getAdjustedLength() > 0) /*
        if(SymbolTable.getScope().getCurrentProgram().getNoLivingFillers()>0)
        ClassFile.println("\tsuper(" +
        String.valueOf(SymbolTable.getScope().getCurrentProgram().getNoLivingFillers())+","+
        "new CobolBytes("+
        String.valueOf(SymbolTable.getScope().getCurrentProgram().getAdjustedLength())+"));");
        else*/ {
            ClassFile.println("\tsuper(" + "new CobolBytes("
                    + String.valueOf(SymbolTable.getScope().getCurrentProgram().getAdjustedLength()) + "));");
        } else;
        ClassFile.println("}");
        ClassFile.println("public void initialize(Program p) {");
        ClassFile.tab();
        ClassFile.println("if(__initialized) return; else __initialized=true;");
        ClassFile.println("__setProgram(p);");
        if (context.isDecimalPointIsComma()) {
            ClassFile.println("__setDecimalPointIsComma();");
        }
        if (context.getCurrencySign() != null) {
            ClassFile.println("__setCurrencySign(" + context.getCurrencySign() + ");");
        }
        ArrayList<?> a = (ArrayList<?>) SymbolTable.getScope().getCurrentProgram().getChildren();
        if (a != null) {
            for (Iterator<?> e = a.iterator(); e.hasNext();) {
                SymbolProperties o2 = (SymbolProperties) e.next();
                if (!(o2.getRef() || o2.getMod())) {
                    continue;
                }
                initializeOneSymbol(o2);
            }
        }
        ClassFile.backTab();
        ClassFile.endMethodScope();
    }

    public void initializeOneSymbol(SymbolProperties initProps) {
        //try{
        if (initProps == null
                || //!(initProps.getRef()||initProps.getMod())||
                initProps.getType() == SymbolConstants.PARAGRAPH
                || initProps.getType() == SymbolConstants.SECTION) {
            return;
        }
        if (initProps.getIsSuppressed()) {
            return;
        }

        if (initProps.getJavaType() != null) {
            initProps.setIdentifierType(initProps.getJavaType().getType());
        }

        int lvl = initProps.getLevelNumber();

        if (lvl == 88 || lvl == 66 || lvl == 78) {
            return;
        }

        if (initProps.is01Group()) {
            if (initProps.getValues() != null && initProps.getValues().size() > 0) {
                SymbolProperties.CoupleValue values = initProps.getValues().get(0);
                expression.push(formatLiteral(values.value1).toString());
                String exprString = TranslationTable.getInstance().getAssignString(initProps, null, false, true, true);
                exprString = exprString.substring(exprString.substring(0, exprString.indexOf('(') + 1).indexOf('.') + 1);
                ClassFile.println(exprString);
            } else {
                ClassFile.println(initProps.getJavaName1() + ".initialize(this);");
            }
            return;
        }
        if (initProps.getValues() != null && initProps.getValues().size() > 0) {
            SymbolProperties.CoupleValue values = initProps.getValues().get(0);
            String temp = formatLiteral(values.value1).toString();
            if (values.value1.isAll) {
                temp = "__all(" + temp + ',' + String.valueOf(initProps.getLength()) + ")";
            }
            if (initProps.getJavaType().getMaxScalingLength() != 0) {
                temp = doScaleLiteral(initProps, temp, false);
            }
            expression.push(new ExpressionString(temp, expressionType));
            if (!initProps.getIsFiller() && initProps.getNoOccursSubscripts() > 0) {
                int idx = 1;
                if (initProps.getIndexesWorkSpace() != null) {
                    initProps.getIndexesWorkSpace().clear();
                } else {
                    initProps.setIndexesWorkSpace(new ArrayList<String>());
                }
                for (SymbolProperties par : initProps.getOccursParents()) {
                    String idxStr = "idx" + String.valueOf(idx++);
                    ClassFile.println("for(int " + idxStr + "=1;"
                            + idxStr + "<=" + String.valueOf(par.getMaxOccurs())
                            + ";++" + idxStr + ") {");
                    ClassFile.tab();
                    initProps.getIndexesWorkSpace().add(idxStr);
                }
            }

            if (!initProps.getIsFiller()) {
                temp = TranslationTable.getInstance().getAssignString(initProps, null, false);
                temp = temp.substring(temp.substring(0, temp.indexOf('(') + 1).indexOf('.') + 1);
            } else {
                String exprString = TranslationTable.getInstance().convertType(expression.pop3(), initProps.getIdentifierType(), expressionType);
                temp = SymbolUtil.getInstance().getLocalFillerSetter(initProps, exprString) + ';';
            }


            if (temp != null && temp.trim().length() > 0) {
                ClassFile.println(temp);
            }
            if (!initProps.getIsFiller() && initProps.getNoOccursSubscripts() > 0) {
                initProps.getIndexesWorkSpace().clear();
                for (int idx = 0; idx < initProps.getNoOccursSubscripts(); ++idx) {
                    ClassFile.backTab();
                    ClassFile.println("}");
                }
            }
        }
        //} catch(Exception e) {
        //e.printStackTrace();
        //}
        return;

    }

    public String doScaleLiteral(SymbolProperties initProps, String temp, boolean isArith) {

        temp = "__scale(" + temp + ',' + ((!isArith ? ((initProps.getJavaType().getMaxScalingLength() < 0)
                ? (-initProps.getJavaType().getMaxScalingLength() + initProps.getJavaType().getMaxIntLength())
                : -initProps.getJavaType().getMaxScalingLength())
                : initProps.getJavaType().getMaxScalingLength())) + ')';
        expressionType = Constants.BIGDECIMAL;

        return temp;
    }

    private String doOneAll(ExpressionString lit, int len) {
        if (lit.isAll && len > 0) {
            return lit.literal.insert(0, "__all(").append(',').append(len).append(')').toString();
        } else {
            return lit.toString();
        }
    }

    public void doOne88(SymbolProperties o1) {
        try {
            if (o1 == null) {
                return;
            }
            if (o1.getIsSuppressed()) {
                return;
            }

            int lvl = o1.getLevelNumber();

            if (lvl != 88 || !(o1.getParent().getRef() || o1.getParent().getMod())) {
                return;
            }

            if (o1.getValues() == null || o1.getValues().size() <= 0) {
                return;
            }
            String getSubscripts = "";
            String accessSubscripts = "";
            if (o1.getParent().isOccurs() || o1.getParent().isAParentInOccurs()) {
                int size;
                if (o1.getParent().getOccursParents() != null && (size = o1.getParent().getOccursParents().size()) > 0) {
                    for (int i = 1; i <= size; ++i) {
                        getSubscripts += "int idx" + String.valueOf(i) + ((i != size) ? "," : "");
                        accessSubscripts += "idx" + String.valueOf(i) + ((i != size) ? "," : "");

                    }
                }
            }

            ClassFile.doMethodScope("public boolean get" + o1.getJavaName2() + "(" + getSubscripts
                    + ") {");
            ClassFile.tab();
            String retValue;
            if (o1.getParent().getIsFiller()) {
                retValue = SymbolUtil.getInstance().getLocalFillerGetter(o1.getParent());
            } else {
                retValue = "get" + o1.getParent().getJavaName2() + "(" + accessSubscripts
                        + ")";
            }
            retValue = "equals(" + retValue;
            int numThrough = 0;

            boolean foundPlain = false;
            boolean first = true;
            methodScope:
            {
                for (SymbolProperties.CoupleValue values : o1.getValues()) {
                    if (values.value2 != null) {
                        ++numThrough;
                        continue;
                    }
                    foundPlain = true;
                    retValue += "," + doOneAll(formatLiteral(values.value1), o1.getParent().getLength());
                }

                if (numThrough > 0) {
                    if (foundPlain) {
                        ClassFile.println("boolean b_=" + retValue + ");");
                    } else {
                    }

                } else {
                    if (foundPlain) {
                        ClassFile.println("return " + retValue + ");");
                    } else {
                        ClassFile.println("return false;");
                    }
                    break methodScope;
                }
                first = true;
                for (SymbolProperties.CoupleValue values : o1.getValues()) {
                    if (values.value2 == null) {
                        continue;
                    }
                    if (first) {
                        if (numThrough == 1) {
                            ClassFile.println("return equalsRange(get" + o1.getParent().getJavaName2() + "(" + accessSubscripts
                                    + "),"
                                    + doOneAll(formatLiteral(values.value1), o1.getParent().getLength()) + ","
                                    + doOneAll(formatLiteral(values.value2), o1.getParent().getLength()) + ");");
                            //ClassFile.println("return b_;");
                            break methodScope;
                        }
                        if (!foundPlain) {
                            ClassFile.println("boolean b_=equalsRange(get" + o1.getParent().getJavaName2() + "(" + accessSubscripts
                                    + "),"
                                    + doOneAll(formatLiteral(values.value1), o1.getParent().getLength()) + "," + doOneAll(formatLiteral(values.value2), o1.getParent().getLength()) + ");");
                            foundPlain = true;
                            continue;
                        }
                    }
                    ClassFile.println("b_|=equalsRange(get" + o1.getParent().getJavaName2() + "(" + accessSubscripts
                            + "),"
                            + doOneAll(formatLiteral(values.value1), o1.getParent().getLength()) + "," + doOneAll(formatLiteral(values.value2), o1.getParent().getLength()) + ");");
                }
                ClassFile.println("return b_;");
            }
            ClassFile.backTab();
            ClassFile.endMethodScope();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return;

    }
}
 public class CobolFillTable extends DepthFirstVisitor {

    private Stack<String> qualified = new Stack<String>();
    private Stack<SymbolProperties> dataStack = null;
    private SymbolProperties props = null;
    private SymbolProperties parent = null;
    private SymbolProperties paragraphProps = null;
    private SymbolProperties sectionProps = null;
    private String paragraphName = null;
    private String sectionName = null;
    private Cobol2Java.ExpressionString literal = context.getCobol2Java().new ExpressionString();
    private String pictureString = null;
    private String dataName = null;
    private String levelNumber = null;
    private String value1 = null;
    private String value2 = null;
    private String lastTokenString = null;
    private int fillerMark = 0;
    private int usage = Constants.DISPLAY;
    private boolean doLiteral;
    private boolean firstParagraph = true;
    private boolean doQualified = false;
    private boolean doingProgramName = false;
    private boolean doingValue = false;
    private boolean doingLevelNumber = false;
    private boolean doingDataName = false;
    private boolean doingPicture = false;
    public boolean isStatementInError;
    public String errorMessage;

    @Override
    public void visit(CompilationUnit n) {
        SymbolTable.getScope().setCloneOnLookup(false);
        super.visit(n);
    }

    @Override
    public void visit(NestedProgramUnit n) {
        boolean saveFirstParagraph = firstParagraph;
        firstParagraph = true;
        n.nestedIdentificationDivision.accept(this);
        n.nodeOptional1.accept(this);
        n.nodeOptional.accept(this);
        postProcess(n);
        n.nodeOptional2.accept(this);
        n.nodeListOptional.accept(this);
        SymbolTable.getScope().endProgram();
        firstParagraph = saveFirstParagraph;
    }

    private void postProcess(Node n) {
        for (SymbolProperties file : filesToPostProcess) {
            if (file.getOtherData2() != null) {
                //file.setOtherData2(SymbolTable.getScope().lookup((String)file.getOtherData2(),SymbolConstants.DATA));
                if (file.getOtherData2() == null) {
                    reportError(n, "Invalid Primary key in file " + file.getDataName() + ".");
                } else {
                    setRef(((SymbolProperties) file.getOtherData2()));
                }
            }
            if (file.getOtherData() != null && file.getOtherData().size() > 0) {
                ArrayList<Object> a = new ArrayList<Object>();
                for (Object o : file.getOtherData()) {
                    //o=SymbolTable.getScope().lookup((String)o,SymbolConstants.DATA);
                    if (o == null) {
                        reportError(n, "Invalid Alternat key in file " + file.getDataName() + ".");
                    } else {
                        setRef(((SymbolProperties) o));
                        a.add(o);
                    }
                }
                file.setOtherData(a);
            }
        }
        if (dependingOnToPostProcess != null) {
            for (SymbolProperties dep : dependingOnToPostProcess) {
                if (dep.getOtherData2() != null) {
                    props = null;
                    ((Node) dep.getOtherData2()).accept(this);
                    if (props == null) {
                        reportError(n, "Unknwon symbol in depending on clase of " + dep.getDataName() + ".");
                    } else {
                        dep.setDependingOnOccurs(props);
                        setRef(props);
                    }
                }
            }
        }
    }

    @Override
    public void visit(ProgramUnit n) {
        firstParagraph = true;
        n.identificationDivision.accept(this);
        n.nodeOptional1.accept(this);
        createSystemSymbols();
        n.nodeOptional.accept(this);
        postProcess(n);
        n.nodeOptional2.accept(this);
        SymbolTable.getScope().endProgram();
        //super.visit(n);
    }

    private void createSystemSymbols() {

        props = createIndexSymbol("RETURN-CODE", SymbolTable.getScope().getCurrentProgram(), true);
        props.setFromRESLibrary(true);
        //props.setJavaType(new CobolSymbol());
        adjustSetJavaName(props);

        props = createIndexSymbol("FILE-STATUS", SymbolTable.getScope().getCurrentProgram(), true);
        props.setFromRESLibrary(true);
        //props.setJavaType(new CobolSymbol());
        adjustSetJavaName(props);

        props = createIndexSymbol("DEBUG-LINE", SymbolTable.getScope().getCurrentProgram(), true);
        props.setPictureString("9(6)");
        props.setDataUsage((short) Constants.DISPLAY);
        //props.setJavaType(new CobolSymbol());
        props.setFromRESLibrary(true);
        adjustSetJavaName(props);

        props = createIndexSymbol("DEBUG-CONTENTS", SymbolTable.getScope().getCurrentProgram(), true);
        props.setPictureString("X(100)");
        props.setDataUsage((short) Constants.DISPLAY);
        props.getJavaType().setType(Constants.STRING);
        props.setFromRESLibrary(true);
        adjustSetJavaName(props);

        props = createIndexSymbol("DEBUG-NAME", SymbolTable.getScope().getCurrentProgram(), true);
        props.setPictureString("X(100)");
        props.setDataUsage((short) Constants.DISPLAY);
        props.getJavaType().setType(Constants.STRING);
        props.setFromRESLibrary(true);
        adjustSetJavaName(props);

        props = createIndexSymbol("DEBUG-SUB-1", SymbolTable.getScope().getCurrentProgram(), true);
        props.setPictureString("X(10)");
        props.setDataUsage((short) Constants.DISPLAY);
        props.getJavaType().setType(Constants.STRING);
        props.setFromRESLibrary(true);
        adjustSetJavaName(props);

        props = createIndexSymbol("DEBUG-SUB-2", SymbolTable.getScope().getCurrentProgram(), true);
        props.setPictureString("X(10)");
        props.setDataUsage((short) Constants.DISPLAY);
        props.getJavaType().setType(Constants.STRING);
        props.setFromRESLibrary(true);
        adjustSetJavaName(props);

        props = createIndexSymbol("DEBUG-SUB-3", SymbolTable.getScope().getCurrentProgram(), true);
        props.setPictureString("X(10)");
        props.setDataUsage((short) Constants.DISPLAY);
        props.getJavaType().setType(Constants.STRING);
        props.setFromRESLibrary(true);
        adjustSetJavaName(props);
    }

    @Override
    public void visit(DataDivision n) {
        super.visit(n);
    }
    
    @Override
    public void visit(SectionName n) {
        super.visit(n);
        sectionName = lastTokenString;
        sectionProps = SymbolTable.getScope().lookup(sectionName, SymbolConstants.SECTION);
    }

    @Override
    public void visit(ParagraphName n) {
        super.visit(n);
        paragraphName = lastTokenString;
        paragraphProps = SymbolTable.getScope().lookup(paragraphName, SymbolConstants.PARAGRAPH);
    }

    @Override
    public void visit(ProcedureName n) {
        sectionName = paragraphName = null;
        n.nodeChoice.choice.accept(this);
        if (paragraphName != null && sectionName != null) {
            paragraphProps = SymbolTable.getScope().lookup(paragraphName, sectionName);
        }
    }

    @Override
    public void visit(ProcedureSection n) {

        parent = null;
        props = null;

        popToProgram();

        n.sectionHeader.accept(this);

        if ((props = createSection()) == null) {
            reportError(n, "Duplcate Section: " + sectionName);
        }

        n.paragraphs.accept(this);

    }

    private void popToProgram() {
        while (dataStack != null && dataStack.size() > 0) {
            parent = (SymbolProperties) dataStack.peek();
            if (parent.getType() == SymbolConstants.PROGRAM) {
                break;
            }
            if (props == null && parent.getType() == SymbolConstants.SECTION) {
                props = (SymbolProperties) dataStack.pop();
            } else {
                dataStack.pop();
            }
        }
    }

    private SymbolProperties createSection() {
        sectionProps = new SymbolProperties();

        if (firstParagraph) {
            firstParagraph = false;
            //parent.setFallThruPara(sectionProps);
        } else {
            //props.setFallThruPara(sectionProps);
        }

        props = sectionProps;
        props.setDataName(sectionName);
        props.setLevelNumber((short) 0);
        props.setType(SymbolConstants.SECTION);
        props.setParent(parent);
        props.setParagraphMark(new Integer(++SymbolTable.paragraphMark));
        adjustSetJavaName(props);
        addChild(props, parent);
        if (parent.getParagraphList() == null) {
            parent.setParagraphList(new ArrayList<SymbolProperties>());
        }
        parent.getParagraphList().add(props);

        //Lookup and Insert
        if (SymbolTable.getScope().lookup(sectionName) != null) {
            return null;
        } else {
            SymbolTable.getScope().insert(sectionName, props);
            dataStack.push(props);
            return props;
        }
    }

    @Override
    public void visit(Paragraph n) {
        n.nodeChoice.choice.accept(this);
        if (n.nodeChoice.which == 0) {
            parent = null;
            props = null;
            while (dataStack != null && dataStack.size() > 0) {
                parent = (SymbolProperties) dataStack.peek();
                if (parent.getType() == SymbolConstants.PROGRAM
                        || parent.getType() == SymbolConstants.SECTION) {
                    break;
                }
                if (props == null) {
                    props = (SymbolProperties) dataStack.pop();
                } else {
                    dataStack.pop();
                }
            }

            if ((parent == null && firstParagraph) || dataStack == null || dataStack.size() <= 0) {
                reportError(n, "Fatal Error " + ((parent == null) ? 2 : (dataStack == null) ? 3 : 4)
                        + " Encountered while processing Paragraph: " + paragraphName);
                return;
            }

            paragraphProps = new SymbolProperties();
            props = paragraphProps;
            props.setDataName(paragraphName);
            props.setLevelNumber((short) 0);
            props.setType(SymbolConstants.PARAGRAPH);
            props.setParent(parent);
            adjustSetJavaName(props);
        } else {
            while (dataStack != null && dataStack.size() > 0) {
                parent = (SymbolProperties) dataStack.peek();
                if (parent.getType() == SymbolConstants.PROGRAM
                        || parent.getType() == SymbolConstants.SECTION) {
                    break;
                }
                dataStack.pop();
            }
            props.setParent(parent);
            return;
        }

        //	props.setParagraphMark(new Integer(++SymbolTable.paragraphMark));
        addChild(props, parent);
        if (parent.getParagraphList() == null) {
            parent.setParagraphList(new ArrayList<SymbolProperties>());
        }
        parent.getParagraphList().add(props);
        if (SymbolTable.getScope().lookup(paragraphName, parent.getDataName()) != null) {
            reportError(n, "Duplcate Paragraph: " + paragraphName);
            return;
        } else {
            SymbolTable.getScope().insert(paragraphName, props);
            ((RESNode) n).props = props;
            dataStack.push(props);
        }
        n.nodeChoice1.accept(this);
    }

    @Override
    public void visit(EntryStatement n) {
        n.literal.accept(this);
        createProgram(paragraphName = RunTimeUtil.getInstance().stripQuotes(literal.toString(), true), true);
    }

    @Override
    public void visit(Paragraphs n) {
        super.visit(n);
    }

    @Override
    public void visit(ProcedureBody n) {
        super.visit(n);
    }

    private boolean isInGroupDictionary(String name, SymbolProperties par) {
        if (par == null) {
            return false;
        }
        ArrayList<String> others = (ArrayList<String>) find01Level(par).getGroupDictionary();
        if (others != null && others.size() > 0) {
            for (Iterator<String> ite = others.iterator(); ite.hasNext();) {
                if (ite.next().equals(name)) {
                    return true;
                }
            }
        }
        return false;
    }

    private void addToGroupDictionary(String name, SymbolProperties par) {
        if (par == null) {
            return;
        }
        ArrayList<String> others = (ArrayList<String>) find01Level(par).getGroupDictionary();
        if (others == null) {
            others = new ArrayList<String>();
        }
        others.add(name);
        par.setGroupDictionary(others);
    }

    private SymbolProperties find01Level(SymbolProperties par) {
        while (!(par == null || par.isProgram() || par.isFile() || par.getLevelNumber() == 01 || par.getLevelNumber() == 77)) {
            par = par.getParent();
        }
        return par;
    }
    private boolean doUseStatementsInDeclaratives = false;

    @Override
    public void visit(ProcedureDivision n) {
        doUseStatementsInDeclaratives = false;
        n.nodeOptional1.accept(this);
        if (n.procedureBody.paragraphs.nodeListOptional.present()) {
            ++SymbolTable.paragraphMark;
            n.procedureBody.paragraphs.nodeListOptional.accept(this);
        }
        if (n.procedureBody.paragraphs.nodeListOptional1.present()) {
            n.procedureBody.paragraphs.nodeListOptional1.accept(this);
        }
        if (n.procedureBody.nodeListOptional.present()) {
            n.procedureBody.nodeListOptional.accept(this);
        }
        n.nodeOptional.accept(this);
        doUseStatementsInDeclaratives = true;
        n.nodeOptional1.accept(this);
        if (!RESConfig.getInstance().isInError()) {
            SymbolTable.visit(SymbolTable.getScope().getCurrentProgram(), new CalculateSymbolLength());
        }
    }

    @Override
    public void visit(UsingArgs n) {
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            props = null;
            e.nextElement().accept(this);
            if (props != null) {
                if (!props.isTopLevelData()) {
                    reportError(n, "Using clause arguments must be 01 or 77 levels only.");
                }
                if (!props.isLinkageSection()) {
                    reportError(n, "Using clause arguments must be defined in Linkage Section only.");
                }
                setRef(props);
                setMod(props);
            }
        }

    }

    @Override
    public void visit(NodeToken n) {
        if (n.tokenImage.trim().length() <= 0) {
            return;
        }
        lastTokenString = n.tokenImage;
        if (firstTokenInStatement == null) {
            firstTokenInStatement = n;
        }
        super.visit(n);
        if (doQualified) {
            if (qualified == null) {
                qualified = new Stack<String>();
            }
            if (n.tokenImage != null) {
                if (n.tokenImage.equalsIgnoreCase("IN")
                        || n.tokenImage.equalsIgnoreCase("OF")); else {
                    qualified.push(n.tokenImage);
                }
            }
        } else if (doLiteral) {
            literal.literal.append(n.tokenImage);
        } else if (doingDataName) {
            if (dataName == null) {
                dataName = "";
            }
            dataName += n.tokenImage;
        } else if (doingLevelNumber) {
            if (levelNumber == null) {
                levelNumber = "";
            }
            levelNumber += n.tokenImage;
        } else if (doingValue) {
            if (value1 == null) {
                value1 = "";
                value1 += n.tokenImage;
            } else if (n.tokenImage.equalsIgnoreCase("THROUGH")
                    || n.tokenImage.equalsIgnoreCase("THRU")) {
                if (value1 == null) {
                    value1 = "";
                }
            } else {
                value2 = "";
                value2 += n.tokenImage;
            }
        } else if (doingPicture) {
            pictureString += n.tokenImage;
        } else if (doingExecSQL) {
            doExecSQLSetRefMod(n);

        }
    }

    private void doExecSQLSetRefMod(NodeToken n) {
        if (n.kind == CobolParserConstants.S_BIND) {
            doSingleSQLParm(n.tokenImage);
        } else {
            ArrayList<String> parms = TranUtil.get().getParameters(n.tokenImage, false);
            if (parms != null) {
                for (String parm : parms) {
                    doSingleSQLParm(parm);
                }
            }
        }
    }

    private void doSingleSQLParm(String tokenImage) {
        SymbolProperties data = TranUtil.get().getParameter(tokenImage);
        if (data != null) {
            setRef(data);
            setMod(data);
        }
        data = TranUtil.get().getIndicator(tokenImage);
        if (data != null) {
            setRef(data);
            setMod(data);
        }
    }
    private boolean doingExecSQL = false;

    @Override
    public void visit(Literal n) {
        doLiteral = true;
        literal = context.getCobol2Java().new ExpressionString();
        n.nodeChoice.accept(this);
        if (n.nodeOptional.present() && (n.nodeChoice.which == 0 || n.nodeChoice.which == 1)) {
            literal.isAll = true;
        } else {
            literal.isAll = false;
        }
        doLiteral = false;
    }

    @Override
    public void visit(FigurativeConstant n) {
        String lit = null;
        switch (n.nodeChoice.which) {
            case 0:
            case 1:
            case 2:
                lit = "0";
                break;
            case 3:
            case 4:
                lit = "\" \"";
                break;
            case 5:
            case 6:
                lit = "HIGH-VALUE";
                break;
            case 7:
            case 8:
                lit = "LOW-VALUE";
                break;
            case 9:
            case 10:
                lit = "\"\\\"\"";
                break;
            case 11:
            case 12:
            default:
                lit = "0";
                break;
        }
        if (doLiteral) {
            literal.literal.append(lit);
        } else {
            literal = context.getCobol2Java().new ExpressionString(lit);
        }
    }
    private ArrayList<SymbolProperties> filesToPostProcess = new ArrayList<SymbolProperties>();

    @Override
    public void visit(FileAndSortDescriptionEntry n) {
        while (!dataStack.peek().isProgram()) {
            dataStack.pop();
        }
        if (context.getTraceLevel() >= 2) {
            System.out.println("Doing CobolFillTable FD/SD " + n.line);
        }
        isStatementInError = false;
        usage = Constants.DISPLAY;
        n.fileName.accept(this);
        while (dataStack.size() > 0 && (parent = (SymbolProperties) dataStack.peek()) != null && parent.getType() != SymbolConstants.PROGRAM) {
            dataStack.pop();
        }
        if (lastTokenString != null && lastTokenString.trim().length() > 0
                && parent != null && parent.getType() == SymbolConstants.PROGRAM
                && (SymbolTable.getScope().lookup(lastTokenString, parent.getDataName())) == null) {
            props = new SymbolProperties();
            props.setType(SymbolConstants.FILE);
            props.setDataName(lastTokenString);
            props.setLength(0);
            props.setAdjustedLength(0);
            props.setParent(parent);
            n.nodeListOptional.accept(this);
            if (doExternal(SymbolConstants.FILE)) {
                return;
            }
            addChild(props, parent);
            adjustSetJavaName(props);
            SymbolTable.getScope().insert(props.getDataName(), props);
            dataStack.push(props);
            filesToPostProcess.add(dataStack.peek());
            props = null;
            if (RESConfig.getInstance().isPrintCobolStatementsAsComments()
                    || RESConfig.getInstance().isRetainCobolComments()) {
                //props.setDataDescriptionEntry(n);//TODO
            }
        }

    }

    @Override
    public void visit(DataBlankWhenZeroClause n) {
        props.setBlankWhenZero(true);
    }

    @Override
    public void visit(ExternalClause n) {
        props.setExternal(true);
    }

    @Override
    public void visit(SameAreaClause n) {
        redefinesName = null;
        SymbolProperties par = null,prev=null;
        ArrayList<SymbolProperties> a = new ArrayList<SymbolProperties>();
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            e.nextElement().accept(this);
            if (props != null) {
                a.add(props);
                if(prev==null)
                    prev=props;
                else
                    prev=((prev.getInternalMark()<=props.getInternalMark())?prev:props);
            }
        }
        if(prev==null) return;
        redefinesName=prev.getChildren().get(0).getDataName();par=prev;
        for(SymbolProperties props2:a) {
            if (prev.getDataName().equalsIgnoreCase(props2.getDataName())) {
                continue;
            }
            props=props2.getChildren().get(0);
            doRedefines(par);
        }
    }
    private boolean doingLinkageSection = false;

    @Override
    public void visit(LinkageSection n) {
        doingLinkageSection = true;
        //Pop the file name as not parents until we reach the program
        while (dataStack.size() > 0 && ((SymbolProperties) dataStack.peek()).getType() != SymbolConstants.PROGRAM) {
            dataStack.pop();
        }
        super.visit(n);
        doingLinkageSection = false;
    }

    @Override
    public void visit(WorkingStorageSection n) {

        //Pop the file name as not parents until we reach the program
        while (dataStack.size() > 0 && ((SymbolProperties) dataStack.peek()).getType() != SymbolConstants.PROGRAM) {
            dataStack.pop();
        }

        super.visit(n);
    }

    @Override
    public void visit(AccessModeClause n) {
        props.setOtherData1(n.nodeChoice.which);
        n.nodeChoice.choice.accept(this);
    }

    @Override
    public void visit(AlternateRecordKeyClause n) {
        SymbolProperties saveProps = props;
        n.qualifiedDataName.accept(this);
        if (saveProps.getOtherData() == null) {
            saveProps.setOtherData(new ArrayList<Object>());
        }
        props.setDuplicateKey(n.nodeOptional3.present());
        saveProps.getOtherData().add(props);
        props = saveProps;
    }

    @Override
    public void visit(KeyClause n) {
        SymbolProperties saveProps = props;
        n.qualifiedDataName.accept(this);
        saveProps.setOtherData2(props);
        props = saveProps;
    }

    @Override
    public void visit(RecordContainsClause n) {
        switch (n.nodeChoice.which) {
            case 0:
                ((NodeSequence) n.nodeChoice.choice).elementAt(1).accept(this);
                props.setAdjustedLength((int) integerConstant);
                if (((NodeOptional) ((NodeSequence) n.nodeChoice.choice).elementAt(0)).present()) {
                    ((NodeOptional) ((NodeSequence) n.nodeChoice.choice).elementAt(0)).accept(this);
                    props.setLength((int) integerConstant);
                } else {
                    props.setLength(props.getAdjustedLength());
                }
                break;
            case 1:
            //TODO VARYING DEPENDING ON
        }
    }
    private boolean doNotAddChildrenToSymbolTable = false;

    @Override
    public void visit(DataDescriptionEntry n) {
        if (context.getTraceLevel() >= 2) {
            System.out.println("Doing CobolFillTable DataDescriptionEntry " + n.line);
        }
        if (n.nodeChoice.which >= 5) {
            return;
        }
        isStatementInError = false;
        usage = Constants.DISPLAY;

        props = new SymbolProperties();

        props.setLinkageSection(doingLinkageSection);
        pictureString = null;
        redefinesName = null;
        if (RESConfig.getInstance().isPrintCobolStatementsAsComments()
                || RESConfig.getInstance().isRetainCobolComments()) {
            props.setDataDescriptionEntry(n);
        }

        //Initialize
        NodeSequence v = (NodeSequence) n.nodeChoice.choice;
        int i = 0;
        for (Enumeration<Node> e = v.elements(); e.hasMoreElements();) {
            doingLevelNumber = false;
            doingDataName = false;
            if (i == 0) {
                doingLevelNumber = true;
                levelNumber = null;
            }
            if (i == 1) {
                dataName = null;
                doingDataName = true;
            }
            e.nextElement().accept(this);
            i++;
        }
        propagateRef();
        propagateMod();

        doingDataName = false;
        doingLevelNumber = false;
        //post-process

        if (levelNumber != null && levelNumber.length() > 0) {
            props.setLevelNumber(Short.parseShort(levelNumber));
        } else {
            //TODO Error processing
            return;
        }
        props.setDataCategory(FieldFormat.getDataCategory(pictureString));
        if (props.getLevelNumber() == 1) {
            doNotAddChildrenToSymbolTable = false;
        }
        if (doNotAddChildrenToSymbolTable) {
            return;
        }

        if (dataName == null || dataName.equalsIgnoreCase("FILLER")) {
            dataName = "FILLER" + new Integer(fillerMark++).toString().trim() + "_";
            props.setIsFiller(true);
        }

        props.setDataName(dataName);

        if (props.getLevelNumber() == 78) {
            createIndexSymbol(dataName, SymbolTable.getScope().getCurrentProgram(), false);
            if (props.getValues() == null || props.getValues().size() <= 0) {
                reportError(n, "78 level VALUE must not be null.");
            }
            return;
        }


        if (props == null || dataName == null) {
            //TODO Error processing
            return;
        }
        if (context.getTraceLevel() >= 2) {
            System.out.println("Doing CobolFillTable symbol " + dataName);
        }
        props.setType(SymbolConstants.DATA);
        if (usage == Constants.INDEX) {//INDEX
            parent = SymbolTable.getScope().getCurrentProgram();
        } else {
            parent = find01Level(dataStack.peek());
            if (parent != null && parent.getDataUsage() == Constants.INDEX
                    && !(props.getLevelNumber() == 77 || props.getLevelNumber() == 1
                    || props.getLevelNumber() == 66 || props.getLevelNumber() == 88)
                    && props.getLevelNumber() > parent.getLevelNumber()) {
                pictureString = INDEX_PICTURE_STRING;
                props.setDataUsage((short) Constants.INDEX);
                props.setIndexRedefines(true);
                props.setRedefines(parent);
                parent = SymbolTable.getScope().getCurrentProgram();
            } else if (props.getLevelNumber() == 66) {
                parent.setHasRenames(true);
            } else {
                while (dataStack.size() > 0
                        && (parent = (SymbolProperties) dataStack.peek()) != null) {
                    if ((props.getLevelNumber() == 77 || props.getLevelNumber() == 1) && parent.getLevelNumber() != 0) {
                        dataStack.pop();
                    } else if (props.getLevelNumber() <= parent.getLevelNumber()) {
                        dataStack.pop();
                    } else {
                        break;
                    }
                }
            }
        }

        if (dataStack.size() <= 0) {
            parent = null;
        }
        if (parent != null) {
            props.setParent(parent);
            props.setExternal(props.isExternal() || parent.isExternal());
            if (doExternal(SymbolConstants.DATA)) {
                return;
            }
            addChild(props, parent);
            props.setIsSuppressed(false);
            doRedefines(parent);
            doVaryingPicture();
        }


        //do the symbol table and level stack

        props.setDataUsage((short) usage);
        if (props.isFloatingPoint()) {
            if (props.getDataUsage() == Constants.COMPUTATIONAL1) {
                props.setPictureString("-.9(8)E-99");
            } else {
                props.setPictureString("-.9(17)E-99");
            }
        } else {
            props.setPictureString(pictureString);
        }
        adjustSetJavaName(props);
        SymbolTable.getScope().insert(props.getDataName(), props);
        dataStack.push(props);

        if (RESConfig.getInstance().isAllSymbols()) {
            props.setRef(true);
        }

        if (dataName.equalsIgnoreCase("SQLCA") && props.getLevelNumber() == 1 && pictureString == null) {
            props.setRef(false);
            props.setMod(false);
            props.setFromRESLibrary(true);
            props.getJavaType().setType(Constants.GROUP);
            SymbolProperties tempProps = createDataSymbol("sqlcode", props, "9(8)", Constants.BINARY, 02);
            tempProps.setFromRESLibrary(true);
            tempProps.setIsFormat(false);
            tempProps.setRef(true);
            tempProps = createDataSymbol("sqlwarn", props, "X(8)", Constants.DISPLAY, 02);
            tempProps.setFromRESLibrary(true);
            //tempProps.setJavaType(new CobolSymbol());
            tempProps.setIsFormat(false);
            tempProps.setRef(true);
            tempProps = createDataSymbol("sqlerrmc", props, "X(80)", Constants.DISPLAY, 02);
            tempProps.setFromRESLibrary(true);
            tempProps.getJavaType().setType(Constants.STRING);
            tempProps.setIsFormat(false);
            tempProps.setRef(true);
            tempProps = createDataSymbol("sqlerrd", props, "9(8)", Constants.BINARY, 02);
            tempProps.setFromRESLibrary(true);
            //tempProps.setJavaType(new CobolSymbol());
            tempProps.setIsFormat(false);
            tempProps.setRef(true);
            tempProps.setOccurs(true);
            tempProps.setMaxOccurs(5);
            doNotAddChildrenToSymbolTable = true;
        }

        if (props.getDataCategory() == Constants.NUMERIC_EDITED
                || (FieldFormat.isString(props.getPictureString()) && !FieldFormat.isPlainString(props.getPictureString()))) {
            props.setIsFormat(true);
        }
        //if(props.getDataCategory()==Constants.NUMERIC&&props.getDataUsage()==Constants.DISPLAY)
        //props.setForceCobolBytes(true);
        props = null;
    }

    //Type can be DATA or FILE
    private boolean doExternal(int type) {
        if (props == null) {
            return false;
        }
        SymbolProperties props2 = SymbolTable.getScope().lookup(props.getDataName(), type);
        if (props2 != null) {
            boolean b = props2.isExternal();

            if (props.getLevelNumber() == 01 || props.isFile()) {
                b = props.isExternal();
            } else {
                SymbolProperties props3 = find01Level(dataStack.peek());
                if (props3 != null && ((props3.getLevelNumber() == 1 && type == SymbolConstants.DATA)
                        || (props3.isFile() && type == SymbolConstants.FILE))) {
                    b = props3.isExternal();
                }
            }
            if (props2.isExternal() && b) {
                dataStack.push((SymbolProperties) props2);
                return true;
            }

        }
        return false;
    }

    private void doVaryingPicture() {

        if (props == null || !props.isVarying()) {
            return;
        }

        SymbolProperties tempProps;
        String key1 = props.getDataName() + "-LEN";
        String key2 = props.getDataName() + "-ARR";
        if (props != null && props.isVarying() && pictureString != null
                && (tempProps = SymbolTable.getScope().lookup(key1, props.getDataName())) == null
                && (tempProps = SymbolTable.getScope().lookup(key2, props.getDataName())) == null) {

            tempProps = new SymbolProperties();
            tempProps.setType(SymbolConstants.DATA);
            tempProps.setDataName(key1);
            tempProps.setParent(props);
            tempProps.setPictureString(VARYING_LEN_PICTURE_STRING);
            //tempProps.setJavaType(new CobolSymbol());
            addChild(tempProps, props);
            tempProps.setVaryingLen(true);
            SymbolTable.getScope().insert(key1, tempProps);
            tempProps = new SymbolProperties();
            tempProps.setType(SymbolConstants.DATA);
            tempProps.setDataName(key2);
            tempProps.setParent(props);
            tempProps.setPictureString(pictureString);
            tempProps.getJavaType().setType(Constants.STRING);
            addChild(tempProps, props);
            tempProps.setVaryingArray(true);
            SymbolTable.getScope().insert(key2, tempProps);
        }
        return;


    }

    @SuppressWarnings("unused")
    private void doRedefines(SymbolProperties par) {
        SymbolProperties data2;
        if (par.isFile() && par.getChildren().size() > 1) {
            data2 = par.getChildren().get(0);
        } else {
            if (redefinesName == null) {
                return;
            }
            if (par == null) {
                data2 = SymbolTable.getScope().lookup(redefinesName);
            } else {
                data2 = SymbolTable.getScope().lookup(redefinesName, par.getDataName());
            }
        }
        if (data2 == null);//TODO Semantic error
        else {
            props.setRedefines(data2);
            ArrayList<SymbolProperties> a = data2.getRedefinedBy();
            if (a == null) {
                a = new ArrayList<SymbolProperties>();
            }
            a.add(props);
            data2.setRedefinedBy(a);
            while (par != null && par.getType() != SymbolConstants.PROGRAM && par.getLevelNumber() != 1 && par.getLevelNumber() != 77) {
                par = par.getParent();
            }
            if (par != null) {
                par.setAChildHasRedefines(true);
            }
        }
    }

    @Override
    public void visit(Subscript n) {
        SymbolProperties propsDataName = props;
        //for (Enumeration e=n.nodeList.elements();e.hasMoreElements();) {
        //NodeChoice ch=(NodeChoice)e.nextElement();
        switch (n.nodeChoice.which) {
            case 0:
                break;
            case 1:
                NodeSequence seq = (NodeSequence) n.nodeChoice.choice;
                seq.elementAt(0).accept(this);
                if (isStatementInError || props == null) {
                    return;
                }
                setRef(props);
                break;
            case 2:
        }
        //}
        props = propsDataName;
    }

    @Override
    public void visit(AddStatement n) {
        expressionType = Constants.INTEGER;
        super.visit(n);
    }

    @Override
    public void visit(DivideStatement n) {
        expressionType = Constants.INTEGER;
        super.visit(n);
    }

    @Override
    public void visit(MultiplyStatement n) {
        expressionType = Constants.INTEGER;
        super.visit(n);
    }

    @Override
    public void visit(SubtractStatement n) {
        expressionType = Constants.INTEGER;
        super.visit(n);
    }

    @Override
    public void visit(AddBody n) {
        super.visit(n);
    }

    @Override
    public void visit(ArithIdentifier n) {
        super.visit(n);
        if (props == null) {
            return;
        }
        setMod(props);
        if (FieldFormat.verifyCobolPicture(props.getPictureString()) == Constants.BIGDECIMAL) {
            //SymbolTable.programs.peek().setImportBigDecimal(true);
            expressionType = Constants.BIGDECIMAL;
        }
    }

    @Override
    public void visit(ArithIdentifierList n) {
        super.visit(n);
    }

    @Override
    public void visit(IdOrLiteral n) {
        super.visit(n);
        switch (n.nodeChoice.which) {
            case 0:
                if (isStatementInError || props == null) {
                    return;
                }
                setRef(props);
                if (props.getPictureString() == null) {
                    return;
                }
                if (FieldFormat.verifyCobolPicture(props.getPictureString()) == Constants.BIGDECIMAL) {
                    //SymbolTable.programs.peek().setImportBigDecimal(true);
                    expressionType = Constants.BIGDECIMAL;
                }
                break;
            case 1:
                //int prevExpressionType=expressionType;
                //formatLiteral(literal);
                if (expressionType == Constants.BIGDECIMAL) {
                    SymbolTable.getScope().getCurrentProgram().setImportBigDecimal(true);
                }
            default:
        }
    }

    @Override
    public void visit(IdOrLiteralList n) {
        super.visit(n);
    }

    @Override
    public void visit(ProgramIdParagraph n) {
        doingProgramName = true;
        //super.visit(n);
        n.programName.accept(this);
        doingProgramName = false;
        SymbolTable.getScope().startProgram((SymbolProperties) dataStack.peek());
    }

    @Override
    public void visit(ProgramName n) {
        super.visit(n);
        if (doingProgramName) {
            createProgram(n.cobolWord.nodeToken.tokenImage, false);
        }
    }

    private void createProgram(String name, boolean isEntry) {

        props = new SymbolProperties();
        props.setDataName(name);
        props.setLevelNumber((short) 0);
        props.setType(SymbolConstants.PROGRAM);

        if (isEntry) {
            adjustSetJavaName(props);
            SymbolTable.getScope().insert(name, props);
            return;
        }

        if (dataStack == null) {
            dataStack = new Stack<SymbolProperties>();
        } else;

        while (dataStack.size() > 0
                && (parent = (SymbolProperties) dataStack.peek()) != null) {
            if (!parent.isProgram()) {
                dataStack.pop();
            } else {
                break;
            }
        }

        if (dataStack.size() <= 0) {
            parent = null;
        }
        SymbolProperties symbol = null;
        if (parent != null) {
            symbol =
                    SymbolTable.getScope().lookup(name, (String) parent.getDataName());
            if (symbol != null) {
                reportError("*** Error: Duplicate Symbol"
                        + (String) props.getDataName() + " IN " + parent.getDataName());
                return;
            } else {
                props.setParent(parent);
                addChild(props, parent);
            }
        } else {
            symbol = SymbolTable.getScope().lookup(name, SymbolConstants.DATA);
            if (symbol != null && props.getParent() == null) {
                reportError("*** Error: Duplicate Symbol"
                        + (String) props.getDataName());
                return;
            }
        }
        adjustSetJavaName(props);
        SymbolTable.getScope().insert(name, props);
        dataStack.push(props);
        props = null;
    }

    @Override
    public void visit(NestedProgramIdParagraph n) {
        doingProgramName = true;
        super.visit(n);
        SymbolTable.getScope().startProgram((SymbolProperties) dataStack.peek());
        doingProgramName = false;
    }

    @Override
    public void visit(DataExternalClause n) {
        props.setExternal(true);
    }

    @Override
    public void visit(DataGlobalClause n) {
        super.visit(n);
    }

    @Override
    public void visit(DataJustifiedClause n) {
        props.setJustifiedRight(n.nodeOptional.present());
    }

    @Override
    public void visit(DataName n) {
        super.visit(n);
        if (insertDummyData) {
            SymbolProperties tempProps = new SymbolProperties();
            tempProps.setDataName(lastTokenString);
            tempProps.setType(SymbolConstants.DUMMY);
            //tempProps.setJavaType(new CobolSymbol());
            tempProps.getJavaType().setType(Constants.OBJECT);
            SymbolTable.getScope().insert(tempProps.getDataName(), tempProps);
        }
    }

    @Override
    public void visit(CdName n) {
        super.visit(n);
        SymbolProperties tempProps = new SymbolProperties();
        tempProps.setDataName(lastTokenString);
        tempProps.setType(SymbolConstants.DUMMY);
       // tempProps.setJavaType(new CobolSymbol());
        tempProps.getJavaType().setType(Constants.OBJECT);
        SymbolTable.getScope().insert(tempProps.getDataName(), tempProps);
    }

    @Override
    public void visit(MoveStatement n) {

        switch (n.nodeChoice.which) {
            case 0:
                NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
                if (nodeseq.size() != 3) {
                    return;
                }
                SymbolProperties propsFrom = null;
                boolean isSourceANumber = false;
                int javaType1 = 0,
                 dataUsage1 = 0,
                 javaType2 = 0,
                 dataUsage2 = 0;
                NodeChoice choice2 = (NodeChoice) nodeseq.elementAt(0);
                ;
                choice2.accept(this);
                if (choice2.which == 0) {
                    propsFrom = props;
                    if (isStatementInError || props == null) {
                        return;
                    }
                    javaType1 = FieldFormat.verifyCobolPicture(propsFrom.getPictureString());
                    dataUsage1 = propsFrom.getDataUsage();
                    setRef(props);
                    isSourceANumber = (verifyCobolPicture(props.getPictureString()) <= Constants.BIGDECIMAL);
                } else {
                    formatLiteral(literal);
                    javaType1 = expressionType;
                    dataUsage1 = Constants.BINARY;
                    //isSourceANumber=(expressionType<=Constants.BIGDECIMAL);
                }
                if (nodeseq.elementAt(2) instanceof NodeList) {
                    for (Enumeration<Node> e = ((NodeList) nodeseq.elementAt(2)).elements();
                            e.hasMoreElements();) {
                        Node node = e.nextElement();
                        node.accept(this);
                        if (isStatementInError || props == null) {
                            return;
                        }
                        setMod(props);
                        javaType2 = FieldFormat.verifyCobolPicture(props.getPictureString());
                        dataUsage2 = props.getDataUsage();
                        if (javaType2 <= Constants.BIGDECIMAL) {
                            if (dataUsage2 != Constants.DISPLAY) {
                                props.setIsFormat(!props.isFromRESLibrary());
                            }
                        } else if (verifyCobolPicture(props.getPictureString()) == Constants.STRING
                                && !FieldFormat.isPlainString(props.getPictureString())) {
                            props.setIsFormat(!props.isFromRESLibrary());
                        }
                        if (propsFrom != null) {
                            if (javaType1 <= Constants.BIGDECIMAL) {
                                if (dataUsage1 != Constants.DISPLAY) {
                                    propsFrom.setIsFormat(!props.isFromRESLibrary());
                                }
                            } else if (javaType1 == Constants.STRING
                                    && !FieldFormat.isPlainString(propsFrom.getPictureString())) {
                                propsFrom.setIsFormat(!props.isFromRESLibrary());
                            }
                        }
                    }
                }
                break;
            case 1:
                nodeseq = (NodeSequence) n.nodeChoice.choice;
                propsFrom = null;
                isSourceANumber = false;
                nodeseq.elementAt(1).accept(this);
                if (isStatementInError || props == null) {
                    return;
                }
                propsFrom = props;
                setRef(props);

                if (nodeseq.elementAt(3) instanceof NodeList) {
                    for (Enumeration<Node> e = ((NodeList) nodeseq.elementAt(3)).elements();
                            e.hasMoreElements();) {
                        Node node = e.nextElement();
                        node.accept(this);
                        setMod(props);
                        doCorrespondingMove(propsFrom, props, true);
                    }
                }
        }
    }

    private int verifyCobolPicture(String picture) {
        if (picture == null) {
            return Constants.GROUP;
        } else {
            return FieldFormat.verifyCobolPicture(picture);
        }
    }

    private void doCorrespondingMove(SymbolProperties from, SymbolProperties to, boolean first) {
        propagateRefAllChildren(from);
        propagateModAllChildren(to);
        if ((from = find01Level(from)) != null) {
            from.setRef(true);
        }
        if ((to = find01Level(to)) != null) {
            to.setMod(true);
        }
    }

    private void propagateModAllChildren(SymbolProperties to) {
        to.setMod(true);
        if (to.hasChildren()) {
            for (SymbolProperties ch : to.getChildren()) {
                propagateModAllChildren(ch);
            }
        }
    }

    private void propagateRefAllChildren(SymbolProperties from) {
        from.setRef(true);
        if (from.hasChildren()) {
            for (SymbolProperties ch : from.getChildren()) {
                propagateRefAllChildren(ch);
            }
        }
    }
    private static final String INDEX_PICTURE_STRING = "9999999";
    private static final String VARYING_LEN_PICTURE_STRING = INDEX_PICTURE_STRING;
    //private static final String VARYING_ARR_PICTURE_STRING="X(132)";
    private static final short INDEX_LEVEL = 77;
    private ArrayList<SymbolProperties> dependingOnToPostProcess = null;

    @Override
    public void visit(DataOccursClause n) {
        SymbolProperties tempprops = null;
        if (n.nodeOptional.present()) {
            NodeChoice nodechoice = ((NodeChoice) ((NodeSequence) n.nodeOptional.node).elementAt(0));
            nodechoice.accept(this);
            switch (nodechoice.which) {
                case 0:
                    break;
                case 1:
                    tempprops = SymbolTable.getScope().lookup(lastTokenString);
                    if (tempprops == null) {
                        reportError(n, "Unknown Symbol :" + lastTokenString);
                        return;
                    }
                    if (tempprops.getValues() == null || tempprops.getValues().size() <= 0) {
                        reportError(n, "May not be used in OCCUSRS. No VALUE in Symbol :" + lastTokenString);
                        return;
                    }
                    integerConstant = Integer.parseInt(tempprops.getValues().get(0).value1.toString());
            }
            //accept(this);
            props.setMinOccurs((int) integerConstant);
            tempprops = null;
            n.nodeChoice.accept(this);
            switch (n.nodeChoice.which) {
                case 0:
                    break;
                case 1:
                    tempprops = SymbolTable.getScope().lookup(lastTokenString);
                    if (tempprops == null) {
                        reportError(n, "Unknown Symbol :" + lastTokenString);
                        return;
                    }
                    if (tempprops.getValues() == null || tempprops.getValues().size() <= 0) {
                        reportError(n, "May not be used in OCCUSRS. No VALUE in Symbol :" + lastTokenString);
                        return;
                    }
                    integerConstant = Integer.parseInt(tempprops.getValues().get(0).value1.toString());
            }
            props.setMaxOccurs((int) integerConstant);
            tempprops = null;
            props.setOccurs(true);
            props.setVaryingOccurs(true);
        } else {
            n.nodeChoice.accept(this);
            switch (n.nodeChoice.which) {
                case 0:
                    break;
                case 1:
                    tempprops = SymbolTable.getScope().lookup(lastTokenString);
                    if (tempprops == null) {
                        reportError(n, "Unknown Symbol :" + lastTokenString);
                        return;
                    }
                    if (tempprops.getValues() == null || tempprops.getValues().size() <= 0) {
                        reportError(n, "May not be used in OCCURS. No VALUE in Symbol :" + lastTokenString);
                        return;
                    }
                    integerConstant = Integer.parseInt(tempprops.getValues().get(0).value1.toString());
            }
            props.setMaxOccurs((int) integerConstant);
            props.setMinOccurs(props.getMaxOccursInt());
            props.setOccurs(true);
            props.setVaryingOccurs(false);
            tempprops = null;
        }
        if (n.nodeOptional2.present()) {
            props.setOtherData2(n.nodeOptional2.node);
            if (dependingOnToPostProcess == null) {
                dependingOnToPostProcess = new ArrayList<SymbolProperties>();
            }
            dependingOnToPostProcess.add(props);
        }
        if (n.nodeOptional3.present()) {
            NodeList nodelist = (NodeList) ((NodeSequence) n.nodeOptional3.node).elementAt(2);
            for (Enumeration<Node> e = nodelist.elements(); e.hasMoreElements();) {
                ((NodeSequence) e.nextElement()).elementAt(0).accept(this);
                tempprops = createIndexSymbol(lastTokenString, SymbolTable.getScope().getCurrentProgram(), true);
                tempprops.setRef(true);
                if (props.getMajorIndex() == null) {
                    props.setMajorIndex(tempprops);
                }
                tempprops.setMajorIndex(props);//isOccurs() decides if it is a index or table.
            }
        }
        //super.visit(n);
    }

    private SymbolProperties createDataSymbol(String dataName, SymbolProperties parent, String picture,
            int usage, int level) {
        SymbolProperties tempProps;
        if ((tempProps = SymbolTable.getScope().lookup(dataName, parent.getDataName())) == null) {
            tempProps = new SymbolProperties();
            tempProps.setType(SymbolConstants.DATA);
            tempProps.setDataName(dataName);
            tempProps.setParent(parent);
            tempProps.setPictureString(picture);
            tempProps.setLevelNumber((short) level);
            tempProps.setDataUsage((short) usage);
            adjustSetJavaName(tempProps);
            addChild(tempProps, parent);
            if (RESConfig.getInstance().isAllSymbols()) {
                tempProps.setRef(true);
            }
            SymbolTable.getScope().insert(dataName, tempProps);
        } else {
            return null;
        }
        return tempProps;
    }

    private SymbolProperties createIndexSymbol(String dataName, SymbolProperties parent, boolean create) {
        SymbolProperties tempProps;
        if ((tempProps = SymbolTable.getScope().lookup(dataName, parent.getDataName())) == null) {
            if (create) {
                tempProps = new SymbolProperties();
            } else {
                tempProps = props;
            }
            tempProps.setType(SymbolConstants.DATA);
            tempProps.setDataName(dataName);
            tempProps.setParent(parent);
            tempProps.setPictureString(INDEX_PICTURE_STRING);
            tempProps.setLevelNumber(INDEX_LEVEL);
            tempProps.setDataUsage((short) Constants.BINARY);
            adjustSetJavaName(tempProps);
            addChild(tempProps, parent);
            SymbolTable.getScope().insert(dataName, tempProps);
            if (RESConfig.getInstance().isAllSymbols()) {
                tempProps.setRef(true);
            }
        }
        return tempProps;
    }

    private void addChild(SymbolProperties child, SymbolProperties par) {
        if (par == null || child == null) {
            return;
        }
        if (par.getChildren() == null) {
            par.setChildren(new ArrayList<SymbolProperties>());
        } else {
            if (par.getChildren().size() > 0) {
                par.getChildren().get(par.getChildren().size() - 1).setSibling(child);
            }
        }
        par.getChildren().add(child);

    }
    private long integerConstant = 0;

    @Override
    public void visit(IntegerConstant n) {
        super.visit(n);
        integerConstant = FieldFormat.parseNumber(((NodeToken) n.nodeChoice.choice).tokenImage).longValue();
        //literal=((NodeToken)n.nodeChoice.choice).tokenImage;
    }

    @Override
    public void visit(DataPictureClause n) {
        n.pictureString.accept(this);
        props.setVarying(n.nodeOptional1.present());
    }

    @Override
    public void visit(PictureString n) {
        this.pictureString = "";
        doingPicture = true;
        super.visit(n);
        doingPicture = false;
    }

    @Override
    public void visit(NonDotChars n) {
        // TODO Auto-generated method stub
        super.visit(n);
    }

    @Override
    public void visit(PictureCurrency n) {
        this.pictureString += n.nodeToken.tokenImage;
    }

    @Override
    public void visit(PictureOccurence n) {
        super.visit(n);
    }

    @Override
    public void visit(PicturePunctuation n) {
        // TODO Auto-generated method stub
        super.visit(n);
    }

    @Override
    public void visit(DataRecordClause n) {
        super.visit(n);
    }
    private String redefinesName = null;

    @Override
    public void visit(DataRedefinesClause n) {
        redefinesName = n.dataName.cobolWord.nodeToken.tokenImage;
    }

    @Override
    public void visit(RenamesClause n) {
        SymbolProperties tempProps;
        tempProps = props;
        n.qualifiedDataName.accept(this);
        tempProps.setRedefinedBy(new ArrayList<SymbolProperties>());
        tempProps.getRedefinedBy().add(props);
        if (n.nodeOptional.present()) {
            tempProps.setPictureString(null);
            n.nodeOptional.accept(this);
            tempProps.getRedefinedBy().add(props);
        } else {
            tempProps.setPictureString(props.getPictureString());
        }
        props = tempProps;
    }

    @Override
    public void visit(DataSignClause n) {
        if (n.nodeChoice.which == 0) {
            props.setSignLeading(true);
        }
        if (n.nodeOptional1.present()) {
            props.setSignSeparate(true);
        }
        //super.visit(n);
    }

    @Override
    public void visit(DataSynchronizedClause n) {
        super.visit(n);
    }

    @Override
    public void visit(DataUsageClause n) {

        switch (n.nodeChoice.which) {
            case 3://Comp-2
            case 9://Compuational-2
                pictureString = "-.9(17)E-99";
                usage = Constants.BINARY;
                break;
            case 2://Comp-1
            case 8://Compuational-1
                pictureString = "-.9(8)E-99";
                usage = Constants.BINARY;
                break;
            case 4://Comp-3
            case 10://Compuational-3
            case 16://Packed-Decimal
                usage = Constants.PACKED_DECIMAL;
                break;
            case 0://Binary
            case 1://Comp
            case 5://Comp-4
            case 7://Computational
            case 11://Compuational-4
            case 6://Comp-5
            case 12://Compuational-5
                usage = Constants.BINARY;
                break;
            case 13://Display
                usage = Constants.DISPLAY;
                break;
            case 14://Display-1
                usage = Constants.DISPLAY_1;
                break;
            case 15://Index
                usage = Constants.INDEX;
                pictureString = INDEX_PICTURE_STRING;
                break;
            case 17://Pointer
            case 18://Function-Pointer
            case 19://Procedure-Pointer
            default://Object Reference DataName()
                usage = Constants.OBJECT;
        }
    }

    @Override
    public void visit(DataValueClause n) {
        //super.visit(n.nodeList);
        ArrayList<SymbolProperties.CoupleValue> a = new ArrayList<SymbolProperties.CoupleValue>();
        doit:
        for (int i = 0; i < n.nodeList.size(); ++i) {
            NodeSequence seq = (NodeSequence) n.nodeList.elementAt(i);
            if (((NodeChoice) seq.elementAt(0)).which == 0) {
                SymbolProperties saveProps = props;
                ((NodeChoice) seq.elementAt(0)).choice.accept(this);
                if (props != null) {
                    Cobol2Java.ExpressionString value1 = props.getValues().get(0).value1;
                    Cobol2Java.ExpressionString value2 = null;
                    a.add(saveProps.new CoupleValue(value1, value2));
                }
                props = saveProps;
                break doit;
            } else {
                seq.elementAt(0).accept(this);
                Cobol2Java.ExpressionString value1 = literal;
                Cobol2Java.ExpressionString value2 = null;
                if (((NodeOptional) seq.elementAt(2)).present()) {
                    NodeSequence seq2 = (NodeSequence) ((NodeOptional) seq.elementAt(2)).node;
                    seq2.elementAt(1).accept(this);
                    value2 = literal;
                }
                a.add(props.new CoupleValue(value1, value2));
            }
        }

        props.setValues(a);
    }

    @Override
    public void visit(LevelNumber n) {
        short lvl = Short.parseShort(n.nodeToken.tokenImage);
        props.setLevelNumber(lvl);
        super.visit(n);
    }

    @Override
    public void visit(QualifiedDataName n) {
        qualified = new Stack<String>();
        doQualified = true;
        super.visit(n);
        doQualified = false;
        processQualifiedStack(n);
    }

    private void processQualifiedStack(Node n) {

        SymbolProperties props2 = null;
        props = null;
        if (qualified == null || qualified.size() <= 0) {
            return;
        }
        String curr = null;
        String prev = null;
        curr = (String) qualified.pop();
        do {
            if (qualified.size() > 0) {
                prev = curr;
                curr = (String) qualified.pop();
                if (props2 != null) {
                    props2 = findChild(props2, curr);
                } else {
                    props2 = SymbolTable.getScope().lookup(curr, prev);
                }
                if (props2 == null) {
                    reportError(n, "Unknown Symbol : " + curr + " IN " + prev);
                    break;
                }
            } else {
                props2 = SymbolTable.getScope().lookup(curr);
                if (props2 == null) {
                    reportError(n, "Unknown Symbol : " + curr);
                    break;
                }
            }
            lastTokenString = curr;
            if (props2.isVaryingArray() && props2.getParent().isVarying()) {
                props2 = props2.getParent();
            }

        } while (qualified != null && qualified.size() > 0);

        props = (SymbolProperties) props2;//.clone();
        if (props2 != null) {
            props.setIndexesWorkSpace(null);//subscripts will fill this
            props.setSubstringWorkSpace(null);//LeftMost... and Length will fill this
            setRef(props);
        }
    }

    private SymbolProperties findChild(SymbolProperties props, String name) {
        if (props.getChildren() == null || props.getChildren().size() <= 0) {
            return null;
        }
        for (SymbolProperties ch : props.getChildren()) {
            if (ch.getDataName().equalsIgnoreCase(name)) {
                return ch;
            }
        }
        SymbolProperties ret = null;
        for (SymbolProperties ch : props.getChildren()) {
            ret = findChild(ch, name);
            if (ret != null) {
                return ret;
            }
        }
        return ret;
    }

    @Override
    public void visit(LeftmostCharacterPosition n) {
        SymbolProperties propsDataName = props;
        super.visit(n);
        props = propsDataName;
    }

    @Override
    public void visit(Length n) {
        SymbolProperties propsDataName = props;
        super.visit(n);
        props = propsDataName;
    }

    @Override
    public void visit(Identifier n) {
        super.visit(n);
    }
    private ArrayList<SymbolProperties> refList = new ArrayList<SymbolProperties>();
    private ArrayList<SymbolProperties> modList = new ArrayList<SymbolProperties>();

    @Override
    public void visit(DisplayStatement n) {
        super.visit(n);
        /*
        for(Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
        Node node = ((NodeSequence)e.nextElement()).elementAt(0);
        if (node instanceof NodeChoice) {
        NodeChoice nodechoice = (NodeChoice) node;
        switch(nodechoice.which) {
        case 0:
        nodechoice.accept(this);
        if(isStatementInError||props==null) return;
        setRef(props);
        if(props.getPictureString()!=null)
        props.setIsFormat(true);
        break;
        case 1:
        break;
        default:
        }
        }
        }
         */
    }
    private int expressionType = 0;

    @Override
    public void visit(ArithmeticExpression n) {
        expressionType = Constants.SHORT;
        super.visit(n);
    }

    private void formatLiteral(Cobol2Java.ExpressionString lit) {
        context.getCobol2Java().formatLiteral(lit);
        expressionType = context.getCobol2Java().expressionType;
        return;
    }

    @Override
    public void visit(Basis n) {
        super.visit(n);
        if (isStatementInError) {
            return;
        }
        if (props != null) {
            setRef(props);
        }
        //Here duplicating the code structure from Cobol2Java visit(Basis)
        switch (n.nodeChoice.which) {
            case 0:
                if (props == null) {
                    return;
                }
                String pic = (String) props.getPictureString();
                int type;
                if (pic == null) {
                    type = Constants.STRING;
                } else {
                    type = FieldFormat.verifyCobolPicture(pic);
                }
                switch (type) {
                    case Constants.SHORT:
                    case Constants.INTEGER:
                    case Constants.LONG:
                        if (expressionType == Constants.BIGDECIMAL) {
                            //setImportBigDecimalInProgram(SymbolTable.programs.peek());
                            break;
                        } else if (expressionType < type) {
                            expressionType = type;
                        }
                        break;
                    case Constants.BIGDECIMAL:
                        if (expressionType == Constants.BIGDECIMAL) {
                        } else if (expressionType < type) {
                            expressionType = type;
                        }
                        //setImportBigDecimalInProgram(SymbolTable.programs.peek());
                        break;
                    case Constants.STRING:
                    case Constants.GROUP:
                    case Constants.UNKNOWN:
                        expressionType = Constants.UNKNOWN;
                }
                break;//out of case 0
            case 1:
                int prevExpressionType = expressionType;
                formatLiteral(literal);
                if (prevExpressionType == Constants.BIGDECIMAL
                        || expressionType == Constants.BIGDECIMAL) {
                    //setImportBigDecimalInProgram(SymbolTable.programs.peek());
                } else if (prevExpressionType > Constants.BIGDECIMAL
                        || expressionType > Constants.BIGDECIMAL) {
                    expressionType = Constants.UNKNOWN;
                }
                break;
            default:
                break;
        }
    }

    @Override
    public void visit(ComputeStatement n) {
        expressionType = Constants.INTEGER;
        int lhsType = 0;
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            Node node = e.nextElement();
            node.accept(this);
            if (props == null) {
                return;
            }
            setMod(props);
            lhsType = Math.max(lhsType, FieldFormat.verifyCobolPicture(props.getPictureString()));
        }
        super.visit(n);
        /*
        n.arithmeticExpression.accept(this);
        if(expressionType<Constants.BIGDECIMAL&&lhsType==Constants.BIGDECIMAL) {
        //setImportBigDecimalInProgram(props);
        }
         */
    }

    private SymbolProperties findProgram(final SymbolProperties data) {
        SymbolProperties pgm = data;
        while (pgm != null && pgm.getType() != SymbolConstants.PROGRAM) {
            pgm = (SymbolProperties) pgm.getParent();
        }       
        return pgm;
    }

    @Override
    public void visit(AcceptStatement n) {
        n.identifier.accept(this);
        setMod(props);
        props = findProgram(props);
        if (props != null) {
            props.setImportLib(Boolean.TRUE);
        }
        //super.visit(n);
    }

    @Override
    public void visit(TimesDiv n) {
        super.visit(n);
    }

    @Override
    public void visit(Power n) {
        super.visit(n);
    }

    private void propagateRef(SymbolProperties node) {
        if (node == null || node.isProgram()) {
            return;
        }
        ref(node);
        propagateRefParents(node);
    }
    /*
    private void propagateRef(ArrayList<SymbolProperties> n) {
    if (n==null) return;int i=0;
    for(SymbolProperties child:n) {
    propagateRef(child);
    }
    }
     */

    private void propagateRef() {
        if (refList == null) {
            return;
        }
        for (SymbolProperties child : refList) {
            propagateRef(child);
        }
        refList.clear();
    }

    private void propagateMod() {
        if (modList == null) {
            return;
        }
        for (SymbolProperties child : modList) {
            propagateRef(child);
        }
        modList.clear();
    }

    private void propagateRefParents(SymbolProperties node) {
        if (node == null) {
            return;
        }
        boolean isToBe = node.getLevelNumber() == 1 || node.getLevelNumber() == 77 || node.getIsFiller() || node.isOccurs();
        while (node.getLevelNumber() != 1 && !node.isFile() && (node = (SymbolProperties) node.getParent()) != null) {
            if (isToBe || node.getLevelNumber() == 1 || node.getLevelNumber() == 77 || node.getIsFiller() || node.isOccurs()) {
                ref(node);
            }
        }
        if (node != null) {
            ref(node);
        }
        propagateRefChildren(node);
    }

    private void propagateRefChildren(SymbolProperties node) {
        if (node == null) {
            return;
        }
        if (node.getParent().isFile()) {
            ref(node.getParent());
        }
        if (node.getChildren() == null) {
            return;
        }
        boolean isToBe = node.getLevelNumber() == 1
                || node.getPictureString() != null
                || node.getLevelNumber() == 88
                || node.getLevelNumber() == 66
                || node.getLevelNumber() == 77;
        for (SymbolProperties child : node.getChildren()) {
            if (isToBe || child.getLevelNumber() == 1
                    || child.getPictureString() != null
                    || child.getLevelNumber() == 88
                    || child.getLevelNumber() == 66
                    || child.getLevelNumber() == 77) {
                ref(child);
            }
            propagateRefChildren(child);
        }
    }

    private void propagateMod(SymbolProperties node) {
        if (node == null || node.isProgram()) {
            return;
        }
        mod(node);
        propagateModParents(node);
    }

    /*
    private void propagateMod(ArrayList<SymbolProperties> n) {
    if (n==null) return;
    for(SymbolProperties child:n) {
    propagateMod(child);
    }
    }
     */
    private void propagateModParents(SymbolProperties node) {
        if (node == null) {
            return;
        }
        boolean isToBe = node.getLevelNumber() == 1 || node.getLevelNumber() == 77 || node.getIsFiller() || node.isOccurs();
        while (node.getLevelNumber() != 1 && !node.isFile() && (node = (SymbolProperties) node.getParent()) != null) {
            if (isToBe || node.getLevelNumber() == 1 || node.getIsFiller() || node.isOccurs()) {
                mod(node);
            }
        }
        if (node != null) {
            mod(node);
        }
        propagateModChildren(node);
    }

    private void propagateModChildren(SymbolProperties node) {
        if (node == null) {
            return;
        }
        if (node.getParent().isFile()) {
            mod(node.getParent());
        }
        if (node.getChildren() == null) {
            return;
        }
        boolean isToBe = node.getLevelNumber() == 1
                || node.getPictureString() != null
                || node.getLevelNumber() == 88
                || node.getLevelNumber() == 66
                || node.getLevelNumber() == 77;
        for (SymbolProperties child : node.getChildren()) {
            if (isToBe || child.getLevelNumber() == 1
                    || child.getPictureString() != null
                    || child.getLevelNumber() == 88
                    || child.getLevelNumber() == 66) {
                mod(child);
            }
            propagateModChildren(child);
        }
    }

    private void ref(SymbolProperties refSym) {
        if (refSym.getRef()) {
            return;
        }
        refSym.setRef(true);
        if (refSym.getRedefines() != null && !refSym.getRedefines().getRef()) {
            refSym.getRedefines().setRef(true);
            propagateRef(refSym.getRedefines());
        }
        if (refSym.getRedefinedBy() != null) {
            for (SymbolProperties t : refSym.getRedefinedBy()) {
                t.setRef(true);
                propagateRef(t);
            }
        }
        if (refSym.getIsFiller()) {
            propagateRef(refSym);
        }
    }

    private void mod(SymbolProperties modSym) {
        if (modSym.getMod()) {
            return;
        }
        modSym.setMod(true);
        if (modSym.getRedefines() != null && !modSym.getRedefines().getMod()) {
            modSym.getRedefines().setMod(true);
            propagateMod(modSym.getRedefines());
        }
        if (modSym.getRedefinedBy() != null) {
            for (SymbolProperties t : modSym.getRedefinedBy()) {
                t.setMod(true);
                propagateMod(t);
            }
        }
        if (modSym.getIsFiller()) {
            propagateMod(modSym);
        }
    }

    private void setRef(SymbolProperties refSym) {
        if (refSym == null) {
            return;
        }
        if (!refSym.getRef()) {
            ref(refSym);
            refList.add(refSym);
        }
    }

    private void setMod(SymbolProperties modSym) {
        if (modSym == null) {
            return;
        }
        if (!modSym.getMod()) {
            mod(modSym);
            modList.add(modSym);
        }
    }

    @Override
    public void visit(PerformVarying n) {
        n.identifier.accept(this);
        if (props == null) {
            return;
        }
        setMod(props);
        super.visit(n);
    }

    @Override
    public void visit(ConvertingPhrase n) {
        props = null;
        n.nodeChoice.accept(this);
        if (props != null) {
            setRef(props);
        }
        props = null;
        n.nodeChoice1.accept(this);
        if (props != null) {
            setRef(props);
        }
        n.nodeListOptional.accept(this);
    }

    @Override
    public void visit(PerformBody n) {
        super.visit(n);
    }

    @Override
    public void visit(PerformOption n) {
        props = null;
        if (n.nodeChoice.which == 0) {
            ((NodeSequence) n.nodeChoice.choice).elementAt(0).accept(this);
            if (props != null) {
                setRef(props);
            }
        } else {
            n.nodeChoice.choice.accept(this);
        }
    }

    @Override
    public void visit(InspectStatement n) {
        n.identifier.accept(this);
        if (isStatementInError || props == null) {
            return;
        }
        if (isGroupOrAlphanumeric(props)) {
            setRef(props);
            n.nodeChoice.accept(this);
        } else {
            reportError(n, props.getDataName() + " :Inspect Statement Data name must be Group or Alphannumeric.");
        }
    }

    @Override
    public void visit(ReplacingPhrase n) {
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeChoice nodechoice0 = (NodeChoice) e.nextElement();
            NodeSequence seq = (NodeSequence) nodechoice0.choice;
            if (nodechoice0.which == 0) {
                doInspectPhrase1(seq.elementAt(2));
                seq.elementAt(3).accept(this);
            } else {
                NodeList nodelist = (NodeList) seq.elementAt(1);
                for (Enumeration<Node> e2 = nodelist.elements(); e2.hasMoreElements();) {
                    NodeSequence seq2 = (NodeSequence) e2.nextElement();
                    doInspectPhrase1(seq2.elementAt(0));
                    doInspectPhrase1(seq2.elementAt(2));
                    seq2.elementAt(3).accept(this);
                }
            }
        }
    }

    public void reportError(Node n, String msg) {
        isStatementInError = true;
        RESConfig.getInstance().setInError(true);
        System.out.println("@CobolSourceFile(\"" + ((RESNode) n).sourceFile + "\"," + String.valueOf(firstTokenInStatement.beginLine) + "):" + msg);
    }

    public void reportError(String msg) {
        isStatementInError = true;
        RESConfig.getInstance().setInError(true);
        System.out.println("@CobolSourceFile():" + msg);
    }

    private void doInspectPhrase1(Node n) {
        props = null;
        literal = null;
        n.accept(this);
        if (props != null) {
            if (!isGroupOrAlphanumeric(props)) {
                reportError(n, props.getDataName() + " :Inspect pharase must specify a group or alphanumeric");
                return;
            } else if (isStatementInError) {
                return;
            }
            setRef(props);
        } else {
        }
    }

    @Override
    public void visit(TallyingPhrase n) {
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeSequence seq = (NodeSequence) e.nextElement();
            seq.elementAt(0).accept(this);
            if (!isIntegerElement(props)) {
                reportError(n, props.getDataName() + " :Inspect Statement Tallying Counter must be an Integer element");
                return;
            }
            setMod(props);
            NodeList nodelist = (NodeList) seq.elementAt(2);
            for (Enumeration<Node> e2 = nodelist.elements(); e2.hasMoreElements();) {
                NodeChoice nodechoice = (NodeChoice) e2.nextElement();
                if (nodechoice.which == 0) {
                    nodechoice.choice.accept(this);
                } else {
                    NodeSequence seq2 = (NodeSequence) nodechoice.choice;
                    NodeList list = (NodeList) seq2.elementAt(1);
                    for (Enumeration<Node> e3 = list.elements(); e3.hasMoreElements();) {
                        NodeSequence seq3 = (NodeSequence) e3.nextElement();
                        doInspectPhrase1(seq3.elementAt(0));
                        seq3.elementAt(1).accept(this);
                    }
                }
            }
        }
        n.nodeOptional.accept(this);
    }

    @Override
    public void visit(BeforeAfterPhrase n) {
        doInspectPhrase1(n.nodeChoice1);
    }

    @Override
    public void visit(SetStatement n) {
        props = null;
        for (Enumeration<Node> e0 = n.nodeList.elements(); e0.hasMoreElements();) {
            NodeSequence nodeSequence  = (NodeSequence) e0.nextElement();
            nodeSequence.elementAt(1).accept(this);
            setRef(props);
            for (Enumeration<Node> e = ((NodeList)nodeSequence.elementAt(0))
                    .elements(); e.hasMoreElements();) {
                e.nextElement().accept(this);
                if (props == null) {
                    continue;
                }
                setMod(props);props=null;
            }
        }
     }

    @Override
    public void visit(AbbreviationLeaf n) {
        super.visit(n);
    }

    @Override
    public void visit(AbbreviationRest n) {
        super.visit(n);
    }

    @Override
    public void visit(ConditionNameReference n) {
        qualified.clear();
        doQualified = true;
        n.conditionName.accept(this);
        switch (n.nodeChoice.which) {
            case 0:
                NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
                nodeseq.elementAt(0).accept(this);
                nodeseq.elementAt(1).accept(this);
                doQualified = false;
                processQualifiedStack(n);
                setRef(props);
                nodeseq.elementAt(2).accept(this);
                break;
            case 1:
                n.nodeChoice.choice.accept(this);
                doQualified = false;
                processQualifiedStack(n);
                setRef(props);
        }
    }

    @Override
    public void visit(RelationCondition n) {
        super.visit(n);
    }

    @Override
    public void visit(ClassCondition n) {
        super.visit(n.identifier);
        if (isStatementInError || props == null) {
            return;
        }
        setRef(props);
        switch (n.nodeChoice.which) {
            case 0:
                props.setNumericTested(true);
                break;
            case 1:
                props.setAlphabeticTested(true);
                break;
            case 2:
                props.setAlphabeticLowerTested(true);
                break;
            case 3:
                props.setAlphabeticUpperTested(true);
                break;
            case 4:
            //TODO implement ClassName in Env Section.
            case 5:
            //TODO implement DBCS test.
            case 6:
            //TODO implement KANJI test.
            default:
            //Why would I come here?
        }
    }

    private boolean isGroupOrAlphanumeric(SymbolProperties pr) {
        if ((props.getPictureString() == null && props.getChildren() != null && props.getChildren().size() > 0) ||//Group
                FieldFormat.verifyCobolPicture(props.getPictureString()) == Constants.STRING) {//Alphanumeric
            return true;
        }
        return false;
    }

    private boolean isIntegerElement(SymbolProperties pr) {
        if (props.getPictureString() != null
                && FieldFormat.verifyCobolPicture(props.getPictureString()) <= Constants.LONG) {
            return true;
        }
        return false;
    }

    @Override
    public void visit(ExecSqlStatement n) {
        context.setSqlTranslated(true);
        doingExecSQL = true;
        super.visit(n);
        doingExecSQL = false;
    }

    @Override
    public void visit(StringStatement n) {
        n.identifier.accept(this);
        if (props == null) {
            return;
        }
        setMod(props);
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeSequence nodeseq = (NodeSequence) e.nextElement();
            if (((NodeOptional) nodeseq.elementAt(1)).present()) {
                NodeSequence opt = (NodeSequence) ((NodeOptional) nodeseq.elementAt(1)).node;
                NodeChoice nodech = (NodeChoice) opt.elementAt(2);
                switch (nodech.which) {
                    case 0:
                        nodech.accept(this);
                        setRef(props);
                        break;
                    case 1:
                }
            }
            for (Enumeration<Node> e2 = ((NodeList) nodeseq.elementAt(0)).elements(); e2.hasMoreElements();) {
                props = null;
                literal = null;
                NodeChoice nodechoice = (NodeChoice) e2.nextElement();
                switch (nodechoice.which) {
                    case 0:
                        nodechoice.accept(this);
                        setRef(props);//props.setIsFormat(true);
                        break;
                    case 1:
                }

            }
        }
    }

    @Override
    public void visit(UnstringStatement n) {
        n.identifier.accept(this);
        if (props == null) {
            return;
        }
        setRef(props);
        if (n.nodeOptional.present()) {
            props = null;
            literal = null;
            NodeSequence nodeseq = (NodeSequence) n.nodeOptional.node;

            if (((NodeChoice) nodeseq.elementAt(3)).which == 0) {
                nodeseq.elementAt(3).accept(this);
            }
            if (props != null) {
                setRef(props);
            }
            NodeListOptional orList = (NodeListOptional) nodeseq.elementAt(4);
            if (orList.present()) {
                for (Enumeration<Node> e = orList.elements(); e.hasMoreElements();) {
                    NodeSequence nodeseq2 = (NodeSequence) e.nextElement();
                    if (((NodeChoice) nodeseq2.elementAt(2)).which == 0) {
                        nodeseq2.elementAt(2).accept(this);
                    }
                    if (props != null) {
                        setRef(props);
                    }
                }
            }
        }
        /////
        for (Enumeration<Node> e2 = n.nodeList.elements(); e2.hasMoreElements();) {
            NodeSequence nodeseq3 = (NodeSequence) e2.nextElement();
            nodeseq3.elementAt(0).accept(this);
            setMod(props);
            NodeOptional opt = (NodeOptional) nodeseq3.elementAt(1);
            if (opt.present()) {
                setMod(props);
            }
            opt = (NodeOptional) nodeseq3.elementAt(2);
            if (opt.present()) {
                setMod(props);
            }
        }

        if (n.nodeOptional2.present()) {
            n.nodeOptional2.accept(this);
            setMod(props);
        }

        if (n.nodeOptional3.present()) {//On OverFlow
            n.nodeOptional3.accept(this);
        }
        if (n.nodeOptional4.present()) {//Not On OverFlow
            n.nodeOptional4.accept(this);
        }


    }

    @Override
    public void visit(OpenStatement n) {
        boolean inp = false, op = false, iop = false, ext = false;
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeChoice nodech = (NodeChoice) e.nextElement();
            NodeSequence nodeseq = (NodeSequence) nodech.choice;
            switch (((NodeToken) nodeseq.elementAt(0)).kind) {
                case CobolParserConstants.INPUT:
                    inp = true;
                    break;
                case CobolParserConstants.OUTPUT:
                    op = true;
                    break;
                case CobolParserConstants.INPUT_OUTPUT:
                case CobolParserConstants.I_O:
                    iop = true;
                    break;
                case CobolParserConstants.EXTEND:
                    ext = true;
                    break;
                default:
            }

            for (Enumeration<Node> e2 = ((NodeList) nodeseq.elementAt(1)).elements();
                    e2.hasMoreElements();) {
                isStatementInError = false;
                e2.nextElement().accept(this);
                if (isStatementInError || props == null) {
                    continue;
                }
                props.setFileOpenedInput(props.isFileOpenedInput() || inp);
                props.setFileOpenedOutput(props.isFileOpenedOutput() || op);
                props.setFileOpenedIO(props.isFileOpenedIO() || iop);
                props.setFileOpenedExtend(props.isFileOpenedExtend() || ext);
                if (inp || iop) {
                    setRef(props);
                }
                if (op || iop || ext) {
                    setMod(props);
                }

            }
            inp = op = iop = ext = false;
        }
    }

    @Override
    public void visit(ReadStatement n) {
        n.fileName.accept(this);
        if (props == null) {
            return;
        }
        setRef(props);
        for (SymbolProperties ch : props.getChildren()) {
            setMod(ch);
        }
        if (n.nodeOptional2.present()) {
            n.nodeOptional2.accept(this);
            setMod(props);
        }
        n.nodeOptional4.accept(this);
        n.nodeOptional5.accept(this);
        n.nodeOptional6.accept(this);
        n.nodeOptional7.accept(this);
    }

    @Override
    public void visit(WriteStatement n) {
        n.recordName.accept(this);
        if (props == null) {
            return;
        }
        setMod(props);
        if (n.nodeOptional.present()) {
            props = null;
            n.nodeOptional.accept(this);
            if (props != null) {
                setRef(props);
            }
        }
        if (n.nodeOptional1.present()) {
            props = null;
            n.nodeOptional1.accept(this);
            if (props != null) {
                setRef(props);
            }
        }
        n.nodeOptional2.accept(this);
        n.nodeOptional3.accept(this);
        n.nodeOptional4.accept(this);
        n.nodeOptional5.accept(this);
    }

    @Override
    public void visit(RewriteStatement n) {
        n.recordName.accept(this);
        if (props == null) {
            return;
        }
        setMod(props);
        if (n.nodeOptional.present()) {
            props = null;
            n.nodeOptional.accept(this);
            if (props != null) {
                setRef(props);
            }
        }
        if (n.nodeOptional1.present()) {
            props = null;
            n.nodeOptional1.accept(this);
            if (props != null) {
                setRef(props);
            }
        }
        n.nodeOptional1.accept(this);
        n.nodeOptional2.accept(this);
    }
    public NodeToken firstTokenInStatement = null;

    @Override
    public void visit(Statement n) {
        if (context.getTraceLevel() >= 2) {
            System.out.println("Doing CobolFillTable Statement " + n.line);
        }

        firstTokenInStatement = null;
        isStatementInError = false;
        //if(refList==null)
        //refList=new Stack<ArrayList>();
        //if(modList==null)
        //modList=new Stack<ArrayList>();
        //refList.push(new ArrayList());
        //modList.push(new ArrayList());

        super.visit(n);
        if (isStatementInError) {
            n.deadStatement = true;
            return;
        }
        if (refList != null && refList.size() > 0) {
            if (n.ref == null) {
                n.ref = new ArrayList<Object>();
            }
            //a=refList.pop();
            //n.ref.addAll(a);
            propagateRef();
        }
        if (modList != null && modList.size() > 0) {
            if (n.mod == null) {
                n.mod = new ArrayList<Object>();
            }
            //a=modList.pop();
            //n.mod.addAll(a);
            propagateMod();
        }
    }

    @Override
    public void visit(FileControlClause n) {
        super.visit(n);
    }

    @Override
    public void visit(AssignClause n) {
        n.nodeChoice.accept(this);
        if (props != null && props.getType() == SymbolConstants.FILE) {
            if (lastTokenString.charAt(0) != '\"' && lastTokenString.charAt(0) != '\'') {
                lastTokenString = '\"' + lastTokenString + '\"';
            }
            props.setOtherName(lastTokenString.toUpperCase());
        }
    }

    @Override
    public void visit(SelectClause n) {
        n.fileName.accept(this);

    }

    @Override
    public void visit(FileName n) {
        super.visit(n);
        props = SymbolTable.getScope().lookup(lastTokenString, SymbolConstants.FILE);
        if (props != null) {
            props.setRef(true);
            propagateRef(props);
        }
    }

    @Override
    public void visit(FileStatusClause n) {
        SymbolProperties saveProps = props;
        props = null;
        n.qualifiedDataName.accept(this);
        if (saveProps != null && props != null) {
            if (saveProps.getFileStatus() == null) {
                saveProps.setFileStatus(new ArrayList<SymbolProperties>());
            }
            saveProps.getFileStatus().add(props);
            props.setMod(true);
            propagateRef(props);
        }
        props = saveProps;
    }

    @Override
    public void visit(OrganizationClause n) {
        if (props == null) {
            reportError(n, "Unknown Symbol: " + lastTokenString);
        } else {
            props.setDataUsage((short) n.nodeChoice.which);
        }
    }

    @Override
    public void visit(InputOutputSectionParagraph n) {
        // TODO Auto-generated method stub
        super.visit(n);
    }

    @Override
    public void visit(InputOutputSection n) {
        // TODO Auto-generated method stub
        super.visit(n);
    }

    @Override
    public void visit(EnvironmentSection n) {
        // TODO Auto-generated method stub
        super.visit(n);
    }

    @Override
    public void visit(EnvironmentDivision n) {
        super.visit(n);
    }
    private long dataRenameMark = 0;

    private SymbolProperties findValidParent(SymbolProperties ch) {
        if (ch.is01Group()) {
            return SymbolTable.getScope().getFirstProgram();
        }
        do {
            ch = ch.getParent();
        } while (ch != null && ch.getIsFiller() && !ch.isProgram());
        return ch;
    }

    private boolean checkChildExists(SymbolProperties ch, SymbolProperties par) {
        if (ch.getParent() == null || ch == null || ch.getIsFiller()) {
            return false;
        }
        SymbolProperties symbol = null;
        do {
            if (par == null) {
                break;
            }
            symbol = SymbolTable.getScope().lookup(ch.getDataName(), par.getDataName());
            par = par.getParent();
        } while (par != null);
        if (symbol != null) {
            return true;
        }
        return false;
    }

    private void adjustSetJavaName(SymbolProperties p) {
        if (p.isFromRESLibrary()) {
            p.setJavaName1(NameUtil.convertCobolNameToJava(p.getDataName(), false) + "__");
            p.setJavaName2(NameUtil.convertCobolNameToJava(p.getDataName(), true) + "__");
            return;
        }
        if (p.isIndexRedefines()) {
            p.setJavaName1(p.getRedefines().getJavaName1());
            p.setJavaName2(p.getRedefines().getJavaName2());
            p.setRef(false);
            p.setMod(false);
            return;
        }
        boolean childExists = checkChildExists(p, findValidParent(p));
        String saveDataName = p.getDataName().replace('.', '-');
        boolean isData = !(p.getType() == SymbolConstants.PROGRAM);
        String javaName = NameUtil.convertCobolNameToJava(p.getDataName(), false);
        char ch = javaName.charAt(0);
        if (childExists) {
            javaName += "_" + String.valueOf(++dataRenameMark);
        }
        if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')); else {
            javaName = "_" + javaName;
        }
        if (isInGroupDictionary(javaName, p.getParent())) {
            javaName += new Integer(SymbolTable.duplicateJavaNameMark++).toString().trim();
        }
        addToGroupDictionary(javaName, p.getParent());
        p.setJavaName1(javaName);
        javaName = NameUtil.convertCobolNameToJava(p.getDataName(), true);
        ch = javaName.charAt(0);
        if (childExists) {
            javaName += "_" + String.valueOf(dataRenameMark);
        }
        if ((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')); else {
            javaName = "_" + javaName;
        }

        if (isInGroupDictionary(javaName, p.getParent())) {
            javaName += new Integer(SymbolTable.duplicateJavaNameMark++).toString().trim();
        }
        addToGroupDictionary(javaName, p.getParent());
        p.setJavaName2(javaName);
        p.setDataName(saveDataName);

        if (p.getType() == SymbolConstants.PROGRAM || (p.getLevelNumber() == 1 && p.getPictureString() == null)) {
            p.setDoWriteClassFile(true);
            if (!RESConfig.getInstance().isOverwriteJavaFiles()) {
                if (Files.exists(p, isData)) {
                    p.setDoWriteClassFile(false);
                } else {
                    p.setDoWriteClassFile(true);
                }
                if (!p.isDoWriteClassFile()) {
                    System.out.println("Name " + p.getDataName() + " exists. Not overwritten.");
                }
            }
        }
    }
    //Singleton COnstructors
    private static CobolFillTable thiz = null;
    private static RESContext context = null;

    private CobolFillTable() {
    }

    public static CobolFillTable getInstance(RESContext ctx) {
        if (thiz == null) {            
            context = ctx;
            thiz = new CobolFillTable();
        }
        return thiz;
    }

    public static void clear() {
        thiz=null;
        context=null;
    }

    @Override
    public void visit(CallStatement n) {
        props = null;
        n.nodeChoice.choice.accept(this);
        if (props != null) {
            setRef(props);
        }
        n.nodeOptional.accept(this);
    }

    @Override
    public void visit(CallByContentArgs n) {
        props = null;
        n.nodeChoice.choice.accept(this);
        if (props != null) {
            setRef(props);
        }
    }

    @Override
    public void visit(CallByReferenceArgs n) {
        props = null;
        n.nodeChoice.choice.accept(this);
        if (props != null) {
            setRef(props);
            setMod(props);
        }
    }

    @Override
    public void visit(InitializeStatement n) {
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            e.nextElement().accept(this);
            if (props != null) {
                setMod(props);
            }
        }
        if (n.nodeOptional.present()) {
            NodeSequence nodeseq = (NodeSequence) n.nodeOptional.node;
            for (Enumeration<Node> e = ((NodeList) nodeseq.elementAt(1)).elements(); e.hasMoreElements();) {
                props = null;
                e.nextElement().accept(this);
                if (props != null) {
                    setRef(props);
                }
            }
        }
    }
    
    @Override
    public void visit(Declaratives n) {
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeSequence nodeseq = (NodeSequence) e.nextElement();
            popToProgram();
            if (!doUseStatementsInDeclaratives) {
                ((SectionHeader) nodeseq.elementAt(0)).accept(this);
                if ((sectionProps = createSection()) == null) {
                    reportError(n, "Duplicate Section in Declaratives: " + sectionName);
                }
                nodeseq.elementAt(4).accept(this);
            } else {
                nodeseq.elementAt(2).accept(this);
            }
        }
    }

    @Override
    public void visit(FileAndSortDescriptionEntryClause n) {
        super.visit(n);
    }

    @Override
    public void visit(IntrinsicFunction n) {
        super.visit(n);
    }

    @Override
    public void visit(SearchStatement n) {
        n.qualifiedDataName.accept(this);
        if (!props.isOccurs()) {
            reportError(n, "Search Statement is valid only on tables with Occurs clause.");
        }
        if (props.getMajorIndex() == null) {
            reportError(n, "Search Statement is valid only on tables with INDEXED BY.");
        }
        setRef(props);
        props = null;
        n.nodeOptional1.accept(this);
        setMod(props);
        n.nodeOptional2.accept(this);
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            NodeSequence nodeseq = (NodeSequence) e.nextElement();
            nodeseq.elementAt(1).accept(this);
            nodeseq.elementAt(2).accept(this);
        }
    }

    @Override
    public void visit(CancelStatement n) {
        for (Enumeration<Node> e = n.nodeList.elements(); e.hasMoreElements();) {
            props = null;
            literal = null;
            e.nextElement().accept(this);
            if (props != null) {
                setRef(props);
            }
        }
    }

    @Override
    public void visit(CommunicationInputClause n) {
        insertDummyData = true;
        super.visit(n);
        insertDummyData = false;
    }
    private boolean insertDummyData = false;

    @Override
    public void visit(CommunicationIOClause n) {
        insertDummyData = true;
        super.visit(n);
        insertDummyData = false;
    }

    @Override
    public void visit(CommunicationOutputClause n) {
        insertDummyData = true;
        super.visit(n);
        insertDummyData = false;
    }
}
 public class CobolRecode extends DepthFirstVisitor {

	private CobolRecode() {}
	private static CobolRecode thiz = null;
        private static RESContext context = null;
	public static CobolRecode getInstance(RESContext ctx) {
		if(thiz==null)  {
                    context = ctx;
                    thiz = new CobolRecode();
            }
		return thiz;
	}
	public static void clear() { thiz = null;context = null; }
	private Stack<Boolean> nextStatementDead = new Stack<Boolean>();
	private boolean lastStatementDead=false;
	private int paraStatementCount=0,sectionStatementCount=0;
	
	@Override
	public void visit(ProcedureSection n) {
		n.sectionHeader.sectionName.accept(this);
		sectionStatementCount=0;
		//String sectionName=lastTokenString;
		super.visit(n);
		//if(sectionStatementCount<=RESConfig.getInstance().getInlineStatement()){
			//props=SymbolTable.getScope().lookup(sectionName,SymbolConstants.SECTION);
			//if(props!=null) props.setConsolidateParagraph(true);
		//}
	}

	@Override
	public void visit(GotoStatement n) {
		NodeOptional nodeopt=(NodeOptional)((NodeSequence)n.nodeChoice.choice).elementAt(1);
		if(!nodeopt.present()) {
			
			if (nextStatementDead.size()>0)
				nextStatementDead.set(nextStatementDead.size()-1, true);
			else
				nextStatementDead.push(true);
			super.visit(n);
			((NodeSequence)n.nodeChoice.choice).elementAt(0).accept(this);
			props=SymbolTable.getScope().lookup(lastTokenString);
			if(props!=null) { 
				props.setGotoTarget(true);
			}
		} else {
			NodeListOptional nodelistopt=(NodeListOptional) ((NodeSequence)nodeopt.node).elementAt(0);
			for(Enumeration<Node> e=nodelistopt.elements();e.hasMoreElements();) {
				e.nextElement().accept(this);
				props=SymbolTable.getScope().lookup(lastTokenString);
				if(props!=null) { 
					props.setGotoTarget(true);
				}
			}

		}
	}
	
	@Override
	public void visit(ProcedureName n) {
		((NodeSequence)n.nodeChoice.choice).elementAt(0).accept(this);
	}

	@Override
	public void visit(Paragraph n) {
		//n.paragraphName.accept(this);
		//String paragraphName=lastTokenString;
		paraStatementCount=0;
		nextStatementDead.push(false);
		super.visit(n);
		/*
		if(paraStatementCount<=RESConfig.getInstance().getInlineStatement()){
			props=SymbolTable.getScope().lookup(paragraphName,SymbolConstants.PARAGRAPH);
			if(props!=null) { 
				props.setConsolidateParagraph(true);
				props.setOtherData2(n.nodeChoice);
			}
		}
		*/
		n.deadStatement=nextStatementDead.pop();
	}

	private String lastTokenString = null;
	private SymbolProperties props = null;
	
	@Override
	public void visit(NodeToken n) {
		lastTokenString=n.tokenImage;
	}


	@Override
	public void visit(UnstringStatement n) {
		boolean onOverflowTailDead=false,notOnOverflowTailDead=false;

		n.nodeOptional3.accept(this);
		
		onOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		n.nodeOptional4.accept(this);
		notOnOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		if(notOnOverflowTailDead&&onOverflowTailDead)
			if (nextStatementDead.size()>0)
				nextStatementDead.set(nextStatementDead.size()-1, true);
			else
				lastStatementDead=true;
	
	}

	@Override
	public void visit(IfStatement n) {
		boolean ifTailDead=false;boolean elseTailDead=false;
		switch(n.nodeChoice.which) {
		case 0:
			NodeSequence seq =(NodeSequence)n.nodeChoice.choice;
			seq.elementAt(0).accept(this);
			break;
		case 1:
		default:
		}
		
		ifTailDead=lastStatementDead;
		lastStatementDead=false;
		
		if(n.nodeOptional1.present()) {
			if (n.nodeOptional1.node instanceof NodeSequence) {
				NodeSequence nodeseq=(NodeSequence)n.nodeOptional1.node;
				NodeChoice choice= (NodeChoice)nodeseq.elementAt(1);
				switch(choice.which) {
				case 0:
					NodeSequence seq =(NodeSequence)choice.choice;
					seq.elementAt(0).accept(this);
					break;
				case 1:
				default:
				}
				elseTailDead=lastStatementDead;
			}
		}
		
		if(ifTailDead&&elseTailDead)
			if (nextStatementDead.size()>0)
				nextStatementDead.set(nextStatementDead.size()-1, true);
			else
				lastStatementDead=true;
	}

	@Override
	public void visit(Statement n) {
		
		if(context.getTraceLevel()>=2) {
			System.out.println("Doing CobolRecode statement "+n.line);
		}
		
		if(n.nodeChoice.choice instanceof ReadStatement||n.nodeChoice.choice instanceof ExecSqlStatement) {
			boolean deadAlready=(nextStatementDead.size()>0)?nextStatementDead.peek().booleanValue():false;
			nextStatementDead.push(deadAlready);
		}
		else
		n.deadStatement=(nextStatementDead.size()>0)?nextStatementDead.peek().booleanValue():false;
		if(!n.deadStatement) {
			paraStatementCount++;sectionStatementCount++;
		}
		super.visit(n);
		lastStatementDead=(nextStatementDead.size()>0)?nextStatementDead.peek().booleanValue():false;
		if(n.nodeChoice.choice instanceof ReadStatement||n.nodeChoice.choice instanceof ExecSqlStatement) 
			nextStatementDead.pop();
	}

	@Override
	public void visit(StatementList n) {
		boolean deadAlready=(nextStatementDead.size()>0)?nextStatementDead.peek().booleanValue():false;
		nextStatementDead.push(deadAlready);
		super.visit(n);
		nextStatementDead.pop();
	}

	@Override
	public void visit(StopStatement n) {
		super.visit(n);
	}

	@Override
	public void visit(SubtractStatement n) {
		//Interpret Overflow as Size Error
		boolean onOverflowTailDead=false,notOnOverflowTailDead=false;

		n.nodeOptional.accept(this);
		
		onOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		n.nodeOptional1.accept(this);
		notOnOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		if(notOnOverflowTailDead&&onOverflowTailDead)
			if (nextStatementDead.size()>0)
				nextStatementDead.set(nextStatementDead.size()-1, true);
			else
				lastStatementDead=true;
	
	}

	@Override
	public void visit(DivideStatement n) {
		//Interpret Overflow as Size Error
		boolean onOverflowTailDead=false,notOnOverflowTailDead=false;

		n.nodeOptional.accept(this);
		
		onOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		n.nodeOptional1.accept(this);
		notOnOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		if(notOnOverflowTailDead&&onOverflowTailDead)
			if (nextStatementDead.size()>0)
				nextStatementDead.set(nextStatementDead.size()-1, true);
			else
				lastStatementDead=true;
	
	
	}

	@Override
	public void visit(MultiplyStatement n) {
		//Interpret Overflow as Size Error
		boolean onOverflowTailDead=false,notOnOverflowTailDead=false;

		n.nodeOptional.accept(this);
		
		onOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		n.nodeOptional1.accept(this);
		notOnOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		if(notOnOverflowTailDead&&onOverflowTailDead)
			if (nextStatementDead.size()>0)
				nextStatementDead.set(nextStatementDead.size()-1, true);
			else
				lastStatementDead=true;
	
		}

	@Override
	public void visit(ComputeStatement n) {
		//Interpret Overflow as Size Error
		boolean onOverflowTailDead=false,notOnOverflowTailDead=false;

		n.nodeOptional.accept(this);
		
		onOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		n.nodeOptional1.accept(this);
		notOnOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		if(notOnOverflowTailDead&&onOverflowTailDead)
			if (nextStatementDead.size()>0)
				nextStatementDead.set(nextStatementDead.size()-1, true);
			else
				lastStatementDead=true;
	
		}

	@Override
	public void visit(AddStatement n) {
		//Interpret Overflow as Size Error
		boolean onOverflowTailDead=false,notOnOverflowTailDead=false;

		n.nodeOptional.accept(this);
		
		onOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		n.nodeOptional1.accept(this);
		notOnOverflowTailDead=lastStatementDead;
		lastStatementDead=false;
		
		if(notOnOverflowTailDead&&onOverflowTailDead)
			if (nextStatementDead.size()>0)
				nextStatementDead.set(nextStatementDead.size()-1, true);
			else
				lastStatementDead=true;
	
	}

	@Override
	public void visit(SearchStatement n) {
		n.nodeOptional2.accept(this);
		boolean searchMakesNextDead = lastStatementDead;
		for(Enumeration<Node> e=n.nodeList.elements();e.hasMoreElements();) {
			NodeSequence nodeseq =  (NodeSequence)e.nextElement();
			nodeseq.elementAt(1).accept(this);
			NodeChoice nodech = (NodeChoice) nodeseq.elementAt(2);
			if(nodech.which==0) {
				nodech.accept(this);
				searchMakesNextDead&=lastStatementDead;
			} else {
				searchMakesNextDead=false;
			}
		}
		
		if(searchMakesNextDead)
			if (nextStatementDead.size()>0)
				nextStatementDead.set(nextStatementDead.size()-1, true);
			else
				lastStatementDead=true;
	}

	@Override
	public void visit(AlterStatement n) {
			for(Enumeration<Node> e=n.nodeList.elements();e.hasMoreElements();) {
				NodeSequence nodeseq=(NodeSequence)e.nextElement();
				nodeseq.elementAt(0).accept(this);
				props=SymbolTable.getScope().lookup(lastTokenString);
				if(props!=null)
					props.setAlteredParagraph(true);
			}
	}


}
 public class TranUtil {

    private static TranUtil thiz = null;

    private TranUtil() {
    }

    public static TranUtil get() {
        if (thiz == null) {
            thiz = new TranUtil();
        }
        return thiz;
    }

    public static void clear() {
        thiz = null;
    }

    public ArrayList<String> getParameters(String sqlString, boolean extendedPattern) {
        ArrayList<String> ret = new ArrayList<String>();
        StringTokenizerEx aStringTokenizerEx = null;
        if (!extendedPattern) {
            aStringTokenizerEx = new StringTokenizerEx(" " + sqlString + " ", ":[ ]*[a-zA-Z0-9\\-\\.]+([ \t\r\n]*:[ ]*[a-zA-Z0-9\\-\\.]+)?");
        } else {
            aStringTokenizerEx = new StringTokenizerEx(" " + sqlString + " ", "[:]?[ ]*[a-zA-Z0-9\\-\\.]+([ \t\r\n]*:[ ]*[a-zA-Z0-9\\-\\.]+)?");
        }
        @SuppressWarnings("unused")
        final String firstDelimiter = aStringTokenizerEx.getDelimiter();
        for (@SuppressWarnings("unused") String aString : aStringTokenizerEx) {
            // uses the split String detected and memorized in 'aString'
            ret.add(aStringTokenizerEx.getDelimiter());
        }

        return ret;
    }

    //parmWithOptionalIndiacator is of the format :data-name:indicator or :data-name
    public SymbolProperties getParameter(String parmWithOptionalIndiacator) {
        int j;
        String parm;
        if (parmWithOptionalIndiacator == null
                || (parmWithOptionalIndiacator = parmWithOptionalIndiacator.trim()).length() <= 0) {
            return null;
        }
        if (parmWithOptionalIndiacator.charAt(0) != ':') {
            if (((j = parmWithOptionalIndiacator.indexOf(':', 1)) < 0)) {
                parm = parmWithOptionalIndiacator.substring(0);
            } else {
                parm = parmWithOptionalIndiacator.substring(0, j);
            }
        } else if (((j = parmWithOptionalIndiacator.indexOf(':', 1)) < 0)) {
            parm = parmWithOptionalIndiacator.substring(1);
        } else {
            parm = parmWithOptionalIndiacator.substring(1, j);
        }
        return SymbolTable.getScope().lookup(parm.trim(), SymbolConstants.DATA);
    }

    public SymbolProperties getIndicator(String parmWithOptionalIndiacator) {
        int j;
        String ind;
        if (parmWithOptionalIndiacator == null
                || (parmWithOptionalIndiacator = parmWithOptionalIndiacator.trim()).length() <= 0) {
            return null;
        }
        if (parmWithOptionalIndiacator.charAt(0) != ':') {
            if (((j = parmWithOptionalIndiacator.indexOf(':', 1)) < 0)) {
                return null;
            } else {
                ind = parmWithOptionalIndiacator.substring(j + 1).trim();
            }
        } else if (((j = parmWithOptionalIndiacator.indexOf(':', 1)) < 0)) {
            return null;
        } else {
            ind = parmWithOptionalIndiacator.substring(j + 1).trim();
        }
        return SymbolTable.getScope().lookup(ind, SymbolConstants.DATA);
    }
    private boolean previousError = false;
    private Properties dbProps = null;

    public void printIndexedFileDatabaseProperties(SymbolProperties props) {
        if (previousError || !RESConfig.getInstance().isToGenVSAMISAMDb()) {
            return;
        }
        if (dbProps == null) {
            if (RESConfig.getInstance().getOutputDir().length() <= 0) {
                RESConfig.getInstance().setOutputDir("." + File.separatorChar);
            } else if (RESConfig.getInstance().getOutputDir().charAt(
                    RESConfig.getInstance().getOutputDir().length() - 1) != File.separatorChar) {
                RESConfig.getInstance().setOutputDir(RESConfig.getInstance().getOutputDir() + File.separatorChar);
            }
            File dbPropsFile = new File(RESConfig.getInstance().getOutputDir() + "Database.properties");
            dbProps = new Properties();
            if (dbPropsFile.exists()) {
                if (dbPropsFile.canRead() && dbPropsFile.canWrite()) {
                    if (!RESConfig.getInstance().isOverwriteJavaFiles()) {
                        previousError = true;
                        RunTimeUtil.getInstance().reportError("Database.properties can not be overwritten.Try -overwrite option.", false);
                        return;
                    }
                    try {
                        dbProps.loadFromXML(new FileInputStream(dbPropsFile));
                    } catch (InvalidPropertiesFormatException e) {
                        previousError = true;
                        RunTimeUtil.getInstance().reportError("Database.properties can not be loaded.", false);
                        return;
                    } catch (FileNotFoundException e) {
                        previousError = true;
                        RunTimeUtil.getInstance().reportError("Database.properties can not be loaded.", false);
                        return;
                    } catch (IOException e) {
                        previousError = true;
                        RunTimeUtil.getInstance().reportError("Database.properties can not be loaded.", false);
                        return;
                    }
                } else {
                    previousError = true;
                    RunTimeUtil.getInstance().reportError("Database.properties can not be read/written.", false);
                    return;
                }
            }
        }

        String fileName = NameUtil.convertCobolNameToSQL(props.getOtherName());

//		if(RESConfig.getInstance().isOverwriteJavaFiles()) {
        //SymbolProperties primKey=SymbolTable.getScope().lookup(,props.getChildren().get(0).getDataName());
        ArrayList<String> altKeyList = new ArrayList<String>();
        StringBuffer altKey = new StringBuffer();
        StringBuffer altKeys = new StringBuffer();
        StringBuffer altKeys2 = new StringBuffer();
        StringBuffer altKeys3 = new StringBuffer();
        if (props.getOtherData() != null && props.getOtherData().size() > 0) {
            for (Object o : props.getOtherData()) {
                SymbolProperties os = (SymbolProperties) o;
                next:
                {
                    altKey.setLength(0);
                    altKey.append("alt_").append(os.getOffset()).
                            append('_').append(os.getLength());
                    for (String s : altKeyList) {
                        if (s.equalsIgnoreCase(altKey.toString())) {
                            break next;
                        }
                    }
                    altKeyList.add(altKey.toString());
                    if (altKeys.length() > 0) {
                        altKeys2.append(',');
                    }
                    altKeys.append(',');
                    altKeys2.append(altKey);
                    altKeys.append(altKey).append(" VARCHAR(").append(os.getLength()).append(") ");
                    if (!os.isDuplicateKey()) {
                        altKeys3.append(", UNIQUE (").append(altKey).append(')');
                    }
                }
            }
        }
        if (altKeys3.length() > 0) {
            altKeys.append(altKeys3);
        }
        String idLine = props.getDataName() + "(" + ((String) props.getOtherName()).toUpperCase() + ") PRIMARY(" + ((SymbolProperties) props.getOtherData2()).getJavaName2() + ")";
        dbProps.put(fileName, idLine);
        dbProps.put(fileName + "_createSQL", getSQLCreate(props, altKeys.toString()));
        dbProps.put(fileName + "_altKeys", altKeys2.toString());
        //	} else
        //	RunTimeUtil.getInstance().reportError("Properties exists for file " +fileName +
        //		" . Not overwritten.",false);
    }

    public void saveDatabaseProperties() {
        if (dbProps != null) {
            try {
                dbProps.storeToXML(new FileOutputStream(new File(RESConfig.getInstance().getOutputDir() + File.separatorChar + "Database.properties")), "Generated by RES.");
                dbProps = null;
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    public String getSQLCreate(SymbolProperties file, String altKeys) {
        return createSqlTemplate.replace("%0", NameUtil.convertCobolNameToSQL(file.getOtherName())).
                replace("%1", getCreateTableSqlAttributes(file) + altKeys);
    }

    public String getCreateTableSqlAttributes(SymbolProperties file) {
        columnsGen.clear();
        StringBuffer attributeString = new StringBuffer();
        if (file.getChildren() == null || file.getChildren().size() <= 0) {
            reportError("File must have atleast one data record defined.");
        }
        attributeString.append("PRIMARY_KEY__ ");
        switch (((SymbolProperties) file.getOtherData2()).getIdentifierType()) {
            case Constants.SHORT:
            case Constants.INTEGER:
            case Constants.LONG:
                attributeString.append("INTEGER");
                break;
            case Constants.BIGDECIMAL:
                attributeString.append("DECIMAL");
                break;
            case Constants.BYTE:
            case Constants.CHAR:
            case Constants.STRING:
            case Constants.GROUP:
                attributeString.append("varchar(" + String.valueOf(((SymbolProperties) file.getOtherData2()).getLength()) + ')');
            default:
        }
        attributeString.append(" UNIQUE, DATA_BYTES__ ");

        attributeString.append(DATA_BYTES_COLUMN_TYPE[RESConfig.getInstance().getSqlDatabaseType()]);

        //appendCreateAttributes(attributeString,findIndexedRecord(file));
        return attributeString.toString();
    }
    private static final String[] DATA_BYTES_COLUMN_TYPE = new String[]{
        "TEXT", "LONG", "TEXT", "TEXT", "LONG VARCHAR", "TEXT", "LONG CHAR", "LONG VARCHAR", "TEXT"
    };

    /*
    private SymbolProperties findIndexedRecord(SymbolProperties file) {
    for(SymbolProperties ch:file.getChildren())
    if(ch.isIndexedFileRecord())
    return ch;
    return file.getChildren().get(0);
    }
     */
    public void appendCreateAttributes(StringBuffer attributeString, SymbolProperties props) {
        CobolSymbol sym;
        if (props.isGroupData() && props.hasChildren()) {
            appendCreateAttributes(attributeString, props.getChildren());
        } else if (props.isElementData()) {
            sym = props.getJavaType();
            switch (sym.getType()) {
                case Constants.SHORT:
                case Constants.INTEGER:
                    if (attributeString != null) {
                        if (attributeString.length() > 0) {
                            attributeString.append(',');
                        }
                        attributeString.append(NameUtil.convertCobolNameToSQL(props.getDataName())).append(' ');
                        columnsGen.add(props);
                        attributeString.append("INT");
                    } else {
                        columnsGen.add(props);
                    }
                    break;
                case Constants.LONG:
                    if (attributeString != null) {
                        if (attributeString.length() > 0) {
                            attributeString.append(',');
                        }
                        attributeString.append(props.getJavaName1()).append(' ');
                        columnsGen.add(props);
                        attributeString.append("LONG");
                    } else {
                        columnsGen.add(props);
                    }

                    break;
                case Constants.BIGDECIMAL:
                    if (attributeString != null) {
                        if (attributeString.length() > 0) {
                            attributeString.append(',');
                        }
                        attributeString.append(props.getJavaName1()).append(' ');
                        columnsGen.add(props);
                        attributeString.append("DECIMAL");
                    } else {
                        columnsGen.add(props);
                    }

                    break;
                case Constants.BYTE:
                case Constants.CHAR:
                case Constants.STRING:
                case Constants.GROUP:
                default:
                    if (attributeString != null) {
                        if (attributeString.length() > 0) {
                            attributeString.append(',');
                        }
                        attributeString.append(props.getJavaName1()).append(' ');
                        attributeString.append("varchar(" + String.valueOf(sym.getMaxStringLength()) + ')');
                        columnsGen.add(props);
                    } else {
                        columnsGen.add(props);
                    }

            }
        }
    }

    public void appendCreateAttributes(StringBuffer arributeString, ArrayList<SymbolProperties> children) {
        for (SymbolProperties child : children) {
            appendCreateAttributes(arributeString, child);
        }
    }

    public String getInsertIntoSqlAttributes(SymbolProperties file) {
        StringBuffer arributeString1 = new StringBuffer();
        StringBuffer arributeString2 = new StringBuffer();
        if (file.getChildren() == null || file.getChildren().size() <= 0) {
            reportError("File must have atleast one data record defined.");
        }
        appendInsertAttributes1(arributeString1);
        appendInsertAttributes2(arributeString2);
        return arributeString1.insert(0, "(").append(") VALUES (").append(arributeString2).append(')').toString();
    }

    private void appendInsertAttributes1(StringBuffer attributeString) {
        for (SymbolProperties column : columnsGen) {
            CobolSymbol sym = column.getJavaType();
            switch (sym.getType()) {
                case Constants.SHORT:
                case Constants.INTEGER:
                case Constants.LONG:
                case Constants.BIGDECIMAL:
                case Constants.STRING:
                    if (attributeString.length() > 0) {
                        attributeString.append(',');
                    }
                    attributeString.append(NameUtil.convertCobolNameToSQL(column.getDataName()));
                default:
            }
        }

    }

    private void appendInsertAttributes2(StringBuffer attributeString) {
        for (int i = 0; i < columnsGen.size(); ++i) {
            if (i != 0) {
                attributeString.append(',');
            }
            attributeString.append('?');
        }
    }

    public int setSQLParameters(StringBuffer line) {
        int i = 1;
        for (SymbolProperties column : columnsGen) {
            line.append("\t__dao().set").append(SymbolConstants.getSQL(column.getIdentifierType())).append('(').append(i++).append(',').append(NameUtil.getJavaName(column, false)).append(");");
            ClassFile.println(line.toString());
            line.setLength(0);
        }
        return i;
    }

    public void printSetSQLProperties(SymbolProperties props) {
        /*
        columnsGen.clear();
        ClassFile.println("@Override");
        ClassFile.doMethodScope("public void setSQLProperties(CobolIndexedFile file) throws java.io.IOException {");
        ClassFile.tab();
        ClassFile.println("try {");
        ClassFile.tab();
        //appendCreateAttributes(null,props);
        int i=1;StringBuffer line=new StringBuffer();
        line.append("file.set").append(SymbolConstants.getSQL((
        (SymbolProperties)props.getParent().getOtherData2()).getIdentifierType())).append('(')
        .append(i++).append(',').append(
        SymbolUtil.getInstance().getLocalFillerGetter((SymbolProperties)props.getParent().getOtherData2())).append(");");
        line.append("file.set").append(SymbolConstants.getSQL(Constants.STRING)).append('(')
        .append(i++).append(',').append("new String(super.get()));");

        ClassFile.println(line.toString());
        ClassFile.backTab();
        ClassFile.println("} catch(java.sql.SQLException se) {throw new java.io.IOException(se);}");
        ClassFile.backTab();
        ClassFile.println("}");
         */
    }

    public void printSetStartSQLProperties(SymbolProperties props) {
        /*
        ClassFile.println("@Override");
        ClassFile.doMethodScope("public int numberOfColumns() {");
        ClassFile.println("\treturn "+String.valueOf(columnsGen.size()+1)+";");
        ClassFile.println("}");
         */
        if (props.getParent().getOtherData2() != null) {
            SymbolProperties pk = (SymbolProperties) props.getParent().getOtherData2();
            String pkStr = SymbolUtil.getInstance().getGetterString(pk, -1, 0);
            if (pk.getIdentifierType() == Constants.CHAR || pk.getIdentifierType() == Constants.BYTE) {
                pkStr = "String.valueOf(" + pkStr + ")";
            } else if (pk.getIdentifierType() == Constants.GROUP) {
                pkStr = "new String(" + pkStr + ")";
            }
            ClassFile.println("@Override");
            ClassFile.doMethodScope("public Object primaryKey() {");
            ClassFile.println("\treturn " + pkStr + ";");
            ClassFile.println("}");
            /*
            ClassFile.doMethodScope("public void setPrimaryKey(CobolIndexedFile file,int idx) throws java.io.IOException {");
            ClassFile.println("\ttry {");
            ClassFile.println("\t\tfile.set"+ SymbolConstants.getSQL(((SymbolProperties)props.getParent().getOtherData2()).getIdentifierType())+
            "(idx,get"+((SymbolProperties)props.getParent().getOtherData2()).getJavaName2()+"());");
            ClassFile.println("\t} catch(java.sql.SQLException e) {");
            ClassFile.println("\t\tthrow new java.io.IOException(e);}");
            ClassFile.println("}");
             */
        }
    }

    public void printgetSQLResults(SymbolProperties props) {
        /*
        columnsGen.clear();
        ClassFile.println("@Override");
        ClassFile.doMethodScope("public void getSQLResults(CobolIndexedFile file) throws java.io.IOException {");
        ClassFile.tab();
        ClassFile.println("try {");
        ClassFile.tab();
        //appendCreateAttributes(null,props);
        StringBuffer line=new StringBuffer();
        line.append(
        SymbolUtil.getInstance().getLocalFillerSetter(((SymbolProperties)props.getParent().getOtherData2()),
        "file.get"+SymbolConstants.getSQL(
        ((SymbolProperties)props.getParent().getOtherData2()).getIdentifierType())+'('+(i++)+")")).append(';');
        line.append("valueOf(").
        append("file.get"+SymbolConstants.getSQL(Constants.STRING)).	append('(').append(2).append("));");
        ClassFile.println(line.toString());
        ClassFile.backTab();
        ClassFile.println("} catch(java.sql.SQLException se) {throw new java.io.IOException(se);}");
        ClassFile.backTab();
        ClassFile.println("}");
         */
    }

    private void reportError(String msg) {
        RunTimeUtil.getInstance().reportError(msg, true);
    }
    private ArrayList<SymbolProperties> columnsGen = new ArrayList<SymbolProperties>();
    //private static final String dropSqlTemplate = "\"DROP TABLE %0 \"";
    private static final String createSqlTemplate = "\"CREATE TABLE %0 (%1) \"";
    //private static final String insertSqlTemplate = "\"INSERT INTO %0 (%1) VALUES (%2) \"";
    //private static final String updateSqlTemplate = "\"UPDATE %0 %1 \"";
    //private static final String selectSqlTemplate = "\"SELECT %0 FROM %1 \"";
    //private static final String deleteSqlTemplate = "\"DELETE FROM %0 \"";
    //private static final String whereSqlTemplate = "\"WHERE ? %% PRIMARY_KEY__ \"";
    //private static final String orderBySqlTemplate = "\"ORDER BY PRIMARY_KEY__ \" ";
}
 public class TranslationTable {

    private static TranslationTable thiz = null;
    private static RESContext context = null;

    public static TranslationTable getInstance() {
        if (thiz == null) {
            context = Main.getContext();
            thiz = new TranslationTable();
        }
        return thiz;
    }

    public static void clear() {
        thiz = null;
        context = null;
    }

    private TranslationTable() {
    }
    //This is Holier than Holy... do not touch without knowing your prayers.
    private static final String[][] DOIDOP_CONVERSION =
            new String[][]{
        //To->    	BYTE						CHAR
        //To->    	SHORT						INTEGER						LONG
        //To->    	FLOAT						DOUBLE
        //From		BIGDECIMAL					STRING						CLASS
        /*BYTE*/{"%1", "(char) (%1)",
            "(short) (%1)", "(int) (%1)", "(long) (%1)",
            "(float) (%1)", "(double) (%1)",
            "new BigDecimal(%1)", "String.valueOf(%1)", "String.valueOf(%1).getBytes()",
            "%1"},
        /*CHAR*/ {"(byte) (%1)", "%1",
            "(short) (%1)", "(int) (%1)", "(long) (%1)",
            "(float) %1", "(double) %1",
            "new BigDecimal(%1)", "String.valueOf(%1)", "String.valueOf(%1).getBytes()",
            "%1"},
        /*SHORT*/ {"(byte) (%1)", "(char) (%1)",
            "%1", "%1", "%1",
            "(float) (%1)", "(double) (%1)",
            "new BigDecimal(%1)", "String.valueOf(%1)", "String.valueOf(%1).getBytes()",
            "%1"},
        /*INTEGER*/ {"(byte) (%1)", "(char) (%1)",
            "(short) (%1)", "%1", "%1",
            "(float) (%1)", "(double) (%1)",
            "new BigDecimal(%1)", "String.valueOf(%1)", "String.valueOf(%1).getBytes()",
            "%1"},
        /*LONG*/ {"(byte) (%1)", "(char) (%1)",
            "(short) (%1)", "(int) (%1)", "%1",
            "(float) (%1)", "(double) (%1)",
            "new BigDecimal(%1)", "String.valueOf(%1)", "String.valueOf(%1).getBytes()",
            "%1"},
        /*FLOAT*/ {"(byte) (%1)", "(char) (%1)",
            "(short) (%1)", "(int) (%1)", "(long) (%1)",
            "%1", "%1",
            "new BigDecimal(\"%1\")", "String.valueOf(%1)", "String.valueOf(%1).getBytes()",
            "%1"},
        /*DOUBLE*/ {"(byte) (%1)", "(char) (%1)",
            "(short) (%1)", "(int) (%1)", "(long) (%1)",
            "(float) (%1)", "%1",
            "new BigDecimal(\"%1\")", "String.valueOf(%1)", "String.valueOf(%1).getBytes()",
            "%1"},
        /*BIGDECIMAL*/ {"%1.byteValue()", "(char) %1.byteValue()",
            "%1.shortValue()", "%1.intValue()", "%1.longValue()",
            "%1.floatValue()", "%1.doubleValue()",
            "%1", "__formatPlainDecimal(%1)", "__formatPlainDecimal(%1).getBytes()",
            "%1"},
        /*STRING*/ {"Byte.parseByte(%1)", "__getChar(%1)",
            "FieldFormat.parseInt(%1)", "FieldFormat.parseInt(%1)", "FieldFormat.parseLong(%1)",
            "Float.parseFloat(%1)", "Double.parseDouble(%1)",
            "FieldFormat.parseNumber(%1)", "%1", "%1.getBytes()", "%1"},
        /*CLASS*/ {"%1[0]", "__getChar(%1)",
            "FieldFormat.parseInt(new String(%1))", "FieldFormat.parseInt(new String(%1))", "FieldFormat.parseLong(new String(%1))",
            "Float.parseFloat(new String(%1))", "Double.parseDouble(new String(%1))",
            "FieldFormat.parseNumber(new String(%1))", "new String(%1)", "%1",
            "%1"},
        /*OBJECT*/ {"(Byte)%1", "(Char) %1",
            "(Integer)%1", "(Integer)%1", "(Long)%1",
            "(Float)%1", "(Double)%1",
            "new BigDecimal(%1.toString())", "%1.toString()", "%1.toString().getBytes()",
            "%1"}
    };
    private static final String[] DOIDOP_OPERATION =
            new String[]{"_Math.add(%1,%2)", "_Math.subtract(%1,%2)", "_Math.multiply(%1,%2)", "_Math.divide(%1,%2)",
        "_Math.remainder(%1,%2)", "_Math.pow(%1,%2)"};
    private static final String[] DO_NATIVE_OP_OPERATION =
            new String[]{"%1 + %2", "%1 - %2", "%1 * %2", "%1 / %2",
        "%1 % %2", "Math.pow(%1,%2)"};
    public static final int ADD_OP = 0;
    public static final int SUBTRACT_OP = 1;
    public static final int MULTIPLY_OP = 2;
    public static final int DIVIDE_OP = 3;
    public static final int REMAINDER_OP = 4;
    public static final int POW_OP = 5;

    public ExpressionString doOp(int op, ExpressionString arg1, ExpressionString arg2) {
        ExpressionString s1 = arg1,s2 = arg2;
        arg1 = context.getCobol2Java().new ExpressionString(arg1); //Hack... Need to rework...
        arg2 = context.getCobol2Java().new ExpressionString(arg2); //Hack... Need to rework...
        if (op == DIVIDE_OP) {
            context.getCobol2Java().expressionType = Math.max(arg1.type, Constants.DOUBLE);
            arg1 = convertType(arg1, context.getCobol2Java().expressionType, arg1.type);
            arg1.type = context.getCobol2Java().expressionType;
        }
        if (arg1.type < Constants.INTEGER) {
            arg1 = convertType(arg1, Constants.INTEGER, arg1.type);
            arg1.type = Constants.INTEGER;
        }
        if (arg2.type < Constants.INTEGER) {
            arg2 = convertType(arg2, Constants.INTEGER, arg2.type);
            arg2.type = Constants.INTEGER;
        }
        if (op < 0 || op >= DOIDOP_OPERATION.length) {
            op = 0; //reset to add()
        }
        if (Math.max(arg1.type, arg2.type) > Constants.DOUBLE) {
            arg1.literal.replace(0, arg1.literal.length(), DOIDOP_OPERATION[op].replace("%1", arg1.toString()).replace("%2", arg2.toString()));
        } else {
            arg1.literal.replace(0, arg1.literal.length(), DO_NATIVE_OP_OPERATION[op].replace("%1", arg1.toString()).replace("%2", arg2.toString()));
        }
        context.getCobol2Java().expressionType = arg1.type = Math.max(arg1.type, arg2.type);
        return arg1;

    }

    public ExpressionString doOp(String opArg, ExpressionString arg1, ExpressionString arg2) {
        int op = 0;
        switch (opArg.trim().charAt(0)) {
            case '+':
                op = ADD_OP;
                break;
            case '-':
                op = SUBTRACT_OP;
                break;
            case '*':
                op = MULTIPLY_OP;
                break;
            case '/':
                op = DIVIDE_OP;
                break;
            case '%':
                op = REMAINDER_OP;
                break;
            default:
                op = POW_OP;
                break;
        }
        return doOp(op, arg1, arg2);
    }

    public void doIdOp(SymbolProperties id, String op) {
        if (context.getCobol2Java().expression.size() <= 0) {
            context.getCobol2Java().expression.push(context.getCobol2Java().new ExpressionString(id, id.getJavaType().getMaxScalingLength()));
            context.getCobol2Java().expressionType = context.getCobol2Java().expression.peek().type;
        } else {
            context.getCobol2Java().expression.push(
                    doOp(op, context.getCobol2Java().getExpression(), context.getCobol2Java().new ExpressionString(id, id.getJavaType().getMaxScalingLength())));
        }
    }
    public static Pattern NUMBER_PATTERN = Pattern.compile("(([\\-\\+\\*\\/%]?[0-9]*(\\.[0-9]+)?)|\\.[0-9]+)+");

    public void doLiteralOp(String lit, String op) {
        if (context.getCobol2Java().expression.size() <= 0) {
            context.getCobol2Java().expression.push(context.getCobol2Java().formatLiteral(lit));
        } else {
            ExpressionString arg2 = context.getCobol2Java().getExpression();
            ExpressionString arg1 = context.getCobol2Java().formatLiteral(lit);
            context.getCobol2Java().expression.push(doOp(op, arg2, arg1));
        }
    }

    public void doOp(SymbolProperties props, String op) {
        doIdOp(props, op);
    }

    public void doOp(String lit, String op) {
        doLiteralOp(lit, op);
    }

    public void doOp(ExpressionString exprString, String op) {
        if (context.getCobol2Java().expression.size() <= 0) {
            context.getCobol2Java().expression.push(exprString);
            context.getCobol2Java().expressionType = exprString.type;
        } else {
            ExpressionString arg2 = context.getCobol2Java().getExpression();
            ExpressionString arg1 = exprString;
            context.getCobol2Java().expression.push(
                    doOp(op, arg2, arg1));
        }
    }

    public void doOp(String exprString, int expressionType, String op) {
        doOp(context.getCobol2Java().new ExpressionString(exprString, expressionType), op);
    }

    public String getAssignString(SymbolProperties lhs, SymbolProperties rhs, boolean isAll) {
        return getAssignString(lhs, rhs, isAll, true, false);
    }

    public String getAssignString(SymbolProperties lhs, SymbolProperties rhs, boolean isAll, boolean addSemi) {
        return getAssignString(lhs, rhs, isAll, addSemi, false);
    }

    public String getAssignString(SymbolProperties lhs, SymbolProperties rhs, boolean isAll, boolean addSemi, boolean isSpecialMove) {

        int allLength = 0;
        if (isAll && lhs != null) {
            allLength = lhs.getLength();
        }

        ExpressionString exprString, lhsVarString;
        int lhsType, rhsType = 0;

        if (rhs == null) {
            exprString = context.getCobol2Java().new ExpressionString(context.getCobol2Java().expression.pop());
            if (exprString.type < 0) {
                exprString.type = context.getCobol2Java().expressionType;
            }
        } else {
            exprString = context.getCobol2Java().new ExpressionString(rhs);
        }
        rhsType = exprString.type;

        if (lhs == null && rhs == null) {//Create temporary variable assignment from the expression
            String tempVar = "temp" + new Integer(SymbolTable.tempVariablesMark++).toString().trim();
            exprString.literal.insert(0, SymbolConstants.get(context.getCobol2Java().expressionType) + " "
                    + tempVar + " = ").append(";");
            return exprString.toString();
        }
        boolean delayRHSTypeAsString = false, isJustRight = false;
        if (lhs == null) {//Used in file reads and writes
            lhsVarString = context.getCobol2Java().expression.pop();
            lhsVarString.literal.append("(%0)");
            lhsVarString.type = lhsType = context.getCobol2Java().expressionType;
        } else {//General assigns
            lhsType = lhs.getIdentifierType();

            if (isSpecialMove
                    && (isANumber(lhsType) && lhs.getDataCategory() == Constants.NUMERIC_EDITED && lhs.getIsFormat()
                    && isANumber(rhsType) && rhs == null)) {
                if (lhs.getIsFormat()) {
                    lhsVarString = context.getCobol2Java().new ExpressionString(NameUtil.getJavaName(lhs, true).replace("%0", NameUtil.getFormatName2(lhs, false)), lhsType);
                    delayRHSTypeAsString = true;
                } else {
                    lhsVarString = context.getCobol2Java().new ExpressionString(NameUtil.getJavaName(lhs, true), lhsType);
                }
            } else {
                lhsVarString = context.getCobol2Java().new ExpressionString(NameUtil.getJavaName(lhs, true), lhsType);
            }
        }


        if (rhs == null) {

            if (isSpecialMove) {

                if (!isANumber(lhsType) && isANumber(rhsType)) {
                    if (lhs.getDataCategory() == Constants.NUMERIC_EDITED) {
                        exprString = context.getCobol2Java().new ExpressionString(NameUtil.getFormatName2(lhs, false).replace("%0",
                                ((rhsType == Constants.FLOAT || rhsType == Constants.DOUBLE)
                                ? (convertType(exprString, Constants.BIGDECIMAL, rhsType).toString()) : exprString.toString())),
                                exprString.type = rhsType = Constants.STRING);
                        //rhsType=exprString.type;
                    } else {
                        if (exprString.raw != null
                                && context.getCobol2Java().numPattern.matcher(exprString.raw).matches()) {
                            exprString = context.getCobol2Java().new ExpressionString('\"' + exprString.raw + '\"', rhsType = Constants.STRING);
                        }
                        if (lhs.getIsFormat() && !isANumber(lhsType)) {
                            System.out.println(lhs.getDataName() + "," + exprString.raw);
                            exprString = context.getCobol2Java().new ExpressionString(NameUtil.getFormatName2(lhs, false).replace("%0", exprString.toString()), exprString.type);
                            delayRHSTypeAsString = true;
                        }
                    }
                } else if (lhsType == Constants.STRING && lhs.getIsFormat()) {
                    if (rhsType == Constants.FLOAT || rhsType == Constants.DOUBLE) {
                        exprString = context.getCobol2Java().new ExpressionString("new BigDecimal(\"" + exprString + "\")",
                                rhsType = Constants.BIGDECIMAL);
                    }
                    exprString = context.getCobol2Java().new ExpressionString(NameUtil.getFormatName2(lhs, false).replace("%0",
                            exprString.toString()));
                    delayRHSTypeAsString = true;
                } else;//exprString=context.getCobol2Java().expression.pop3();
            } else if (isANumber(rhsType) && isStringOrGroup(lhsType)) {
                if (lhs.getDataCategory() != Constants.NUMERIC_EDITED) {
                    exprString = context.getCobol2Java().new ExpressionString('\"' + exprString.raw + '\"', rhsType = Constants.STRING);
                } else {
                    if (context.getCobol2Java().numPattern.matcher(exprString.toString()).matches()) {
                        exprString = context.getCobol2Java().new ExpressionString(NameUtil.getFormatName2(lhs, false).replace("%0",
                                "new BigDecimal(\"" + exprString + "\")"),
                                rhsType = Constants.STRING);
                    } else {
                        exprString = context.getCobol2Java().new ExpressionString(NameUtil.getFormatName2(lhs, false).replace("%0",
                                convertType(exprString, Constants.BIGDECIMAL, rhsType).toString()),
                                rhsType = Constants.STRING);
                    }

                }
            } else;//exprString=context.getCobol2Java().expression.pop3();
        } else {
            if (isSpecialMove) {
                if (!isANumber(lhsType)) {
                    if (isANumber(rhsType)) {
                        if (rhs.getDataUsage() == Constants.DISPLAY) {
                            exprString = context.getCobol2Java().new ExpressionString(NameUtil.getJavaName(exprString.props, false,
                                    lhs.getDataCategory() != Constants.NUMERIC_EDITED && !lhs.getIsFormat()), rhsType = exprString.type);

                            isJustRight = true;
                            delayRHSTypeAsString = lhs.getDataCategory() != Constants.NUMERIC_EDITED && !lhs.getIsFormat();
                        }

                        if (rhs.getJavaType().getMaxScalingLength() != 0
                                && !delayRHSTypeAsString) {

                            exprString.setString(context.getCobol2Java().doScaleLiteral(rhs, exprString.toString(), true), Constants.BIGDECIMAL);

                        }

                        if (lhsType == Constants.STRING && lhs.getIsFormat()) {
                            exprString = context.getCobol2Java().new ExpressionString(NameUtil.getFormatName2(lhs, false).replace("%0",
                                    exprString.toString()), rhsType = Constants.STRING);
                        }
                        /*
                        else {
                        if(lhs.getDataCategory()!=Constants.NUMERIC_EDITED&&rhs.getDataUsage()==Constants.DISPLAY)
                        exprString=SymbolUtil.getInstance().getToStringOrGroupMove(rhs);
                        else
                        exprString=NameUtil.getJavaName(rhs,false);
                        if(lhs.getIsFormat()) {
                        exprString=NameUtil.getFormatName2(lhs,false).replace("%0",exprString);
                        } else
                        exprString="getProgram().normalizeString("+exprString+","+
                        lhs.getLength()+")";
                        }
                         * */

                    } else if (lhsType == Constants.STRING && rhsType == Constants.STRING) {
                        exprString = context.getCobol2Java().new ExpressionString(NameUtil.getFormatName2(lhs, false).replace("%0",
                                exprString.toString()), rhsType = Constants.STRING);
                    } else;//exprString=NameUtil.getJavaName(rhs,false);
                } else {//isANumber LHS
                    //exprString=NameUtil.getJavaName(rhs,false);
                    rhsType = Math.max(rhs.getIdentifierType(), rhsType);
                    if (!isANumber(rhsType) && lhs.getDataUsage() == Constants.DISPLAY) {
                        lhsVarString.type = lhsType = Constants.STRING;
                    } else if (lhsType == Constants.STRING && lhs.getIsFormat()) {
                        exprString = context.getCobol2Java().new ExpressionString(NameUtil.getFormatName2(lhs, false).replace("%0", exprString.toString()), rhsType);
                        delayRHSTypeAsString = true;
                    }
                }
            }
        }

        if (delayRHSTypeAsString) {
            exprString.type = rhsType = Constants.STRING;
        }

        if (isSpecialMove) {
            if (lhs.getJavaType().getMaxScalingLength() != 0) {

                if (lhs.getJavaType().getMaxScalingLength() < 0) {
                    exprString.literal.insert(0, "__scale(").append(',').append(String.valueOf(lhs.getJavaType().getMaxIntLength() - lhs.getJavaType().getMaxScalingLength())).append(')');
                } else {
                    exprString.literal.insert(0, "__scale(").append(',').append(
                            (-lhs.getJavaType().getMaxScalingLength())).append(')');
                }
                exprString.type = rhsType = Constants.BIGDECIMAL;
            }
        }

        if (lhsType == Constants.UNKNOWN || rhsType == Constants.UNKNOWN) {
            return "";
        }
        /*
        if(isSpecialMove&&!delayRHSTypeAsString&&
        ((isAnEditedNumber(lhs, lhsVarString.type)&&
        exprString.type==Constants.GROUP))) {
        exprString=context.getCobol2Java().new ExpressionString(SymbolUtil.getInstance().getFromStringOrGroupMove(lhs, exprString.toString()),exprString.type);
        lhsVarString.type=lhsType=Constants.STRING;
        context.getCobol2Java().expressionType=Math.max(lhsType,context.getCobol2Java().expressionType);
        } else
         *
         */
        {
            if (lhs.isJustifiedRight() || isJustRight) {
                exprString.literal = exprString.literal.insert(0, "__justifyRight(").append(",").append(String.valueOf(lhs.getLength())).append(")");
                exprString.type = rhsType = Constants.STRING;
            } else if ((isSpecialMove && isANumber(lhsType) && rhsType == Constants.STRING)) {
                exprString.literal = exprString.literal.insert(0, "__trimNumberToSize(").append(",").append(String.valueOf(lhs.getLength())).append(")");
                exprString.type = rhsType = Constants.STRING;
            }

            if (isAll && allLength > 0) {
                exprString.insert(0, "__all(").append(",").append(String.valueOf(allLength)).append(")");
                exprString.type = rhsType = Constants.STRING;
            }


            if (exprString.type != Constants.STRING || !delayRHSTypeAsString) {

                exprString = convertType(exprString, lhsType, rhsType);

                context.getCobol2Java().expressionType = Math.max(lhsType, context.getCobol2Java().expressionType);
            } else {
                if (!isANumber(lhsType) && rhs != null && rhs.getDataUsage() == Constants.DISPLAY) {
                    exprString = convertType(exprString, lhsType, Constants.STRING);
                }

                context.getCobol2Java().expressionType = Math.max(lhsType, context.getCobol2Java().expressionType);
            }

            exprString.replace(0, exprString.literal.length(), lhsVarString.literal.toString().replace("%0", exprString.toString()));
        }
        return exprString.append(addSemi ? ";" : "").toString();
    }

    private boolean isAString(int lhsType) {
        return lhsType == Constants.STRING;
    }

    private boolean isAnEditedNumber(SymbolProperties lhs, int lhsType) {
        return isANumber(lhsType) && (lhs.getDataUsage() == Constants.DISPLAY);
    }

    private boolean isStringOrGroup(int lhsType) {
        return lhsType > Constants.BIGDECIMAL;
    }

    private boolean isANumber(int rhsType) {
        return rhsType <= Constants.BIGDECIMAL && rhsType > Constants.CHAR;
    }

    //Conversion
    public String convertType(String exprString, int lhsType, int rhsType) {
        if ((rhsType == Constants.DOUBLE || rhsType == Constants.FLOAT) && lhsType == Constants.BIGDECIMAL) {
            if (exprString.indexOf("__function") < 0
                    && context.getCobol2Java().numPattern.matcher(exprString).matches()) {
                return "new BigDecimal(\"" + exprString + "\")";
            } else {
                return "new BigDecimal(" + exprString + ")";
            }
        }

        context.getCobol2Java().expressionType = lhsType;
        exprString = DOIDOP_CONVERSION[rhsType][lhsType].replace(
                "%1", exprString);
        return exprString;
    }

    //Conversion
    public ExpressionString convertType(ExpressionString exprString, int lhsType, int rhsType) {
        exprString.literal = new StringBuilder(convertType(exprString.toString(), lhsType, rhsType));
        exprString.type = lhsType;
        return exprString;
    }

    public String convertSymbolToStringType(SymbolProperties symbol) {
        context.getCobol2Java().expressionType = Constants.STRING;
        if (symbol.getIdentifierType() < Constants.STRING && symbol.getIsFormat()) {
            symbol.setIdentifierType(Constants.STRING);
            return NameUtil.getFormatName2(symbol, true).replace("%0",
                    NameUtil.getJavaName(symbol, false));
        } else {
            symbol.setIdentifierType(Constants.STRING);
            return DOIDOP_CONVERSION[symbol.getIdentifierType()][Constants.STRING].replace(
                    "%1", NameUtil.getJavaName(symbol, false));
        }

    }
    public static final int AND_CONDITION = 0;
    public static final int OR_CONDITION = 1;
    public static final int EQ_CONDITION = 2;
    public static final int NE_CONDITION = 3;
    public static final int LT_CONDITION = 4;
    public static final int GE_CONDITION = 5;
    public static final int GT_CONDITION = 6;
    public static final int LE_CONDITION = 7;
    public static final int POSITIVE_CONDITION = 0;
    public static final int NEGATIVE_CONDITION = 1;
    public static final int ZERO_CONDITION = 2;
    public static final int NOT_ZERO_CONDITION = 3;
    private static final int[] REVERSE_OP = new int[]{1, 0, 3, 2, 5, 4, 7, 6};
    private static final String[] DOID_NATIVE_CONDITION_OP =
            new String[]{"%1 && %2", "%1 || %2",
        "%1 == %2", "%1 != %2",
        "%1 < %2", "%1 >= %2",
        "%1 > %2", "%1 <= %2"};
    private static final String[] DOID_METHODS_CONDITION_OP =
            new String[]{"%1 && %2", "%1 || %2",
        "Compare.eq(%1,%2)", "Compare.ne(%1,%2)",
        "Compare.lt(%1,%2)", "Compare.ge(%1,%2)",
        "Compare.gt(%1,%2)", "Compare.le(%1,%2)"};
    private static final String[] DOID_LO_CONDITION_OP =
            new String[]{"Compare.loValues(%0)==0", "Compare.loValues(%0)!=0",
        "Compare.loValues(%0)<0", "Compare.loValues(%0)>=0",
        "Compare.loValues(%0)>0", "Compare.loValues(%0)<=0"};
    private static final String[] DOID_HI_CONDITION_OP =
            new String[]{"Compare.hiValues(%0)==0", "Compare.hiValues(%0)!=0",
        "Compare.hiValues(%0)<0", "Compare.hiValues(%0)>=0",
        "Compare.hiValues(%0)>0", "Compare.hiValues(%0)<=0"};
    private static final String[] DOID_QUOTE_CONDITION_OP =
            new String[]{"Compare.quotes(%0)==0", "Compare.quotes(%0)!=0",
        "Compare.quotes(%0)<0", "Compare.quotes(%0)>=0",
        "Compare.quotes(%0)>0", "Compare.quotes(%0)<=0"};
    private static final String[] DOID_SPACES_CONDITION_OP =
            new String[]{"Compare.spaces(%0)==0", "Compare.spaces(%0)!=0",
        "Compare.spaces(%0)<0", "Compare.spaces(%0)>=0",
        "Compare.spaces(%0)>0", "Compare.spaces(%0)<=0"};
    private static final int[] SINGLE_ARG_REVERSE_OP = new int[]{1, 0, 3, 2};
    private static final String[] DO_SINGLE_ARG_CONDITION_OP =
            new String[]{"Compare.isPositive(%0)", "Compare.isNegative(%0)",
        "Compare.isZero(%0)", "!Compare.isZero(%0)", "!(%0)"};

    public int getReverseOp(int op, boolean reverse) {
        if (op < 0 || op >= REVERSE_OP.length) {
            op = 0;
        }
        return (reverse ? REVERSE_OP[op] : op);
    }

    public String doCondition(int op, ExpressionString expr1, ExpressionString expr2, boolean doReverseCondition) {

        int l1, l2;
        if (expr1.props != null) {
            l1 = expr1.props.getLength();
        } else {
            l1 = expr1.length;
        }
        if (expr2.props != null) {
            l2 = expr2.props.getLength();
        } else {
            l2 = expr2.length;
        }
        int l = Math.max(l1, l2);
        if (expr1.isAll) {
            expr1.literal.insert(0, "__all(").append(',').append(l).append(')');
        }
        if (expr2.isAll) {
            expr2.literal.insert(0, "__all(").append(',').append(l).append(')');
        }

        if (expr1.type == Constants.FLOAT || expr1.type == Constants.DOUBLE) {
            expr1 = convertType(expr1, Constants.BIGDECIMAL, expr1.type);
        }
        if (expr2.type == Constants.FLOAT || expr2.type == Constants.DOUBLE) {
            expr2 = convertType(expr2, Constants.BIGDECIMAL, expr2.type);
        }

        if (op < 0 || op >= DOID_NATIVE_CONDITION_OP.length) {
            op = 2;//reset to ==
        }
        if ((expr1.toString().equals("\"\\\"\"") || expr2.toString().equals("\"\\\"\"")) && op >= 2) {

            op -= 2;
            if (expr1.toString().equals("\"\\\"\"")) {
                return DOID_QUOTE_CONDITION_OP[getReverseOp(op, getFigConstReverseCondition(op, doReverseCondition))].replace("%0", expr2.toString());
            } else {
                return DOID_QUOTE_CONDITION_OP[getReverseOp(op, doReverseCondition)].replace("%0", expr1.toString());
            }
        }
        if ((expr1.toString().equals("__function().MAX_VALUE()") || expr2.toString().equals("__function().MAX_VALUE()")) && op >= 2) {

            op -= 2;
            if (expr1.toString().equals("__function().MAX_VALUE()")) {
                return DOID_HI_CONDITION_OP[getReverseOp(op, getFigConstReverseCondition(op, doReverseCondition))].replace("%0", expr2.toString());
            } else {
                return DOID_HI_CONDITION_OP[getReverseOp(op, doReverseCondition)].replace("%0", expr1.toString());
            }
        }
        if ((expr1.toString().equals("__function().MIN_VALUE") || expr2.toString().equals("__function().MIN_VALUE()")) && op >= 2) {

            op -= 2;
            if (expr1.toString().equals("__function().MIN_VALUE()")) {
                return DOID_LO_CONDITION_OP[getReverseOp(op, getFigConstReverseCondition(op, doReverseCondition))].replace("%0", expr2.toString());
            } else {
                return DOID_LO_CONDITION_OP[getReverseOp(op, doReverseCondition)].replace("%0", expr1.toString());
            }
        }
        if ((expr1.toString().equals("\" \"") || expr2.toString().equals("\" \"")) && op >= 2) {

            op -= 2;
            if (expr1.toString().equals("\" \"")) {
                return DOID_SPACES_CONDITION_OP[getReverseOp(op, getFigConstReverseCondition(op, doReverseCondition))].replace("%0", expr2.toString());
            } else {
                return DOID_SPACES_CONDITION_OP[getReverseOp(op, doReverseCondition)].replace("%0", expr1.toString());
            }
        }
        if (op < 0 || op >= DOID_NATIVE_CONDITION_OP.length) {
            op = 2;//reset to ==
        }
        if (Math.max(expr1.type, expr2.type) < Constants.BIGDECIMAL) {
            if ((expr1.type == Constants.CHAR || expr2.type == Constants.CHAR) && !(expr1.type == Constants.CHAR && expr2.type == Constants.CHAR)) {
                if (expr1.type == Constants.CHAR) {
                    return DOID_NATIVE_CONDITION_OP[(doReverseCondition ? REVERSE_OP[op] : op)].replace("%1", expr1.toString() + " - \'0\'").replace("%2", expr2.toString());
                } else {
                    return DOID_NATIVE_CONDITION_OP[(doReverseCondition ? REVERSE_OP[op] : op)].replace("%1", expr1.toString()).replace("%2", expr2.toString() + " - \'0\'");
                }
            } else {
                return DOID_NATIVE_CONDITION_OP[(doReverseCondition ? REVERSE_OP[op] : op)].replace("%1", expr1.toString()).replace("%2", expr2.toString());
            }
        } else {
            if (expr1.type == Constants.OBJECT) {
                expr1 = convertType(expr1, Constants.STRING, Constants.OBJECT);
            }
            if (expr2.type == Constants.OBJECT) {
                expr2 = convertType(expr2, Constants.STRING, Constants.OBJECT);
            }
            return DOID_METHODS_CONDITION_OP[(doReverseCondition ? REVERSE_OP[op] : op)].replace("%1", expr1.toString()).replace("%2", expr2.toString());
        }
    }

    private boolean getFigConstReverseCondition(int op, boolean doReverseCondition) {
        if (op == 0 || op == 0) {
            return doReverseCondition;
        } else {
            return !doReverseCondition;
        }
    }

    public ExpressionString doCondition2(int op, ExpressionString expr1, ExpressionString expr2, boolean doReverseCondition) {
        expr1.literal = new StringBuilder(doCondition(op, expr1, expr2, doReverseCondition));
        expr1.setLength(Math.max(expr1.length, expr2.length));
        return expr1;
    }

    public String doCondition(int op, ExpressionString expr, boolean doReverseCondition) {
        if (op < 0 || op >= DO_SINGLE_ARG_CONDITION_OP.length) {
            op = 0;//reset to isPositive()
        }
        return DO_SINGLE_ARG_CONDITION_OP[(doReverseCondition ? SINGLE_ARG_REVERSE_OP[op] : op)].replace("%0", expr.toString());
    }

    public ExpressionString doCondition2(int op, ExpressionString expr1, boolean doReverseCondition) {
        expr1.literal = new StringBuilder(doCondition(op, expr1, doReverseCondition));
        return expr1;
    }
} public class VsamIsam2DbGen extends DepthFirstVisitor {

    private static VsamIsam2DbGen thiz = null;

    private VsamIsam2DbGen() {
    }

    public static VsamIsam2DbGen getInstance() {
        if (thiz == null) {
            thiz = new VsamIsam2DbGen();
        }
        return thiz;
    }

    public static void clear() {
        thiz = null;
    }
    private SymbolProperties props = null;
    private ClassFileWriter classFile = null;
    private ArrayList<SymbolProperties> files2Gen = new ArrayList<SymbolProperties>();
    private String lastDataName = null;

    @Override
    public void visit(CompilationUnit n) {
        super.visit(n);
    }

    @Override
    public void visit(NestedProgramUnit n) {
        n.nestedIdentificationDivision.accept(this);
        n.nodeOptional1.accept(this);
        //n.nodeOptional.accept(this);
        //n.nodeOptional2.accept(this);
        SymbolTable.getScope().endProgram();
    }

    @Override
    public void visit(ProgramUnit n) {
        n.identificationDivision.accept(this);
        initializePass();
        n.nodeOptional1.accept(this);
        //n.nodeOptional.accept(this);
        //n.nodeOptional2.accept(this);
        SymbolTable.getScope().endProgram();
        endPass();
    }

    private void initializePass() {
        if (classFile == null) {
            ClassFile.doProgramScope(classFile = new DBGenClassFileWriter(
                    SymbolTable.getScope().getFirstProgram().getDataName(), "db_gen", false));
            printSymbol = new PrintSymbol(true);
        }
    }

    private void endPass() {
        if (classFile != null) {
            classFile.backTab();
            classFile.println("}");
        }
    }

    @Override
    public void visit(ProgramIdParagraph n) {
        props = SymbolTable.getScope().lookup(n.programName.cobolWord.nodeToken.tokenImage, SymbolConstants.PROGRAM);
        if (props == null) {
            RunTimeUtil.getInstance().reportError("Fatal Error: Cobol2Java.visit(ProgramIdParagraph):"
                    + n.programName.cobolWord.nodeToken.tokenImage, true);
        }
        SymbolTable.getScope().startProgram(props);
    }

    @Override
    public void visit(NestedProgramIdParagraph n) {
        props = SymbolTable.getScope().lookup(n.programName.cobolWord.nodeToken.tokenImage, SymbolConstants.PROGRAM);
        if (props == null) {
            reportError("Fatal Error: Cobol2Java.visit(ProgramIdParagraph):"
                    + n.programName.cobolWord.nodeToken.tokenImage);
        }
        SymbolTable.getScope().startProgram(props);
    }

    @Override
    public void visit(FileSection n) {
        ClassFile.tab();
        if (n.nodeChoice.which == 1) {
            NodeSequence nodeseq = (NodeSequence) n.nodeChoice.choice;
            nodeseq.elementAt(0).accept(this);
            if (props.getDataUsage() == Constants.INDEXED) {
                doOneFile();
            }
        }
        if (n.nodeListOptional.present()) {
            for (Enumeration<Node> e = n.nodeListOptional.elements(); e.hasMoreElements();) {
                NodeSequence nodeseq = (NodeSequence) e.nextElement();
                nodeseq.elementAt(0).accept(this);
                if (props.getDataUsage() != Constants.INDEXED) {
                    //reportError("Skipped file "+props.getDataName()+". Not Indexed Organization.",false);
                    continue;
                }
                doOneFile();
            }
        }

        ClassFile.println("public static void main(String[] args) throws IOException, SQLException {");
        ClassFile.tab();
        ClassFile.println(((DBGenClassFileWriter) ClassFile.current).getClassName()
                + " instance = new "
                + ((DBGenClassFileWriter) ClassFile.current).getClassName() + "();");
        ClassFile.println("instance.execute();");
        ClassFile.backTab();
        ClassFile.println("}");
        ClassFile.println("public void execute() throws IOException, SQLException {");
        ClassFile.tab();
        for (SymbolProperties file : files2Gen) {
            ClassFile.println("do" + file.getJavaName2() + "();");
        }
        ClassFile.backTab();
        ClassFile.println("}");
        int saveOpt = RESConfig.getInstance().getOptimizeAlgorithm();
        RESConfig.getInstance().setOptimizeAlgorithm(0);
        //Dump all data records at the end.
        for (SymbolProperties file : files2Gen) {
            SymbolTable.visit(file.getChildren().get(0), printSymbol);
        }
        RESConfig.getInstance().setOptimizeAlgorithm(saveOpt);
    }

    private void doOneFile() {
        if (props.getChildren() == null || props.getChildren().size() <= 0) {
            reportError("Skipped file " + props.getDataName() + ". Does not include data record.", false);
        }
        reportError("Generating DB for Indexed file " + props.getDataName() + ".", false);
        files2Gen.add(props);
        //Create a COBOL Sequential props to read REPROed data-props
        ClassFile.println("public CobolFile "
                + props.getJavaName1()
                + " = new CobolFile(" + props.getOtherName() + ");");
        String fileName = props.getJavaName1();
        //Construct DROP TABLE...,CREATE TABLE..., INSERT INTO... SQL.
        //String dropSql = TranUtil.get().getSQLDrop(props);
        String createSql = TranUtil.get().getSQLCreate(props, "");
        //String insertSql=TranUtil.get().getSQLInsert(props);
        ClassFile.println("private static final String " + fileName + "_create_SQL = "
                + Main.getContext().getCobol2Java().formatLiteral(createSql) + ";");
        //ClassFile.println("private static final String "+fileName+"_insert_SQL = "+
        //Main.getContext().getCobol2Java().formatLiteral(insertSql)+";");
        //Generate methods that are called from DbMigrate
        ClassFile.doMethodScope("public boolean do" + props.getJavaName2() + "() throws IOException, SQLException{");
        ClassFile.tab();
        SymbolProperties dataRec = props.getChildren().get(0);
        ClassFile.println(props.getJavaName1() + ".openInput();");
        ClassFile.println("int bytesRead=0,recordsRead=0,rowsCommitted=0;");
        ClassFile.println("try {");
        ClassFile.tab();
        //ClassFile.println("__dao().prepareStatement("+Main.getContext().getCobol2Java().formatLiteral(dropSql)+");");
        ClassFile.println("__dao().executeStatement();");
        ClassFile.backTab();
        ClassFile.println("} catch(SQLException e) {}");
        ClassFile.println("__dao().prepareStatement(" + fileName + "_create_SQL);");
        ClassFile.println("__dao().executeStatement();");
        ClassFile.println("__dao().prepareStatement(" + fileName + "_insert_SQL);");
        ClassFile.println("do {");
        ClassFile.println("\tbytesRead=" + props.getJavaName1() + ".read(" + dataRec.getJavaName1() + ".get());");
        ClassFile.println("\tif (bytesRead<=0) break;");
        ClassFile.println("\tif (bytesRead<" + String.valueOf(dataRec.getLength()) + "){ System.out.println(\"Partial record(\"+bytesRead+\" bytes) ignored.\");break; }");
        ClassFile.println("\trecordsRead++;");
        StringBuffer line = new StringBuffer();
        TranUtil.get().setSQLParameters(line);
        ClassFile.println("__dao().executeStatement();");
        ClassFile.println("} while(true);");
        ClassFile.println("__dao().prepareStatement(\"select count(*) from " + props.getJavaName1() + "\");");
        ClassFile.println("__dao().executeQuery();rowsCommitted=__dao().getInt(1);");
        ClassFile.println("System.out.println("
                + Main.getContext().getCobol2Java().formatLiteral('\"' + fileName + '\"')
                + "+\" Records Read: \"+recordsRead+\";Rows Committed: \"+rowsCommitted);");
        ClassFile.println("return true;");
        ClassFile.backTab();
        ClassFile.endMethodScope();
    }

    @Override
    public void visit(DataDivision n) {
        super.visit(n);
    }

    @Override
    public void visit(DataDivisionSection n) {
        switch (n.nodeChoice.which) {
            case 0:
                n.nodeChoice.choice.accept(this);
            default:

        }
    }
    private ArrayList<SymbolProperties> alternateKeys = new ArrayList<SymbolProperties>();

    @Override
    public void visit(FileAndSortDescriptionEntry n) {
        n.fileName.accept(this);
        if (props.getDataUsage() != Constants.INDEXED) {
            return;
        }
        alternateKeys.clear();
        n.nodeListOptional.accept(this);
    }

    @Override
    public void visit(NodeToken n) {
    }

    @Override
    public void visit(FileName n) {
        props = SymbolTable.getScope().lookup(n.cobolWord.nodeToken.tokenImage, SymbolConstants.FILE);
        if (props == null) {
            reportError("Unknown File Name: " + n.cobolWord.nodeToken.tokenImage + ". Contact RES support.", false);
        }
    }

    @Override
    public void visit(KeyClause n) {
        n.qualifiedDataName.accept(this);
    }

    @Override
    public void visit(FileAndSortDescriptionEntryClause n) {
        // TODO Auto-generated method stub
        super.visit(n);
    }

    @Override
    public void visit(QualifiedDataName n) {
        props = null;
        n.nodeSequence.accept(this);
        if (lastDataName == null) {
            return;
        }
        props = SymbolTable.getScope().lookup(lastDataName, SymbolConstants.DATA);
        if (props == null) {
            reportError("Unknown Symbol :" + lastDataName);
        }
    }

    @Override
    public void visit(DataName n) {
        lastDataName = n.cobolWord.nodeToken.tokenImage;
    }

    @Override
    public void visit(AlternateRecordKeyClause n) {
        n.qualifiedDataName.accept(this);
        alternateKeys.add(props);
    }

    @Override
    public void visit(FileControlClause n) {
        // TODO Auto-generated method stub
        super.visit(n);
    }

    private void reportError(String msg) {
        RunTimeUtil.getInstance().reportError(msg, true);
    }

    private void reportError(String msg, boolean exit) {
        RunTimeUtil.getInstance().reportError(msg, exit);
    }
    PrintSymbol printSymbol = null;
}
 public class SymbolTable {

	final int symbol_table_size = 4096;
    SymbolCell[] symbol_table = new SymbolCell[symbol_table_size];

    //final int scope_stack_length = 1024;

    int scope_stack_top = 0;

    int[] scope_stack = new int[symbol_table_size];
    
	public static int paragraphMark = 0;
	public static int tempVariablesMark = 0;
	public static int duplicateJavaNameMark = 0;
        private static long symbolInternalMark=0;
         private boolean cloneOnLookup = false;
	private static SymbolTable table = null;
	
	private static Stack<SymbolProperties> programs=null;
	
	public SymbolProperties getCurrentProgram() {
		if(programs==null||programs.size()<=0) return null;
		return programs.peek();
	}

	public SymbolProperties getFirstProgram() {
		if(programs==null||programs.size()<=0) return null;
		return programs.get(0);
	}

	public boolean isCurrentProgramTopLevel() {
		if(programs==null||programs.size()!=1) return false;
		return true;
	}
	
	public boolean isTopLevePrograml(SymbolProperties props) {
		if(programs==null||programs.size()!=1) return false;
		return programs.peek().getDataName().equalsIgnoreCase(props.getDataName());
	}
	
	public boolean isCurrentProgram(SymbolProperties props) {
		if(programs==null||programs.size()<=0) return false;
		return programs.peek().getDataName().equalsIgnoreCase(props.getDataName());
	}
	
	//public static Cobol2Java cobol2Java = new Cobol2Java();
	   
    public void setCloneOnLookup(boolean cloneOnLookup) {
		this.cloneOnLookup = cloneOnLookup;
	}

	public boolean isCloneOnLookup() {
		return cloneOnLookup;
	}

	static final String TOSTRING_REF_STRING_="bytes_";
    
    private SymbolTable () {
		scope_stack_top = 0;
		for (int i = 0; i<symbol_table_size; i++)
		    symbol_table[i] = null;
    }

    public void startProgram(SymbolProperties program) {
    	if(programs==null) programs = new Stack<SymbolProperties>();
    	programs.push(program);
    }
    
    public void endProgram() {
    	if(programs==null||programs.size()<=0)
    		RunTimeUtil.getInstance().reportError("FatalError: Program Stack empty",true);
    	programs.pop();
    }
    
    public static SymbolTable getScope() {
    	if(table==null) table=new SymbolTable();
    	return table;
    }
    
    public static void clear() {
    	table=null;
    	programs=null;
        paragraphMark = 0;
	tempVariablesMark = 0;
	duplicateJavaNameMark = 0;
        symbolInternalMark=0;
    }
    
    
    static void fatal_error ( String msg, Node x ) {
    	throw new Error("*** Fatal error: " + msg + x);
    }

    /* a hashing function for strings */
    int hash ( String s ) {
    	if(s==null) {
    		System.out.println("*** Fatal error: ERROR IN NULL STRING BEING HASHED");
    		System.exit(-1);
    		return -1;
    	}
    	else
    		return Math.abs(s.hashCode()) % symbol_table_size;
    }

    /* a hashing function for strings */
    int hash ( String s, int table_size ) {
    	if(s==null) {
    		System.out.println("*** Fatal error: ERROR IN NULL STRING BEING HASHED");
    		System.exit(-1);
    		return -1;
    	}
    	else
    		return Math.abs(s.hashCode()) % table_size;
    }
    
    /* insert a new item in the symbol table */
    public void insert ( String key, SymbolProperties binding ) {
    	
    key=key.toUpperCase();
	int loc = hash(key);
        binding.setInternalMark(symbolInternalMark++);
	SymbolCell o=symbol_table[loc];
	//if(symbol_table[loc]!=null)
		//for (SymbolCell s = symbol_table[loc]; s != null; s=s.next)
		  //  o=s;
	symbol_table[loc] = new SymbolCell(key,binding,o);
	if (scope_stack_top >= symbol_table_size)
	   RunTimeUtil.getInstance().reportError("Fatal Error: Symbol Table Stack Overflow.Exiting",true);
	else scope_stack[scope_stack_top++] = loc;
    }

    /* replace an item with a given name in the symbol table */
    public void replace ( String key, SymbolProperties binding ) {
    key=key.toUpperCase();
	int loc = hash(key);
	for (SymbolCell s = symbol_table[loc]; s != null; s=s.next)
	    if (s.name.equals(key))
		s.binding = binding;
    }

    private SymbolProperties cloneSymbol(SymbolProperties props) {
        if(props.getJavaType()!=null)
            props.setIdentifierType(props.getJavaType().getType());
    	if(isCloneOnLookup()) {
    		props.setIndexesWorkSpace(null);
    		props.setSubstringWorkSpace(null);
			try {
				return (SymbolProperties)props.clone();
			} catch (CloneNotSupportedException e) {
				RunTimeUtil.getInstance().reportError(e.getMessage(),false);
			}
    	}
    	return props;
    }
    
    SymbolProperties ret=null;
    /* lookup for an item in the symbol table */
    public SymbolProperties lookup ( String key ) {
    	if((getCurrentProgram()!=null&&
    			(ret=lookup(key,getCurrentProgram().getDataName()))!=null))
    			return cloneSymbol(ret);
	    key=key.toUpperCase();
		int loc = hash(key);
		for (SymbolCell s = symbol_table[loc]; s != null; s=s.next)
		    if (s.name.equalsIgnoreCase(key)) {
	    		return cloneSymbol(s.binding);
		    }
		return null;      // if not found
    }

    /* lookup for an item and parent in the symbol table */
    public SymbolProperties lookup ( String key, String par ) {
        key=key.toUpperCase();
        par=par.toUpperCase();
	int loc = hash(key);
	boolean passedAProgram=false;
	for (SymbolCell s = symbol_table[loc]; s != null; s=s.next)
	    if (s.name.equalsIgnoreCase(key)) {
	    	SymbolProperties props =s.binding;
	    	boolean first=true;
	    	do {
		    	if(!first) {
			    	if(props==null&&(par==null||par.length()==0))
			    		return cloneSymbol(s.binding);
			    	String name = (String) props.getDataName();	
			    	if (name.equalsIgnoreCase(par)&&(!passedAProgram||s.binding.isExternal()))
			    		return cloneSymbol(s.binding);
			    	else 
			    		if(props.isProgram()) {
			    			break;
			    		}
		    	}
		    	first = false;
		    	props = props.getParent();
	    	} while(props!=null);
	    }
	return null;       // if not found
    }
    
    /* lookup for an item and parent in the symbol table */
    public SymbolProperties lookup ( String key, int type ) {
       	if((getCurrentProgram()!=null&&
    			(ret=lookup(key,getCurrentProgram().getDataName()))!=null))
       		if(ret.getType()==type)
    			return cloneSymbol(ret);
       		else return null;
    key=key.toUpperCase();
	int loc = hash(key);
	for (SymbolCell s = symbol_table[loc]; s != null; s=s.next) {
	    if (s.name.equalsIgnoreCase(key)&&s.binding.getType()==type) {
    		return cloneSymbol(s.binding);
	    }
	}
	return null;       // if not found
    }
    
    /* start a new environment */
    public void begin_scope () {
	if (scope_stack_top >= symbol_table_size)
		RunTimeUtil.getInstance().reportError("Fatal Error: Symbol Table Stack Overflow.Exiting",true);
	else scope_stack[scope_stack_top++] = -1;
    }

    /* pop the last environment */
    public void end_scope () {
	int i = scope_stack_top-1;
	for (; scope_stack[i]>=0 && i>0; i--) {
	    int loc = scope_stack[i];
	    symbol_table[loc] = symbol_table[loc].next;
	};
	scope_stack_top = i;
    }

    /* display the content of the symbol table */
	public void display () {
	SymbolCell[] s = new SymbolCell[symbol_table_size];
	for (int i = 0; i<symbol_table_size; i++)
	    s[i] = symbol_table[i];
	for (int i = scope_stack_top-1; i>=0; i--)
	    if (scope_stack[i] == -1)
	       System.out.println("----------------");
	    else { SymbolCell c = s[scope_stack[i]];
	           s[scope_stack[i]] = c.next;
	       SymbolProperties o1=null,o2=null;
	       o1= c.binding;
	       o2= (SymbolProperties) c.binding.getParent();
	       if (o1==null)
	    	   System.out.println("***ERROR IN SYMBOL TABLE"+c.name);
	       else {
	    	   System.out.print("DATA="+c.name);
	    	   if(o2!=null)
	    		  System.out.print(" Parent=" + 
				   (String)o2.getDataName());
	    	   int i1 ;
	    	   i1=o1.getLevelNumber();
	    	   System.out.print(" LEVEL="+i1);
	    	   i1=o1.getOffset();
    		   System.out.print(" Offset="+i1);
	    	   i1=o1.getLength();
    		   System.out.print(" Length="+i1);
	    	   i1=o1.getDataUsage();
    		   System.out.print(" USAGE="+i1);
	    	   String p1 = null;
	    	   if((p1=(String)o1.getPictureString())!=null)
	    		   System.out.print(" PICTURE="+p1);
	    	   p1 = null;
	    	   if((p1=(String)o1.getValue1())!=null)
	    		   System.out.print(" VALUE="+p1);
	    	   p1 = null;
	    	   if((p1=(String)o1.getValue2())!=null)
	    		   System.out.print(" THROUGH"+p1);
	    	   boolean b1 =  o1.getRef();
    		   System.out.print("Ref="+b1);
	    	   b1 = o1.getMod();
    		   System.out.print("Mod="+b1);
	    	   b1 = o1.getIsSuppressed();
    		   System.out.print("IS_SUPRESSED="+b1);
	    	   b1 = o1.getIsFormat();
    		   System.out.print("IsFormat(="+b1);
	       }
	       System.out.println();
	       if(o1!=null&&o1.getChildren()!=null) {
	    	   for (Iterator<SymbolProperties> ite=o1.getChildren().iterator();
	    	   		ite.hasNext();) {
	    		   o2=ite.next();
	    		   System.out.println("\t\t"+((o2==null)?"NullChild":((o2.getDataName())!=null)?
	    				   ((String)o2.getDataName()):"NullName"));
	    	   }
	       }
	    }
    }
    

    public static void visit(SymbolProperties props,Visitor visitor) {
    	if(props.isProgram()&&
    			!SymbolTable.getScope().isCurrentProgram(props)
    			||props.getType()==SymbolConstants.PARAGRAPH
    			||props.getType()==SymbolConstants.SECTION)
    		return;
    	//Preprocess
    	visitor.visitPreprocess(props);
       	
    	//Body
       	if(props.isFile())
    		visitor.visitFile(props);
    	else
    	if(props.getLevelNumber()==1&&props.getPictureString()==null)
    		visitor.visit01Group(props);
    	else
	    	if(props.getLevelNumber()==1&&props.getPictureString()!=null)
	    		visitor.visit01Element(props);
	    	else
		    	if(props.getLevelNumber()==77&&props.getPictureString()!=null)
		    		visitor.visit77Element(props);
		    	else
	    	    	if(props.getLevelNumber()==88)
	    	    		visitor.visit88Element(props);
	    	    	else
		        	if(props.getPictureString()==null)
		        		visitor.visitInnerGroup(props);
		    	    	else
		    	    	if(props.getPictureString()!=null)
		    	    		visitor.visitInnerElement(props);
			        	
    	
    	//Postprocess
    	visitor.visitPostprocess(props);
    	
    }
    
    public static void visit(ArrayList<SymbolProperties> children,Visitor visitor) {
    	//visit children
    	if(children!=null){
    		for(SymbolProperties child:children){
    			
    			visitor.visitChildPreprocess(child);
    			visit(child,visitor);
    			visitor.visitChildPostprocess(child);
    		}
    	} 
    		
    }
    
    public static boolean convert2Java() {
    	visit(SymbolTable.getScope().getCurrentProgram(), new PrintSymbol());
    	TranUtil.get().saveDatabaseProperties();
    	return true;
    }

}
 public class ClassFile {
	
	public static ClassFileWriter current=null;
	public static Stack<ClassFileWriter> files=new Stack<ClassFileWriter>();
	
	public PrintWriter out = null;
	public boolean importJavaUtil = false;
	public boolean importJavaIo = false;
	
	public static void doProgramScope(SymbolProperties props, boolean dataLevel) {
		if (files==null)
			files=new Stack<ClassFileWriter>();
		if(dataLevel)
			current=new DataClassFileWriter(props);
		else  {
			if(SymbolTable.getScope().isCurrentProgramTopLevel()) {			
			current=new ProgramClassFileWriter(props);
			} else
				((ProgramClassFileWriter)current).printHeader(props,true);
		}
		files.push(current);
	}

	public static void doProgramScope(ClassFileWriter gen) {
		current=gen;
		files.push(current);
	}

	public static void endProgramScope() {
		if(current==null)
			return;
		current.println("}");
		current.println("}",true);
		if(files.peek().isData()||SymbolTable.getScope().isCurrentProgramTopLevel()) {			
		current.close();
		
		} else 
			current.backTab();
		files.pop();
		if(files.size()>0) {
			current=files.peek();
		} else {
			current=null;
		}
	}

	public static void doMethodScope(String line,boolean bi) {
		if(current==null)
			return;
		current.println(line,bi);
	}

	public static void endMethodScope(boolean bi) {
		if(current==null)
			return;
		current.println("}",bi);
	}

	public static void println(String line,boolean bi) {
		if(current==null)
			return;
		current.println(line,bi);
	}
	
	public static void print(String line,boolean bi) {
		if(current==null)
			return;
		current.print(line,bi);
	}
	
	public static void printPlainln(String line,boolean bi) {
		if(current==null)
			return;
		current.println(line,bi);
	}
	
	public static void printPlain(String line,boolean bi) {
		if(current==null)
			return;
		current.print(line,bi);
	}
	
	public static void printPlain(char c,boolean bi) {
		if(current==null)
			return;
		current.printPlain(c,bi);
	}

	public static void tab(boolean bi) {
		if(current==null)
			return;
		current.tab(bi);
	}
	
	public static void backTab(boolean bi) {
		if(current==null)
			return;
		current.backTab(bi);
	}
	
	////
	
	public static void doMethodScope(String line) {
		if(current==null)
			return;
		current.println(line);
	}

	public static void endMethodScope() {
		if(current==null)
			return;
		current.println("}");
	}

	public static void println(String line) {
		if(current==null)
			return;
		current.println(line);
	}
	
	public static void print(String line) {
		if(current==null)
			return;
		current.print(line);
	}
	
	public static void printPlainln(String line) {
		if(current==null)
			return;
		current.println(line);
	}
	
	public static void printPlain(String line) {
		if(current==null)
			return;
		current.print(line);
	}
	
	public static void printPlain(char c) {
		if(current==null)
			return;
		current.printPlain(c);
	}

	public static void tab() {
		if(current==null)
			return;
		current.tab();
	}
	
	public static void backTab() {
		if(current==null)
			return;
		current.backTab();
	}


	
	
}

import com.res.cobol.parser.CobolParser;
import com.res.cobol.parser.CobolParserTokenManager;
import com.res.cobol.parser.ParseException;
import com.res.cobol.parser.RESCharStream;
import com.res.cobol.parser.TokenMgrError;
import com.res.cobol.syntaxtree.CompilationUnit;
import com.res.cobol.visitor.TreeDumper;
import java.io.File;
import com.res.common.RESConfig;
import com.res.common.RESContext;
import com.res.java.translation.engine.Cobol2Java;
import com.res.java.translation.engine.CobolFillTable;
import com.res.java.translation.engine.CobolRecode;
import com.res.java.translation.engine.TranUtil;
import com.res.java.translation.engine.TranslationTable;
import com.res.java.translation.engine.VsamIsam2DbGen;
import com.res.java.translation.symbol.SymbolTable;
import com.res.java.util.ClassFile;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStreamReader;

package com.res.cobol;

/*****************************************************************************
Copyright 2009 Venkat Krishnamurthy
This file is part of RES.

RES is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

RES is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with RES.  If not, see <http://www.gnu.org/licenses/>.

@author VenkatK mailto: open.cobol.to.java at gmail.com
 ******************************************************************************/


public class Main {

    private RESConfig config = RESConfig.getInstance();
    private static RESContext context = new RESContext();
    private boolean doListDir = false;
    private Preprocessor preprocessor = new Preprocessor();
    public long startClock;

    public static void main(String[] args) {

        Main instance = new Main();

        try {
            int i = instance.getOptions(args);

            instance.startClock = System.currentTimeMillis();

            System.out.println("RES Cobol 2 Java" + RESConfig.getInstance().versionString + "- COPYRIGHT 2009");

            if (context.isProcessVerbose()) {
                System.out.println("Options: " + context.getOptionsVerbose().toString());
            }

            while (i < args.length) {
                context.setCobol2Java(Cobol2Java.getInstance(context));
                context.setCobolFillTable(CobolFillTable.getInstance(context));
                context.setCobolRecode(CobolRecode.getInstance(context));
                instance.execute(new File(args[i++]));
                CobolParserTokenManager.commentLines.clear();
                CobolParserTokenManager.lastToken = null;
                context.getCharStream().Done();
                CobolFillTable.clear();
                CobolRecode.clear();
                Cobol2Java.clear();

                TranslationTable.clear();
