JavaScript的解析器用于简单表达式。

7
我想找一个可以处理和评估简单表达式的JavaScript解析器。该解析器应该能够评估常规的数学表达式,并支持带参数的自定义函数。它还必须支持字符串处理。偏爱具有||运算符支持的字符串连接,但如果使用+也可以的话,那就没问题。
以下是解析器应该处理的表达式示例:
3 * (2 + 1) - 1
2 * func(2, 2)
func('hello world', 0, 5) || ' you'
是否有人实现了这样的东西或者我在哪里可以找到类似的东西?

你是否正在寻找在不同语言中运行的JavaScript解析器?比如JavaScript解析器的C++实现?还是想要使用JavaScript编写JavaScript解析器? - Jonathan Fingland
抱歉如果我没有表达清楚。不,我的意思是用JavaScript编写一个解析器,解析和评估如上所述的简单表达式。 - AAA
这组“自定义”函数已知吗? - Jonathan Fingland
没错。这个想法是你首先在解析类中注册自己的函数及其名称,然后就可以在表达式中使用它们了。 - AAA
7个回答

9
我有一个修改版的ActionScript解析器(用AS编写,不解析AS),支持自定义函数,但不支持字符串。不过添加字符串支持可能很容易。我会上传到某个地方,这样你就可以在http://silentmatt.com/parser3.js获取它。 编辑:我很容易地添加了基本字符串支持。它不支持转义序列和toJSFunction无法工作,但只需要几分钟就可以使它工作。将连接运算符更改为“||”也应该很容易。
以下是如何评估示例表达式的方法:
js> var parser = new Parser();
js> parser.parse("3 * (2 + 1) - 1").evaluate();
8
js> parser.parse("2 * func(2; 2)").evaluate({ func:Math.pow });
8
js> function substr(s, start, end) { return s.substring(start, end); }
js> parser.parse("func('hello world'; 0; 5) + ' you'").evaluate({ func:substr });
hello you

我不记得为什么我使用分号作为参数分隔符;我想这与区分函数和内置的“运算符”函数有关。
另一个编辑: 我已经尝试过一下,现在有一个更好支持字符串的版本,在http://silentmatt.com/parser3.js(toJSFunction 可用,并且您可以使用标准的 JavaScript 转义序列)。它还使用逗号来分隔所有函数的参数,而字符串连接运算符是 || 而不是 +,后者只执行加法。

谢谢你,我非常感激你的帮助。这个符合我所描述的,并且也很容易修改和扩展。这就是我一直在寻找的。我真的很感激。 - AAA
另一个注释……马修,我忘了说你很棒!我真的很感激第三个版本中的修改,伙计。继续保持好工作。一切顺利。 - AAA
没问题。我一直想玩这个(我已经好几个月没碰它了)。很多功劳要归功于Raphael Graf,他写了最初的版本。 - Matthew Crumley
这个解析器真的很棒。你能指定它发布的许可证吗?我找不到它所基于的原始解析器的参考资料。 - Ryan Hoffman
@RyanHoffman 嗯,显然原始的 ActionScript 版本已经不在网上了。他的代码只有一条注释,说需要给作者信用。我不在意别人如何使用它,只需保留顶部的注释。 - Matthew Crumley

4

试用math.js:

http://mathjs.org

math.js自带一个广泛而易于使用的解析器,还支持像您的示例表达式中一样分配和使用变量和函数。与“本地”JavaScript无缝集成:您可以从解析器作用域获取并设置变量和函数。

您的示例代码将被评估为:

var parser = math.parser();
parser.set('func', function () {
    // ... do something ...
});
parser.evaluate('3 * (2 + 1) - 1');
parser.evaluate('2 * func(2, 2)');
parser.evaluate('func("hello world", 0, 5) + " you"');

在解析器本身中也可以定义函数(目前仅支持单行函数):

parser.evaluate('function f(x, y) = x ^ y');
parser.evaluate('f(2, 3)'); // 8

3
我没有使用过它,但是快速谷歌搜索可以找到 http://jsfromhell.com/classes/math-parser
编辑:
你想做的可能超出了第一个链接的范畴,你还可以看一下道格拉斯·克罗克福德的“简化JavaScript的解析器”
这只是一个解析器,所以您需要自己进行所有评估。然而,它会使事情变得更容易,并且不使用eval。

谢谢。这个听起来很有前途,也是最接近我的要求的,但它缺少字符串支持。而且修改它以支持字符串是困难的,因为它不依赖于递归方法,而是采用了一种优化(但不错)的解析方式。有人能帮忙修改以支持字符串吗? - AAA

2
假设您需要在 JavaScript 中使用 JavaScript 解析器,那么您可能需要使用 eval() 函数。
请参见:https://developer.mozilla.org/En/Core_JavaScript_1.5_Reference/Global_Functions/Eval
请注意,如果不正确使用 eval 函数,可能会存在安全风险。

不,eval对我来说不是选择。正如你所说,它会引入安全风险,在我的情况下,风险真的很高。我想要一个自定义且受限的解析器来执行上述操作。但是谢谢。 - AAA

0

请参考此教程以了解如何构建任意解析器/编译器。 (基本上它自动化了从语法中构建递归下降解析器的过程,这意味着您可以轻松更改表达式语法)。 整个教程都是用JavaScript完成的,因此它直接适用于您。

http://www.bayfronttechnologies.com/mc_tutorial.html


0

0

试试js-expression-eval

这是一个基于JavaScript的字符串表达式评估库。

该库可以评估字符串表达式并返回结果。它支持基本的算术运算,同时也支持自定义变量和函数。

示例:

const parser = new ExpressionParser('A.B + A.C' ,
 { 
    A: (identifier) => {
    switch (identifier) {
        case 'B':
            return 2;
        case 'C':
            return 3;
        }
    }
});
const result = parser.evaluate();
console.log(result); // 5

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接