Skip to content

Instantly share code, notes, and snippets.

@Tandrial
Last active October 7, 2015 19:31
Show Gist options
  • Save Tandrial/aa32106e06a1dde12da6 to your computer and use it in GitHub Desktop.
Save Tandrial/aa32106e06a1dde12da6 to your computer and use it in GitHub Desktop.
LogicEvaluator based on Dijkstra's 2 Stack Eval
import java.util.Scanner;
import java.util.Stack;
public class LogicEval {
public final static String operands = "!&| ";
public final static String numbers = "TF";
public final static String validToken = operands + numbers;
public static boolean eval(String expression) {
Stack<Character> values = new Stack<Character>();
Stack<Character> ops = new Stack<Character>();
char[] token = expression.toUpperCase().toCharArray();
for (int i = 0; i < token.length; i++) {
if (token[i] == ' ')
continue;
if (numbers.contains(String.valueOf(token[i]))) {
values.push(token[i]);
} else if (token[i] == '(') {
ops.push(token[i]);
} else if (token[i] == ')') {
while (ops.peek() != '(') {
if (ops.peek() == '!') {
values.push(applyOp(ops.pop(), values.pop()));
} else {
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
}
}
ops.pop();
} else if (token[i] == '!') {
ops.push(token[i]);
} else if (operands.contains(String.valueOf(token[i]))) {
if (!ops.empty() && ops.peek() == '!') {
values.push(applyOp(ops.pop(), values.pop()));
}
while (!ops.empty() && hatVorrang(token[i], ops.peek())) {
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
}
ops.push(token[i]);
}
}
while (!ops.empty()) {
if (ops.peek() == '!') {
values.push(applyOp(ops.pop(), values.pop()));
} else {
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
}
}
return values.pop() == 'T' ? true : false;
}
private static boolean hatVorrang(char op1, char op2) {
if (op2 == '(' || op2 == ')')
return false;
if (op2 == '!' && (op1 != '(' && op1 != ')'))
return false;
if ((op1 == '&') && (op2 == '|'))
return false;
return true;
}
private static Character applyOp(char op, char a) {
Character result = 'F';
switch (op) {
case '!':
if (a == 'F')
result = 'T';
break;
}
return result;
}
private static Character applyOp(char op, char b, char a) {
Character result = 'F';
switch (op) {
case '&':
if (a == 'T' && b == 'T')
result = 'T';
break;
case '|':
if (a == 'T' || b == 'T')
result = 'T';
break;
}
return result;
}
private static boolean errorCheck(String expression) {
int klammerCount = 0;
for (char c : expression.toCharArray()) {
if (c == '(')
klammerCount++;
else if (c == ')')
klammerCount--;
else if (!validToken.contains(String.valueOf(c))) {
System.out.println("Unbekanntes Symbol gefunden: " + c);
return false;
}
}
if (klammerCount != 0) {
System.out.println("Es fehlt eine Klammer");
return false;
}
return true;
}
public static void main(String[] args) {
Scanner s = new Scanner(System.in);
String eq;
System.out.println("Expression-Parser. exit beendet das Programm.");
while (true) {
System.out.print(": ");
eq = s.nextLine();
if (eq.equals("exit"))
break;
if (errorCheck(eq))
System.out.println(LogicEval.eval(eq));
}
s.close();
System.out.println("Ende");
}
}
import static org.junit.Assert.*;
import org.junit.Test;
public class LogicEvalTest {
@Test
public void testAtom() {
assertEquals(LogicEval.eval("T"), true);
assertEquals(LogicEval.eval("(T)"), true);
assertEquals(LogicEval.eval("((T))"), true);
assertEquals(LogicEval.eval("F"), false);
assertEquals(LogicEval.eval("(F)"), false);
assertEquals(LogicEval.eval("((F))"), false);
}
@Test
public void testOr() {
assertEquals(LogicEval.eval("T|T"), true);
assertEquals(LogicEval.eval("T|F"), true);
assertEquals(LogicEval.eval("F|T"), true);
assertEquals(LogicEval.eval("F|F"), false);
assertEquals(LogicEval.eval("(T|T)"), true);
assertEquals(LogicEval.eval("(T)|F"), true);
assertEquals(LogicEval.eval("F|(T)"), true);
assertEquals(LogicEval.eval("(F)|(F)"), false);
}
@Test
public void testAnd() {
assertEquals(LogicEval.eval("T&T"), true);
assertEquals(LogicEval.eval("T&F"), false);
assertEquals(LogicEval.eval("F&T"), false);
assertEquals(LogicEval.eval("F&F"), false);
assertEquals(LogicEval.eval("(T&T)"), true);
assertEquals(LogicEval.eval("(T)&F"), false);
assertEquals(LogicEval.eval("F&(T)"), false);
assertEquals(LogicEval.eval("(F)&(F)"), false);
}
@Test
public void testNot() {
assertEquals(LogicEval.eval("!T"), false);
assertEquals(LogicEval.eval("!(T)"), false);
assertEquals(LogicEval.eval("!F"), true);
assertEquals(LogicEval.eval("!(F)"), true);
}
@Test
public void testComplex() {
assertEquals(LogicEval.eval("T&!T|!F"), true);
assertEquals(LogicEval.eval("T&!(T|!F)"), false);
assertEquals(LogicEval.eval("(T&!T)|!F"), true);
assertEquals(LogicEval.eval("!(T & (F | T | F) | T)"), false);
assertEquals(LogicEval.eval("!T & F | T | F | T"), true);
assertEquals(LogicEval.eval("!(T&!F)"), false);
assertEquals(LogicEval.eval("!(T&!T|!(F))"), false);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment