我正在寻找一个Java库,该库可以将数学公式解析为AST(抽象语法树)。 / libraries from Java。例如,可以使用Rhino引擎嵌入JavaScript。

基本要求:


解析公式的能力前缀符号。
保留未知变量的能力-我不是在寻找计算器。
可自定义的运算符和函数列表。在功能上(例如sin(x))。一个免费的图书馆就足够了。


评论

注意:尽管我同时发现了一个或多或少合适的JavaScript库,但仍然欢迎更好的替代方法(最好是Java)!

#1 楼

Math.js

JavaScript部分


“ 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 楼

Java

Symja将数学表达式转换为以下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在