001: package org.hansel.stack;
002:
003: public class OrOrOp extends BinaryOperatorEntry {
004: private static final Compressor[] COMPRESSORS = new Compressor[] {
005: new OrOrCompressor(), new AndCompressor(),
006: new NotCompressor() };
007:
008: public OrOrOp(HanselValue op1, HanselValue op2) {
009: super ("||", 11, op1, op2);
010: }
011:
012: public HanselValue compress() {
013: HanselValue result = this ;
014:
015: int i = 0;
016: while ((i < COMPRESSORS.length) && (result instanceof OrOrOp)) {
017: HanselValue op1 = ((OrOrOp) result).getOperator1()
018: .compress();
019: HanselValue op2 = ((OrOrOp) result).getOperator2()
020: .compress();
021: HanselValue newResult = null;
022:
023: if (COMPRESSORS[i].canApply(op1, op2)) {
024: newResult = COMPRESSORS[i].compress(op1, op2);
025:
026: if (result.toString().length() < newResult.toString()
027: .length()) {
028: result = newResult;
029: }
030: } else if (COMPRESSORS[i].canApply(op2, op1)) {
031: newResult = COMPRESSORS[i].compress(op2, op1);
032:
033: if (result.toString().length() < newResult.toString()
034: .length()) {
035: result = newResult;
036: }
037: }
038:
039: if ((newResult != null)
040: && (result.toString().length() > newResult
041: .toString().length())) {
042: result = newResult;
043: i = 0;
044: } else {
045: i++;
046: }
047: }
048:
049: return result;
050: }
051:
052: private interface Compressor {
053: boolean canApply(HanselValue op1, HanselValue op2);
054:
055: HanselValue compress(HanselValue op1, HanselValue op2);
056: }
057:
058: /**
059: * Compresses "a || (!a && b [ && c] )" to "a || b [ && c]".
060: */
061: public static class OrOrCompressor implements Compressor {
062: public boolean canApply(HanselValue op1, HanselValue op2) {
063: if (!(op1 instanceof AndAndOp)) {
064: return false;
065: }
066:
067: HanselValue op11 = ((AndAndOp) op1).getOperator1();
068: String searchFor = op2.invert().toString();
069:
070: while (op11 != null) {
071: if (op11.toString().equals(searchFor)) {
072: return true;
073: }
074:
075: // If op11 is an instance of AndAndOp, we still might
076: // find an adequate operator.
077: if (op11 instanceof AndAndOp) {
078: op11 = ((AndAndOp) op11).getOperator1();
079: } else {
080: op11 = null;
081: }
082: }
083:
084: return false;
085: }
086:
087: public HanselValue compress(HanselValue op1, HanselValue op2) {
088: String searchFor = op2.invert().toString();
089: HanselValue remainder = ((AndAndOp) op1).getOperator2();
090: HanselValue extract = ((AndAndOp) op1).getOperator1();
091:
092: while (!(extract.toString().equals(searchFor))) {
093: remainder = new AndAndOp(((AndAndOp) extract)
094: .getOperator2(), remainder);
095: extract = ((AndAndOp) extract).getOperator1();
096: }
097:
098: return new OrOrOp(op2, remainder);
099: }
100: }
101:
102: /**
103: * Compresses "a && (a || b)" to "a && b".
104: */
105: public static class AndCompressor implements Compressor {
106: public boolean canApply(HanselValue op1, HanselValue op2) {
107: return (op1 instanceof AndAndOp)
108: && (op2 instanceof AndAndOp);
109: }
110:
111: public HanselValue compress(HanselValue op1, HanselValue op2) {
112: AndAndOp and1 = (AndAndOp) op1;
113: AndAndOp and2 = (AndAndOp) op2;
114:
115: String term = and2.getOperator1().toString();
116: HanselValue eliminated = eliminate(and1, term);
117:
118: if (eliminated != null) {
119: return new AndAndOp(and2.getOperator1(), new OrOrOp(
120: eliminated, and2.getOperator2()).compress());
121: }
122:
123: return new OrOrOp(op1, op2);
124: }
125:
126: private HanselValue eliminate(AndAndOp and, String term) {
127: HanselValue op1 = and.getOperator1();
128:
129: // Does this and contain the term?
130: if (op1.toString().equals(term)) {
131: return and.getOperator2();
132: }
133:
134: // if not: Try to eliminate recursivly
135: if (op1 instanceof AndAndOp) {
136: HanselValue eliminated = eliminate((AndAndOp) op1, term);
137: if (eliminated != null) {
138: return new AndAndOp(eliminated, and.getOperator2());
139: }
140: }
141:
142: // eliminating failed.
143: return null;
144: }
145: }
146:
147: /**
148: * Compresses "!a || !b" to "!(a && b)".
149: */
150: public static class NotCompressor implements Compressor {
151: public boolean canApply(HanselValue op1, HanselValue op2) {
152: return (op1 instanceof NotOp) && (op2 instanceof NotOp);
153: }
154:
155: public HanselValue compress(HanselValue op1, HanselValue op2) {
156: return new NotOp(new AndAndOp(op1.invert(), op2.invert()));
157: }
158: }
159:
160: }
|