控制字符串是否为数学表达式
Control if a String is a mathematical expression
我正在寻找一种方法来检查字符串是否是数学表达式,例如
x + y -sin(1) * 99k
我不想计算表达式,但要了解字符串是否以正确的方式编写。
有一些 Java 库可以做到这一点吗?
更新:
对不起,这不是一个方程式,而只是一个表达式(没有'=')。
我考虑了一个可能的解决方案:
- 指定使用的变量
- 用'1'替换所有变量
- 用 JEval 评估新字符串
- 如果程序抛出一个Exception,表达式是错误的
你怎么看?
谢谢
尝试ANTLR。你可以写这样的语法:
grammar Expr;
expr: FuncitonName '(' expr ')'
| '-' expr
| '(' expr ')'
| expr '*' expr
| expr '+' expr
| expr '-' expr
| expr '/' expr
| Const
| Variable
;
FuncitonName : [a-z] + ;
Variable : [a-zA-Z] + ;
Const : [0-9] +;
WS : [ \t\r\n\u000C]+ -> skip;
您应该根据允许的表达式和不允许的表达式来更正确地定义语法。将其保存在文件 Expr.g4
中并执行 antlr4 Expr.g4
以获取您的 ExprLexer.java
和 ExprParser.java
文件。然后你可以用它们来检查一个句子是否是一个算术表达式:
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.BailErrorStrategy;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.misc.ParseCancellationException;
public static boolean isExpr(String exp) {
ExprLexer lexer = new ExprLexer(new ANTLRInputStream(exp));
CommonTokenStream tokens = new CommonTokenStream(lexer);
ExprParser parser = new ExprParser(tokens);
parser.removeErrorListeners();
parser.setErrorHandler(new BailErrorStrategy());
try {
parser.expr();
return true;
} catch (ParseCancellationException e) {
return false;
}
}
最后测试:
System.out.println(isExpr("x + y -sin(1) * 99 * k")); //true
System.out.println(isExpr("x + y +")); //false
你可以参考this问题
我的临时(和部分)解决方案。所有解决方案都是重量级的,但 Nashorn 是内置的。 (要清楚:我也使用 ANTLR)
原始示例中的 sin()
函数有问题,抛出 javax.script.ScriptException: ReferenceError: "sin" is not defined in <eval>
ScriptEngineManager scm = new ScriptEngineManager();
ScriptEngine eng = scm.getEngineByName("nashorn");
Integer k = 1;
Integer x = 2;
Integer y = 3;
eng.put("k", k);
eng.put("x", k);
eng.put("y", k);
Object ret = null;
try {
ret = eng.eval("x + y * 99 * k");
} catch (ScriptException e) {
e.printStackTrace();
}
我个人使用 Groovy。原始 Groovy eval 有同样的问题 groovy.lang.MissingMethodException: No signature of method: sin() is applicable ...
如果我更好地意识到这一点,我将捕获未知 属性 和未知方法....我不知道,如何在 nashorn 或 JEval[=14 中捕获未知元素(但语法正确) =]
我正在寻找一种方法来检查字符串是否是数学表达式,例如
x + y -sin(1) * 99k
我不想计算表达式,但要了解字符串是否以正确的方式编写。
有一些 Java 库可以做到这一点吗?
更新: 对不起,这不是一个方程式,而只是一个表达式(没有'=')。 我考虑了一个可能的解决方案:
- 指定使用的变量
- 用'1'替换所有变量
- 用 JEval 评估新字符串
- 如果程序抛出一个Exception,表达式是错误的
你怎么看?
谢谢
尝试ANTLR。你可以写这样的语法:
grammar Expr;
expr: FuncitonName '(' expr ')'
| '-' expr
| '(' expr ')'
| expr '*' expr
| expr '+' expr
| expr '-' expr
| expr '/' expr
| Const
| Variable
;
FuncitonName : [a-z] + ;
Variable : [a-zA-Z] + ;
Const : [0-9] +;
WS : [ \t\r\n\u000C]+ -> skip;
您应该根据允许的表达式和不允许的表达式来更正确地定义语法。将其保存在文件 Expr.g4
中并执行 antlr4 Expr.g4
以获取您的 ExprLexer.java
和 ExprParser.java
文件。然后你可以用它们来检查一个句子是否是一个算术表达式:
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.BailErrorStrategy;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.misc.ParseCancellationException;
public static boolean isExpr(String exp) {
ExprLexer lexer = new ExprLexer(new ANTLRInputStream(exp));
CommonTokenStream tokens = new CommonTokenStream(lexer);
ExprParser parser = new ExprParser(tokens);
parser.removeErrorListeners();
parser.setErrorHandler(new BailErrorStrategy());
try {
parser.expr();
return true;
} catch (ParseCancellationException e) {
return false;
}
}
最后测试:
System.out.println(isExpr("x + y -sin(1) * 99 * k")); //true
System.out.println(isExpr("x + y +")); //false
你可以参考this问题
我的临时(和部分)解决方案。所有解决方案都是重量级的,但 Nashorn 是内置的。 (要清楚:我也使用 ANTLR)
原始示例中的 sin()
函数有问题,抛出 javax.script.ScriptException: ReferenceError: "sin" is not defined in <eval>
ScriptEngineManager scm = new ScriptEngineManager();
ScriptEngine eng = scm.getEngineByName("nashorn");
Integer k = 1;
Integer x = 2;
Integer y = 3;
eng.put("k", k);
eng.put("x", k);
eng.put("y", k);
Object ret = null;
try {
ret = eng.eval("x + y * 99 * k");
} catch (ScriptException e) {
e.printStackTrace();
}
我个人使用 Groovy。原始 Groovy eval 有同样的问题 groovy.lang.MissingMethodException: No signature of method: sin() is applicable ...
如果我更好地意识到这一点,我将捕获未知 属性 和未知方法....我不知道,如何在 nashorn 或 JEval[=14 中捕获未知元素(但语法正确) =]