gt: 					if (type == 0) datai.wf.vex = dataj.wf.vex = groupIn;
context: package secondstage;
  
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
  
  import org.apache.poi.hssf.usermodel.HSSFCell;
  import org.apache.poi.hssf.usermodel.HSSFRow;
  import org.apache.poi.hssf.usermodel.HSSFSheet;
  
  import datastructure.Data;
  import datastructure.Formula;
  import datastructure.Formulas;
  import datastructure.WeakFeature;
  
  public class ExtractGapTemplate {
  	
  	public static void extract(HSSFSheet sheet, int row1, int row2, int col1, int col2) {
  		//Basically, every column is a vex group.
  		//Try to combine some vex groups into one vex group.
  		for (int i =col1; i <col2; i++) {
  			for (int j = i+1; j <=col2; j++) {
  				boolean flag = true;
  				
  				for (int row =row1; row <=row2; row++) {
  					HSSFRow r = sheet.getRow(row);
  					if (r == null) continue;
  					HSSFCell celli = r.getCell(i);
  					HSSFCell cellj = r.getCell(j);
  					
  					if ((celli==null || celli.getCellType()!=HSSFCell.CELL_TYPE_FORMULA) 
  							&& cellj != null && cellj.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
  						flag = false; break;
  					}
  					if ((cellj==null || cellj.getCellType()!=HSSFCell.CELL_TYPE_FORMULA) 
  							&& celli != null && celli.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
  						flag = false; break;
  					}
  					
  					if (celli != null && celli.getCellType() == HSSFCell.CELL_TYPE_FORMULA &&
  							cellj != null && cellj.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
  						Formula fi = Formulas.fMap.get(row* Formulas.base + i);
  						Formula fj = Formulas.fMap.get(row* Formulas.base + j);
  						if (! fi.getSyntaxTree().equals(fj.getSyntaxTree())) {
  							flag = false; break;
  						}
  					}
  				}
  				
  				if (flag) {
  					//Mark the vex group.
  					//Compare the referenced data cell.
  					for (int row =row1; row <=row2; row++) {
  						HSSFRow r = sheet.getRow(row);
  						if (r == null) continue;
  						HSSFCell celli = r.getCell(i);
  						HSSFCell cellj = r.getCell(j);
  						
  						if (celli != null && celli.getCellType() == HSSFCell.CELL_TYPE_FORMULA &&
  								cellj != null && cellj.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
  							Formula fi = Formulas.fMap.get(row* Formulas.base + i);
  							Formula fj = Formulas.fMap.get(row* Formulas.base + j);
  							int vexgroupIn = -1;
  							if (fi.wf.vex > -1) {
  								if (fj.wf.vex == -1) {
  									vexgroupIn = fj.wf.vex = fi.wf.vex;
  									addReferencedData(sheet, fi, fj, vexgroupIn, 0);
  								}
  							}
  							else {
  								vexgroupIn = fi.wf.vex = fj.wf.vex = WeakFeature.vexN++;
  								addReferencedData(sheet, fi, fj, vexgroupIn, 0);
  							}
  						}
  					}
  				}
  			}
  		}
  		
  		//Basically, every row is a hex group.
  		//Try to combine some hex groups into one hex group.
  		for (int i =row1; i <row2; i++) {
  			for (int j = i+1; j <=row2; j++) {
  				boolean flag = true;
  				HSSFRow ri = sheet.getRow(i);
  				HSSFRow rj = sheet.getRow(j);
  				if (ri == null || rj == null) continue;
  				
  				for (int column =col1; column <=col2; column++) {
  					
  					HSSFCell celli = ri.getCell(column);
  					HSSFCell cellj = rj.getCell(column);
  					 
  					if ((celli==null || celli.getCellType()!=HSSFCell.CELL_TYPE_FORMULA) 
  							&& cellj != null && cellj.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
  						flag = false; break;
  					}
  					if ((cellj==null || cellj.getCellType()!=HSSFCell.CELL_TYPE_FORMULA) 
  							&& celli != null && celli.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
  						flag = false; break;
  					}
  					
  					if (celli != null && celli.getCellType() == HSSFCell.CELL_TYPE_FORMULA &&
  							cellj != null && cellj.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
  						Formula fi = Formulas.fMap.get(i* Formulas.base + column);
  						Formula fj = Formulas.fMap.get(j* Formulas.base + column);
  						if (! fi.getSyntaxTree().equals(fj.getSyntaxTree())) {
  							flag = false; break;
  						}
  					}
  				}
  				
  				if (flag) {
  					//Mark the hex group.
  					//Compare the referenced data cell.
  					for (int column =col1; column <=col2; column++) {
  						
  						HSSFCell celli = ri.getCell(column);
  						HSSFCell cellj = rj.getCell(column);
  						
  						if (celli != null && celli.getCellType() == HSSFCell.CELL_TYPE_FORMULA &&
  								cellj != null && cellj.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
  							Formula fi = Formulas.fMap.get(i* Formulas.base + column);
  							Formula fj = Formulas.fMap.get(j* Formulas.base + column);
  							
  							int hexgroupIn = -1;
  							if (fi.wf.hex > -1) {
  								if (fj.wf.hex == -1) {
  									hexgroupIn = fj.wf.hex = fi.wf.hex;
  									addReferencedData(sheet, fi, fj, hexgroupIn, 1);
  								}
  							}
  							else {
  								hexgroupIn = fi.wf.hex = fj.wf.hex = WeakFeature.hexN++;
  								addReferencedData(sheet, fi, fj, hexgroupIn, 1);
  							}
  						}
  					}
  				}
  			}
  		}
  	}
  	
  	private static void addReferencedData(HSSFSheet sheet, Formula fi,Formula fj,int groupIn, int type) {
  		String content = fi.getSyntaxTree()+"";
  		int start = 0;
  		while (true) {
  			Pattern p = Pattern.compile("R(\\[?)(-*\\d+)(\\]?)C(\\[?)(-*\\d+)(\\]?):R(\\[?)(-*\\d+)(\\]?)C(\\[?)(-*\\d+)(\\]?)");
  			Matcher matcher = p.matcher(content);
  			if (! matcher.find(start)) break;
  			start = matcher.end();
  			
  			int row1, column1, row2, column2;
  			if (matcher.group(2) == null) return;
  			row1 = Integer.parseInt(matcher.group(2));
  			if (matcher.group(1) != null && matcher.group(1).equals("[")) 
  				row1 += fi.getRow();
  				
  			column1 = Integer.parseInt(matcher.group(5));
  			if (matcher.group(4) != null && matcher.group(4).equals("[")) 
  				column1 += fi.getColumn();
  			
  			if (matcher.group(8) == null) {
  				subMatch(sheet, row1, column1, fj.getRow()-fi.getRow()+row1, fj.getColumn()-fi.getColumn()+column1,
  						groupIn, type);
  			}
  			else {
  				row2 = Integer.parseInt(matcher.group(8));
  				if (matcher.group(7) != null && matcher.group(7).equals("[")) 
  					row2 += fi.getRow();
  					
  				column2 = Integer.parseInt(matcher.group(11));
  				if (matcher.group(10) != null && matcher.group(10).equals("[")) 
  					column1 += fi.getColumn();
  				
  				for (int rowi = row1; rowi<=row2; rowi++)
  					for (int columnj = column1; columnj<=column2; columnj++) {
  						subMatch(sheet, row1, column1, 
  								fj.getRow()-fi.getRow()+rowi, fj.getColumn()-fi.getColumn()+columnj,
  								groupIn, type);
  					}
  			}
  			
  			
  		}
  	}
  	
  	private static void subMatch(HSSFSheet sheet, int rowi, int columni, int rowj, int columnj, int groupIn, int type) {
  		HSSFRow ri = sheet.getRow(rowi);
  		HSSFRow rj = sheet.getRow(rowj);
  		if (ri != null) {
  			if (rj == null) {
  				Data datai = Formulas.dMap.get(rowi* Formulas.base + columni);
  				if (datai != null) {
  					if (type == 0) datai.wf.vex = groupIn;
  					else datai.wf.hex = groupIn;
  				}
  			}
  			else {
  				Data datai = Formulas.dMap.get(rowi* Formulas.base + columni);
  				Data dataj = Formulas.dMap.get(rowj* Formulas.base + columnj);
  				if (datai != null && dataj != null) {
  