package translating; import java.util.ArrayList; import java.util.HashSet; import parser.ASTadditiveArithmeticTerm; import parser.ASTarithmeticTerm; import parser.ASTatom; import parser.ASTatomicArithmeticTerm; import parser.ASTmultiplicativeArithmeticTerm; import parser.ASTterm; import parser.ASTvar; import parser.SimpleNode; import parser.SparcTranslatorTreeConstants; /** * This class splits an expression containing arithmetic operations into a set * of atoms of the form A = B, A is a variable and B is of the form t_1 op t_2, * where t_1 and t_2 are arithmetic terms not containing operations and op is * one of *,-,+. */ public class ExpressionSplitter { // set of variable names which were already used in the rule HashSet<String> usedVariableNames; // prefix to be added to introduced variables final String prefix = "VAR_"; // variable id to be used in generating new names int varid = 0; public ExpressionSplitter(HashSet<String> usedVariableNames) { this.usedVariableNames = usedVariableNames; } /** * Split arithmetic term * * @param term * @param newAtoms * array where newly introduced atoms will be added * @return equivalent list of atoms of the form A=t1 op t2 */ public ASTterm split(ASTarithmeticTerm term, ArrayList<ASTatom> newAtoms) { return split((ASTadditiveArithmeticTerm) term.jjtGetChild(0), newAtoms); } /** * Split additive arithmetic term possibly containing one or more + and - * operations * * @param term * @param newAtoms * array where newly introduced atoms will be added * @return equivalent list of atoms of the form A=t1 op t2 */ private ASTterm split(ASTadditiveArithmeticTerm additiveTerm, ArrayList<ASTatom> newAtoms) { return split(additiveTerm, additiveTerm.jjtGetNumChildren()-1, newAtoms); } /** * Split additive arithmetic term possibly containing one or more operands * connected by +, - operators * * @param term * @param newAtoms * array where newly introduced atoms will be added * @param fIndex * the first index in additiveTerm children to consider * @return equivalent list of atoms of the form A=t1 op t2 */ private ASTterm split(ASTadditiveArithmeticTerm additiveTerm, int fIndex, ArrayList<ASTatom> newAtoms) { ASTterm lastMultiplicative = split( (ASTmultiplicativeArithmeticTerm) additiveTerm .jjtGetChild(fIndex), newAtoms); // if this is the last term: if (fIndex == 0) { return lastMultiplicative; } else { // create new variable ASTvar newVar = new ASTvar(SparcTranslatorTreeConstants.JJTVAR); newVar.image = createUniqueVarName(); ASTterm newVarTerm = ASTterm.createArithmeticVarTerm(newVar); //take the last two multiplicative Terms ASTterm allButLast=split(additiveTerm,fIndex-1,newAtoms); //create new additive Term ASTterm newTerm=new ASTterm(SparcTranslatorTreeConstants.JJTTERM); ASTarithmeticTerm newATerm=new ASTarithmeticTerm(SparcTranslatorTreeConstants.JJTARITHMETICTERM); ASTadditiveArithmeticTerm newAdTerm=new ASTadditiveArithmeticTerm(SparcTranslatorTreeConstants.JJTADDITIVEARITHMETICTERM); newAdTerm.image="+"+Character.toString(additiveTerm.image.charAt(fIndex)); newAdTerm.jjtAddChild(allButLast.getLeftMostMultiplicativeTerm(), 0); newAdTerm.jjtAddChild(lastMultiplicative.getLeftMostMultiplicativeTerm(), 1); newATerm.jjtAddChild(newAdTerm, 0); newTerm.jjtAddChild(newATerm, 0); newAtoms.add(createEqAtom(newVarTerm,newTerm)); return newVarTerm; } } /** * Split multiplicative arithmetic term possibly containing one or more * operands connected by * operator * * @param term * @param newAtoms * array where newly introduced atoms will be added * @param fIndex * the first index in additiveTerm children to consider * @return equivalent list of atoms of the form A=t1 op t2 */ private ASTterm split(ASTmultiplicativeArithmeticTerm multTerm, ArrayList<ASTatom> newAtoms) { return split(multTerm, multTerm.jjtGetNumChildren()-1, newAtoms); } /** * Split multiplicative arithmetic term possibly containing one or more * operands connected by * operator * * @param term * @param newAtoms * array where newly introduced atoms will be added * @param fIndex * the first index in additiveTerm children to consider * @return equivalent list of atoms of the form A=t1 op t2 */ private ASTterm split(ASTmultiplicativeArithmeticTerm mTerm, int fIndex, ArrayList<ASTatom> newAtoms) { // TODO Auto-generated method stub ASTterm lastAtomic = split( (ASTatomicArithmeticTerm) mTerm.jjtGetChild(fIndex), newAtoms); // if this is the last term: if (fIndex == 0) { return lastAtomic; } else { // create new variable ASTvar newVar = new ASTvar(SparcTranslatorTreeConstants.JJTVAR); newVar.image = createUniqueVarName(); ASTterm newVarTerm = ASTterm.createArithmeticVarTerm(newVar); //take the last two multiplicative Terms ASTterm allButLast=split(mTerm,fIndex-1,newAtoms); //create new additive Term ASTterm newTerm=new ASTterm(SparcTranslatorTreeConstants.JJTTERM); ASTarithmeticTerm newATerm=new ASTarithmeticTerm(SparcTranslatorTreeConstants.JJTARITHMETICTERM); ASTadditiveArithmeticTerm newAdTerm=new ASTadditiveArithmeticTerm(SparcTranslatorTreeConstants.JJTADDITIVEARITHMETICTERM); ASTmultiplicativeArithmeticTerm newMTerm=new ASTmultiplicativeArithmeticTerm(SparcTranslatorTreeConstants.JJTMULTIPLICATIVEARITHMETICTERM); newMTerm.image=Character.toString(mTerm.image.charAt(fIndex-1));; newAdTerm.image="+"; newMTerm.jjtAddChild(allButLast.getLeftMostAtomicTerm(), 0); newMTerm.jjtAddChild(lastAtomic.getLeftMostAtomicTerm(), 1); newTerm.jjtAddChild(newATerm, 0); newATerm.jjtAddChild(newAdTerm, 0); newAdTerm.jjtAddChild(newMTerm, 0); newAtoms.add(createEqAtom(newVarTerm,newTerm)); newMTerm.toString(); return newVarTerm; } } /** * Split atomic arithmetic term possibly containing one or more * operands * * @param term * @param newAtoms * array where newly introduced atoms will be added * @return equivalent list of atoms of the form A=t1 op t2 */ private ASTterm split(ASTatomicArithmeticTerm atomTerm, ArrayList<ASTatom> newAtoms) { if(atomTerm.jjtGetNumChildren()>0) { SimpleNode child=(SimpleNode)atomTerm.jjtGetChild(0); if(child.getId()==SparcTranslatorTreeConstants.JJTVAR) { return ASTterm.createArithmeticVarTerm((ASTvar)child); } else { // the child is arithmetic term return split((ASTarithmeticTerm)child,newAtoms); } } else { // there are no children, which means there is a number return new ASTterm(Long.parseLong(atomTerm.image)); } } /** * Create unique variable names. Considers all variable names which were * already used * * @return name string, representing unique variable name */ private String createUniqueVarName() { while (usedVariableNames.contains(prefix + varid)) { ++varid; } usedVariableNames.add(prefix + varid); return prefix + varid; } /** * Create atom of the form (left term)=(right term) * * @param left * left term * @param right * right term * @return atom */ private ASTatom createEqAtom(ASTterm left, ASTterm right) { ASTatom newAtom = new ASTatom(SparcTranslatorTreeConstants.JJTATOM); newAtom.jjtAddChild(left, 0); newAtom.jjtAddChild(right, 1); newAtom.image = "="; return newAtom; } }