Added support for xor in expressions

This commit is contained in:
hneemann 2016-07-04 12:10:57 +02:00
parent 10d53aab8f
commit 15714ba7fd
6 changed files with 79 additions and 51 deletions

View File

@ -39,6 +39,18 @@ public abstract class Operation implements Expression {
return simplify(new Or(Arrays.asList(exp), true));
}
/**
* Creates a new XOR expression
*
* @param a the expression to XOR
* @param b the expression to XOR
* @return the created expression
*/
public static Expression xor(Expression a, Expression b) {
return simplify(new XOr(a, b));
}
/**
* Creates a new OR expression
*
@ -222,4 +234,30 @@ public abstract class Operation implements Expression {
return "or" + super.toString();
}
}
/**
* The XOR expression
*/
public static final class XOr extends Operation {
private XOr(Expression a, Expression b) {
super(Arrays.asList(a, b), false);
}
@Override
protected boolean getNeutral() {
return false;
}
@Override
protected boolean calc(boolean a, boolean b) {
return (a || b) && (!a || !b);
}
@Override
public String toString() {
return "xor" + super.toString();
}
}
}

View File

@ -52,9 +52,11 @@ public class Parser {
private Expression parseOr() throws IOException, ParseException {
Expression ex = parseAnd();
while (tokenizer.peek() == OR) {
tokenizer.consume();
ex = Operation.or(ex, parseAnd());
while (tokenizer.peek() == OR || tokenizer.peek() == XOR) {
if (tokenizer.next() == OR)
ex = Operation.or(ex, parseAnd());
else
ex = Operation.xor(ex, parseAnd());
}
return ex;
}

View File

@ -11,7 +11,7 @@ import java.io.Reader;
public class Tokenizer {
enum Token {UNKNOWN, IDENT, AND, OR, NOT, OPEN, CLOSE, ONE, ZERO, EOF}
enum Token {UNKNOWN, IDENT, AND, OR, NOT, XOR, OPEN, CLOSE, ONE, ZERO, EOF}
private final Reader in;
private Token token;
@ -83,6 +83,9 @@ public class Tokenizer {
case ')':
token = Token.CLOSE;
break;
case '^':
token = Token.XOR;
break;
case '&':
c = readChar();
if (c != '&') unreadChar(c);
@ -98,6 +101,7 @@ public class Tokenizer {
token = Token.OR;
break;
case '¬':
case '~':
case '!':
token = Token.NOT;
break;
@ -150,8 +154,7 @@ public class Tokenizer {
private boolean isIdentChar(int c) {
return (c >= 'a' && c <= 'z')
|| (c >= 'A' && c <= 'Z')
|| (c == '_')
|| (c == '^');
|| (c == '_');
}
private boolean isNumberChar(int c) {

View File

@ -1,12 +1,10 @@
package de.neemann.digital.builder.circuit;
import de.neemann.digital.analyse.expression.*;
import de.neemann.digital.analyse.expression.Not;
import de.neemann.digital.builder.BuilderException;
import de.neemann.digital.builder.BuilderInterface;
import de.neemann.digital.core.basic.And;
import de.neemann.digital.core.basic.NAnd;
import de.neemann.digital.core.basic.NOr;
import de.neemann.digital.core.basic.Or;
import de.neemann.digital.core.basic.*;
import de.neemann.digital.core.element.Keys;
import de.neemann.digital.core.element.Rotation;
import de.neemann.digital.core.flipflops.FlipflopD;
@ -19,20 +17,14 @@ import de.neemann.digital.draw.elements.Tunnel;
import de.neemann.digital.draw.elements.VisualElement;
import de.neemann.digital.draw.elements.Wire;
import de.neemann.digital.draw.graphics.Vector;
import de.neemann.digital.draw.library.ElementLibrary;
import de.neemann.digital.draw.shapes.ShapeFactory;
import de.neemann.digital.gui.Main;
import de.neemann.digital.lang.Lang;
import javax.swing.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import static de.neemann.digital.analyse.expression.Not.not;
import static de.neemann.digital.analyse.expression.Operation.and;
import static de.neemann.digital.analyse.expression.Operation.or;
import static de.neemann.digital.draw.shapes.GenericShape.SIZE;
/**
@ -107,6 +99,8 @@ public class CircuitBuilder implements BuilderInterface<CircuitBuilder> {
return new FragmentExpression(frags, new FragmentVisualElement(And.DESCRIPTION, frags.size(), shapeFactory));
else if (op instanceof Operation.Or)
return new FragmentExpression(frags, new FragmentVisualElement(Or.DESCRIPTION, frags.size(), shapeFactory));
else if (op instanceof Operation.XOr)
return new FragmentExpression(frags, new FragmentVisualElement(XOr.DESCRIPTION, frags.size(), shapeFactory));
else
throw new BuilderException(Lang.get("err_builder_operationNotSupported", op.getClass().getSimpleName()));
} else if (expression instanceof Not) {
@ -121,6 +115,9 @@ public class CircuitBuilder implements BuilderInterface<CircuitBuilder> {
} else if (n.getExpression() instanceof Operation.Or) {
ArrayList<Fragment> frags = getOperationFragments((Operation) n.getExpression());
return new FragmentExpression(frags, new FragmentVisualElement(NOr.DESCRIPTION, frags.size(), shapeFactory));
} else if (n.getExpression() instanceof Operation.XOr) {
ArrayList<Fragment> frags = getOperationFragments((Operation) n.getExpression());
return new FragmentExpression(frags, new FragmentVisualElement(XNOr.DESCRIPTION, frags.size(), shapeFactory));
}
return new FragmentExpression(createFragment(n.getExpression()), new FragmentVisualElement(de.neemann.digital.core.basic.Not.DESCRIPTION, shapeFactory));
} else if (expression instanceof Variable) {
@ -288,33 +285,4 @@ public class CircuitBuilder implements BuilderInterface<CircuitBuilder> {
circuit.add(clock);
}
/**
* Only used for manual tests
*
* @param args args
* @throws BuilderException BuilderException
*/
public static void main(String[] args) throws BuilderException {
Variable y0 = new Variable("Y_0");
Variable y1 = new Variable("Y_1");
Variable y2 = new Variable("Y_2");
Variable z = new Variable("A");
Expression y0s = and(not(y0), z);
Expression y1s = or(and(y0, not(y1)), and(y1, not(y0)));
Expression y2s = not(y2);
Expression p0 = and(y0, y1, z);
Circuit circuit = new CircuitBuilder(new ShapeFactory(new ElementLibrary()))
.addSequential("Y_0", y0s)
.addSequential("Y_1", y1s)
.addSequential("Y_2", y2s)
.addCombinatorial("P_0", p0)
.createCircuit();
SwingUtilities.invokeLater(() -> new Main(null, circuit).setVisible(true));
}
}

View File

@ -3,8 +3,7 @@ package de.neemann.digital.analyse.expression;
import junit.framework.TestCase;
import static de.neemann.digital.analyse.expression.Not.not;
import static de.neemann.digital.analyse.expression.Operation.and;
import static de.neemann.digital.analyse.expression.Operation.or;
import static de.neemann.digital.analyse.expression.Operation.*;
import static de.neemann.digital.analyse.expression.Variable.v;
/**
@ -52,4 +51,19 @@ public class OperationTest extends TestCase {
i = and(not(a));
assertTrue(i instanceof Not);
}
public void testXOr() throws Exception {
Variable a = v("a");
Variable b = v("b");
Expression i = xor(a,b);
assertTrue(i instanceof Operation.XOr);
assertEquals(2, ((Operation.XOr) i).getExpressions().size());
assertEquals(false, ((Operation)i).calc(false,false));
assertEquals(true, ((Operation)i).calc(true,false));
assertEquals(true, ((Operation)i).calc(false,true));
assertEquals(false, ((Operation)i).calc(true,true));
}
}

View File

@ -14,7 +14,6 @@ public class ParserTest extends TestCase {
public void testIdent() throws Exception {
assertEquals(new Variable("C"), new Parser("C").parse());
assertEquals(new Variable("A_1"), new Parser("A_1").parse());
assertEquals(new Variable("A^1"), new Parser("A^1").parse());
}
public void testConst() throws Exception {
@ -29,6 +28,10 @@ public class ParserTest extends TestCase {
assertTrue(new Parser("a||b").parse() instanceof Operation.Or);
}
public void testParseXOr() throws Exception {
assertTrue(new Parser("a^b").parse() instanceof Operation.XOr);
}
public void testParseAnd() throws Exception {
assertTrue(new Parser("a*b").parse() instanceof Operation.And);
assertTrue(new Parser("a∧b").parse() instanceof Operation.And);
@ -51,10 +54,11 @@ public class ParserTest extends TestCase {
}
public void testParseNot() throws Exception {
Parser p = new Parser("!a");
Expression exp = p.parse();
Expression exp = new Parser("!a").parse();
assertTrue(exp instanceof Not);
assertTrue(((Not)exp).getExpression() instanceof Variable);
assertTrue(new Parser("~a").parse() instanceof Not);
assertTrue(new Parser("¬a").parse() instanceof Not);
}
public void testParseRegression() throws Exception {
@ -125,5 +129,4 @@ public class ParserTest extends TestCase {
}
}
}