auto-sync
This commit is contained in:
parent
2c2f710580
commit
fffd151b67
|
@ -19,11 +19,9 @@
|
||||||
|
|
||||||
package com.autsia.bracer;
|
package com.autsia.bracer;
|
||||||
|
|
||||||
import java.text.NumberFormat;
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
import java.util.StringTokenizer;
|
import java.util.StringTokenizer;
|
||||||
|
|
||||||
|
@ -35,16 +33,10 @@ import java.util.StringTokenizer;
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
public class BracerParser {
|
public class BracerParser {
|
||||||
/* list of available functions */
|
|
||||||
private final String[] FUNCTIONS = {"abs", "acos", "arg", "asin", "atan",
|
|
||||||
"conj", "cos", "cosh", "exp", "imag", "log", "neg", "pow", "real",
|
|
||||||
"sin", "time_since_boot", "sqrt", "tan", "rpm", "not"};
|
|
||||||
/* list of available operators */
|
/* list of available operators */
|
||||||
private final String OPERATORS = "<>=+-*/&|!";
|
private final String OPERATORS = "<>=+-*/&|!";
|
||||||
/* separator of arguments */
|
/* separator of arguments */
|
||||||
private final String SEPARATOR = ",";
|
private final String SEPARATOR = ",";
|
||||||
/* variable token */
|
|
||||||
private final String VARIABLE = "var";
|
|
||||||
/* temporary stack that holds operators, functions and brackets */
|
/* temporary stack that holds operators, functions and brackets */
|
||||||
private Stack<String> stackOperations = new Stack<>();
|
private Stack<String> stackOperations = new Stack<>();
|
||||||
/* stack for holding expression converted to reversed polish notation */
|
/* stack for holding expression converted to reversed polish notation */
|
||||||
|
@ -88,9 +80,21 @@ public class BracerParser {
|
||||||
StringTokenizer stringTokenizer = new StringTokenizer(expression,
|
StringTokenizer stringTokenizer = new StringTokenizer(expression,
|
||||||
OPERATORS + SEPARATOR + "()", true);
|
OPERATORS + SEPARATOR + "()", true);
|
||||||
|
|
||||||
|
String pendingToken = null;
|
||||||
|
|
||||||
/* loop for handling each token - shunting-yard algorithm */
|
/* loop for handling each token - shunting-yard algorithm */
|
||||||
while (stringTokenizer.hasMoreTokens()) {
|
while (pendingToken != null || stringTokenizer.hasMoreTokens()) {
|
||||||
String token = stringTokenizer.nextToken();
|
String token;
|
||||||
|
if (pendingToken != null) {
|
||||||
|
token = pendingToken;
|
||||||
|
pendingToken = null;
|
||||||
|
} else {
|
||||||
|
token = stringTokenizer.nextToken();
|
||||||
|
}
|
||||||
|
if (stringTokenizer.hasMoreTokens()) {
|
||||||
|
pendingToken = stringTokenizer.nextToken();
|
||||||
|
}
|
||||||
|
|
||||||
if (isSeparator(token)) {
|
if (isSeparator(token)) {
|
||||||
while (!stackOperations.empty()
|
while (!stackOperations.empty()
|
||||||
&& !isOpenBracket(stackOperations.lastElement())) {
|
&& !isOpenBracket(stackOperations.lastElement())) {
|
||||||
|
@ -111,6 +115,12 @@ public class BracerParser {
|
||||||
} else if (isNumber(token)) {
|
} else if (isNumber(token)) {
|
||||||
stackRPN.push(token);
|
stackRPN.push(token);
|
||||||
} else if (isOperator(token)) {
|
} else if (isOperator(token)) {
|
||||||
|
|
||||||
|
if ((token.equals("<") || token.equals(">")) && "=".equals(pendingToken)) {
|
||||||
|
token = token + pendingToken;
|
||||||
|
pendingToken = null;
|
||||||
|
}
|
||||||
|
|
||||||
while (!stackOperations.empty()
|
while (!stackOperations.empty()
|
||||||
&& isOperator(stackOperations.lastElement())
|
&& isOperator(stackOperations.lastElement())
|
||||||
&& getPrecedence(token) <= getPrecedence(stackOperations
|
&& getPrecedence(token) <= getPrecedence(stackOperations
|
||||||
|
@ -141,22 +151,6 @@ public class BracerParser {
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
public String evaluate() throws ParseException {
|
public String evaluate() throws ParseException {
|
||||||
if (!stackRPN.contains("var")) {
|
|
||||||
return evaluate(0);
|
|
||||||
}
|
|
||||||
throw new ParseException("Unrecognized token: var", 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Evaluates once parsed math expression with "var" variable included
|
|
||||||
*
|
|
||||||
* @param variableValue User-specified <code>Double</code> value
|
|
||||||
* @return <code>String</code> representation of the result
|
|
||||||
* @throws <code>ParseException</code> if the input expression is not
|
|
||||||
* correct
|
|
||||||
* @since 3.0
|
|
||||||
*/
|
|
||||||
public String evaluate(double variableValue) throws ParseException {
|
|
||||||
/* check if is there something to evaluate */
|
/* check if is there something to evaluate */
|
||||||
if (stackRPN.empty()) {
|
if (stackRPN.empty()) {
|
||||||
return "";
|
return "";
|
||||||
|
@ -169,10 +163,6 @@ public class BracerParser {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
Stack<String> stackRPN = (Stack<String>) this.stackRPN.clone();
|
Stack<String> stackRPN = (Stack<String>) this.stackRPN.clone();
|
||||||
|
|
||||||
/* enroll the variable value into expression */
|
|
||||||
Collections.replaceAll(stackRPN, VARIABLE,
|
|
||||||
Double.toString(variableValue));
|
|
||||||
|
|
||||||
/* evaluating the RPN expression */
|
/* evaluating the RPN expression */
|
||||||
while (!stackRPN.empty()) {
|
while (!stackRPN.empty()) {
|
||||||
String token = stackRPN.pop();
|
String token = stackRPN.pop();
|
||||||
|
@ -293,8 +283,8 @@ public class BracerParser {
|
||||||
private boolean isNumber(String token) {
|
private boolean isNumber(String token) {
|
||||||
try {
|
try {
|
||||||
Double.parseDouble(token);
|
Double.parseDouble(token);
|
||||||
} catch (Exception e) {
|
} catch (NumberFormatException e) {
|
||||||
return token.equals(VARIABLE);
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -307,12 +297,7 @@ public class BracerParser {
|
||||||
* @since 1.0
|
* @since 1.0
|
||||||
*/
|
*/
|
||||||
private boolean isFunction(String token) {
|
private boolean isFunction(String token) {
|
||||||
for (String item : FUNCTIONS) {
|
return Character.isAlphabetic(token.charAt(0));
|
||||||
if (item.equals(token)) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -33,7 +33,6 @@ import com.autsia.bracer.BracerParser;
|
||||||
*/
|
*/
|
||||||
public class BracerParserTest {
|
public class BracerParserTest {
|
||||||
private final String INPUT_NOVAR = "-sin(3+4+cos(6)/exp(10/pow(22,-1)))";
|
private final String INPUT_NOVAR = "-sin(3+4+cos(6)/exp(10/pow(22,-1)))";
|
||||||
private final String INPUT_VAR = "-sin(3+var+cos(10)/exp(10/pow(22,-1)))";
|
|
||||||
private BracerParser bracerParser;
|
private BracerParser bracerParser;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
|
@ -47,12 +46,6 @@ public class BracerParserTest {
|
||||||
Assert.assertEquals("-0.6570194619480038", bracerParser.evaluate());
|
Assert.assertEquals("-0.6570194619480038", bracerParser.evaluate());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
|
||||||
public void testEvaluateVar() throws Exception {
|
|
||||||
bracerParser.parse(INPUT_VAR);
|
|
||||||
Assert.assertEquals("-0.6569578792490918", bracerParser.evaluate(4));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSimpleBoolean() throws Exception {
|
public void testSimpleBoolean() throws Exception {
|
||||||
bracerParser.parse("true or false");
|
bracerParser.parse("true or false");
|
||||||
|
@ -78,10 +71,18 @@ public class BracerParserTest {
|
||||||
@Test
|
@Test
|
||||||
public void testRusEfi() throws ParseException {
|
public void testRusEfi() throws ParseException {
|
||||||
bracerParser.parse("(time_since_boot < 4) | (rpm > 0)");
|
bracerParser.parse("(time_since_boot < 4) | (rpm > 0)");
|
||||||
Collection<String> stackRPN = bracerParser.getStackRPN();
|
|
||||||
|
|
||||||
Assert.assertEquals("[|, rpm, >, 0, time_since_boot, <, 4]", stackRPN.toString());
|
Assert.assertEquals("[|, rpm, >, 0, time_since_boot, <, 4]", bracerParser.getStackRPN().toString());
|
||||||
|
|
||||||
|
|
||||||
|
bracerParser.parse("(time_since_boot <= 4) | (rpm > 0)");
|
||||||
|
Assert.assertEquals("[|, rpm, >, 0, time_since_boot, <=, 4]", bracerParser.getStackRPN().toString());
|
||||||
|
|
||||||
|
bracerParser.parse("(time_since_boot <= 4) | (rpm > 0)");
|
||||||
|
Assert.assertEquals("[|, rpm, >, 0, time_since_boot, <=, 4]", bracerParser.getStackRPN().toString());
|
||||||
|
|
||||||
|
bracerParser.parse("(time_since_boot <= 4) OR (rpm > 0)");
|
||||||
|
Assert.assertEquals("[OR, rpm, >, 0, time_since_boot, <=, 4]", bracerParser.getStackRPN().toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
Loading…
Reference in New Issue