基本要求:
解析公式的能力前缀符号。
保留未知变量的能力-我不是在寻找计算器。
可自定义的运算符和函数列表。在功能上(例如
sin(x)
)。一个免费的图书馆就足够了。#1 楼
Math.jsJavaScript部分
“ Math.js是JavaScript和Node.js的扩展数学库。”
—项目自述文件
它提供了parse()函数。
使用NodeJS环境的示例:
var math = require('mathjs')();
var ast = math.parse('xy^(1/2)');
// Fully log the object
var util = require('util');
console.log(util.inspect(ast, {showHidden: false, depth: null}));
输出:
{ op: '^',
fn: 'pow',
params:
[ { name: 'xy' },
{ op: '/',
fn: 'divide',
params:
[ { valueType: 'number', value: '1' },
{ valueType: 'number', value: '2' } ] } ] }
Java部分
我使用Java Nashorn VM(仅在Java> = 8中可用)来执行JavaScript。
程序体系结构:
User ---------------> Java
inputs formla |----> Nashorn ----> math.js
|<---------------------|
User <-----------------|
使用Nashorn引擎非常简单(省略了异常处理)
ScriptEngine engine = new ScriptEngineManager().getEngineByName("nashorn");
engine.eval(readerInstancePointingToMathJsLibrary);
engine.eval(readerInstancePointingToBridgeJavaScript);
网桥的JavaScript代码在很大程度上取决于AST节点的实现。我们利用Nashorn在JavaScript中创建Java对象并将其传输到Java的能力。示例:
var math = mathjs();
function convert(formula) {
var ast = math.parse(formula);
var javaAst = /* build your AST with Java objects */
return javaAst;
}
我们现在可以从Java访问该函数甚至传递任意参数:
Invocable inv = (Invocable) engine;
// Expression is my AST node type in Java
expr = (Expression) inv.invokeFunction("convert", formulaFromUser);
注意:我需要一种快速解析数学表达式的方法。解析器(手写的或由解析器生成器生成的)始终是首选。尽管如此,上面的代码显示了如何轻松集成Java Nashorn。
#2 楼
JavaScript几个月前,我使用Esprima解析了此类输入。实际上,Esprima会解析所有JavaScript输入(将其转换为树),因此它应适用于此类数学表达式。 br />
...其中
input
是包含应分析的输入的字符串(如果无效,则将引发错误)。示例
esprima.parse(input);
返回以下对象:
esprima.parse("1+2*3")
我修改了Esprima代码并将其用于实验中项目,以在JavaScript中定义自定义运算符。该应用程序在GitHub上是开源的:http://ionicabizau.net/JavaScript-custom-operators/
评论
Esprima似乎比我实际需要的功能强大得多,并且能够解析功能。不过+1和您的运算符非常有趣。
– ComFreek
14年6月20日在20:14
#3 楼
Java似乎JEP是数学表达式解析器。
JEP是用于解析和评估数学表达式的Java API。使用此库,您可以允许用户输入任意公式作为字符串,并立即对其进行评估。 JEP支持用户定义的变量,常量和函数。包括许多常见的数学函数和常量。
功能
易于使用的软件包,用于解析数学表达式
体积小(jar存档仅56kb) >支持布尔表达式(!,&&,||,<,>,!=,==,> =和<=)
快速求值(可以为不同的变量值快速求值)
包括常见的数学函数
可通过用户定义的函数扩展
预定义的常量,例如“ pi”和“ e”
支持字符串,复数和向量
支持隐式乘法(允许使用“ 3x”而不是“ 3 * x”之类的表达式)
允许在已声明和未声明的变量之间进行选择
与Java 1.1兼容(已通过Sun Java JDK 1.1.8和Microsoft Java VM测试)
支持Unicode字符(包括希腊符号)
包括从中生成主要类的JavaCC语法
它在SourceForge上是开源的。
也,有一个SO问题有关此主题的信息:https://stackoverflow.com/q/4589951/1420197
评论
最初的项目似乎已终止。 SourceForge项目页面链接到一个新的外部站点,该站点提供Jep Java作为商业产品(二进制文件550美元,源代码950美元)。
– ComFreek
2014年6月24日14:26
@ComFreek你是对的。无论如何,我认为最初的项目应该满足您的需求。谢谢您的悬赏! :-)
–IonicăBizău
2014年6月24日14:29在
#4 楼
构建公式解析器/树构建器是一个非常简单的练习。您可以寻找一个库,但是您总是会最终对其进行修改以产生所需的库。取而代之的是,简单地编写所需的代码可能会更容易。它还提供了对第二个链接的访问,该链接显示了如何轻松地将此类解析器转换为可生成AST的解析器。标量值和变量名。您几乎可以用任何语言(包括Java)编写这类解析器的代码。一种解析器来执行此操作,但在这种情况下,通常更容易切换到解析器生成器。
#5 楼
JavaSymja将数学表达式转换为以下Symja AST。
#6 楼
我已经使用javassist将Java表达式转换为字节码(如果要评估表达式,这可能是您最终要寻找的东西)。它甚至可以重新定义现有功能。http://www.csg.ci.i.u-tokyo.ac.jp/~chiba/javassist/
评论
如果我误解了您,请原谅我,但是Javassist如何让我将用户输入(字符串)解析为树结构(Java对象)?
– ComFreek
2014年6月24日14:17
可能不会。它允许您将表达式编译为Java方法,然后可以直接调用以对其求值。这是因为我期望这是您的最终目标。如果这是编写编译器的一部分,则应该手动进行:)
–索比昂·拉文·安德森(ThorbjørnRavn Andersen)
2014年6月24日14:40在
评论
注意:尽管我同时发现了一个或多或少合适的JavaScript库,但仍然欢迎更好的替代方法(最好是Java)!