/** * Flatten an expression with respect to an associative operator: for example the expression (a+b) * + (c+d) becomes list(a,b,c,d), with the list in canonical order (sorted by hashCode) * * @param list a list provided by the caller to contain the result * @return the list of expressions */ private List flattenExpression(List list) { if (operand0 instanceof BinaryExpression && ((BinaryExpression) operand0).operator == operator) { ((BinaryExpression) operand0).flattenExpression(list); } else { int h = operand0.hashCode(); list.add(operand0); int i = list.size() - 1; while (i > 0 && h > list.get(i - 1).hashCode()) { list.set(i, list.get(i - 1)); list.set(i - 1, operand0); i--; } } if (operand1 instanceof BinaryExpression && ((BinaryExpression) operand1).operator == operator) { ((BinaryExpression) operand1).flattenExpression(list); } else { int h = operand1.hashCode(); list.add(operand1); int i = list.size() - 1; while (i > 0 && h > list.get(i - 1).hashCode()) { list.set(i, list.get(i - 1)); list.set(i - 1, operand1); i--; } } return list; }
/** Is this expression the same as another expression? */ public boolean equals(Object other) { if (other instanceof BinaryExpression) { BinaryExpression b = (BinaryExpression) other; if (operator == b.operator) { if (operand0.equals(b.operand0) && operand1.equals(b.operand1)) { return true; } if (isCommutative(operator) && operand0.equals(b.operand1) && operand1.equals(b.operand0)) { return true; } if (isAssociative(operator) && pairwiseEqual( flattenExpression(new ArrayList(4)), b.flattenExpression(new ArrayList(4)))) { return true; } } if (isInverse(operator, b.operator) && operand0.equals(b.operand1) && operand1.equals(b.operand0)) { return true; } } return false; }