Java的Javascript解析器[关闭]

Posted

技术标签:

【中文标题】Java的Javascript解析器[关闭]【英文标题】:Javascript parser for Java [closed] 【发布时间】:2011-09-24 14:09:03 【问题描述】:

谁能推荐一个不错的 Java javascript 解析器?我相信可以使用 Rhino,但是仅仅进行解析似乎有点过头了,或者它是唯一合适的解决方案吗?任何建议将不胜感激。谢谢。

【问题讨论】:

您想解析但不评估 javascript? 你的最终目标是什么?验证脚本?从脚本创建抽象语法树?还有什么? @Bart kybrex 想要 :) 我经常不知道我的目标,直到它完成 :P @jball & @Bart,我需要解析它,也许还需要修改它的内容。 这是我最喜欢的有用问题之一,已结束。 +1 【参考方案1】:

来自https://github.com/google/caja/blob/master/src/com/google/caja/parser/js/Parser.java

下面的文法是 this 文法的上下文无关表示 解析器解析。它与 EcmaScript 262 Edition 3 (ES3) 不一致,其中 实现不同意 ES3。分号插入规则和 正确处理所需的表达式中可能的回溯 回溯在代码中被彻底注释,因为分号插入 需要来自词法分析器和解析器的信息,并且无法确定 有限前瞻。

值得注意的功能

    在错误不会阻止任何进一步错误的队列上报告警告,以便我们可以在一次编译过程中报告多个错误,而不是强迫开发人员玩whack-a-mole。 不解析 Firefox 风格的 catch (<Identifier> if <Expression>),因为它们不适用于 IE 和许多其他解释器。 识别 const,因为许多解释器(不是 IE)都这样做,但会发出警告。 在ArrayObject 构造函数中允许使用尾随逗号,但会发出警告。 允许关键字作为标识符名称,但会发出警告,因为不同的解释器有不同的关键字集。这使我们可以使用扩展的关键字集。

要解析严格的代码,传入一个PedanticWarningMessageQueueMessageLevel#WARNING 及更高版本转换为MessageLevel#FATAL_ERROR


CajaTestCase.js 展示了如何设置解析器,同一个类中的 [fromResource] 和 [fromString] 展示了如何获取正确类型的输入。

【讨论】:

您能否提供或链接到有关如何以这种方式使用它的示例? @Doug,请查看我的编辑。【参考方案2】:

使用 Java V1.8 时,您可以使用一个技巧来解析现成的 Nashorn 实现。通过查看 OpenSDK 源代码中的单元测试,您可以了解如何仅使用解析器,而无需进行所有额外的编译等...

Options options = new Options("nashorn");
options.set("anon.functions", true);
options.set("parse.only", true);
options.set("scripting", true);

ErrorManager errors = new ErrorManager();
Context context = new Context(options, errors, Thread.currentThread().getContextClassLoader());
Source source   = new Source("test", "var a = 10; var b = a + 1;" +
            "function someFunction()  return b + 1;   ");
Parser parser = new Parser(context.getEnv(), source, errors);
FunctionNode functionNode = parser.parse();
Block block = functionNode.getBody();
List<Statement> statements = block.getStatements();

此代码运行后,您将拥有“语句”列表中 3 个表达式的抽象语法树 (AST)。

然后可以根据您的需要对其进行解释或操作。

前面的示例适用于以下导入:

import jdk.nashorn.internal.ir.Block;
import jdk.nashorn.internal.ir.FunctionNode;
import jdk.nashorn.internal.ir.Statement;
import jdk.nashorn.internal.parser.Parser;
import jdk.nashorn.internal.runtime.Context;
import jdk.nashorn.internal.runtime.ErrorManager;
import jdk.nashorn.internal.runtime.Source;
import jdk.nashorn.internal.runtime.options.Options;

您可能需要添加访问规则以使 jdk/nashorn/internal/** 可访问。


在我的上下文中,我使用 Java 脚本作为我自己的领域特定语言 (DSL) 的表达式语言,然后我将在运行时将其编译为 Java 类并使用。 AST 让我可以生成适当的 Java 代码来捕捉 Java Script 表达式的意图。


Nashorn 在 Java SE 8 中可用。

获取 Nashorn 源代码的信息链接在这里: https://wiki.openjdk.java.net/display/Nashorn/Building+Nashorn

【讨论】:

Source 构造函数具有私有访问权限。您应该使用静态方法,例如: Source.sourceFor() 感谢您的评论。私有访问构造函数是在 Java 8u_31 和 Java 8u_45 之间进行的更改。较新的代码应该使用它。我还看到他们正计划在 JDK 9(左右)中正式发布这个库。 @LukeMachowski:我很想知道您如何处理静态代码分析?喜欢防止无限循环等...? @Copernic:我不知道。对于我的用例,我依赖 Garbage In-Garbage Out。如果规则写得不好,那么编译的结果就会很差。也许其他人有一些想法。 Nashorn源改为hg.openjdk.java.net/jdk8/jdk8/nashorn【参考方案3】:

先前的答案描述了一种在 JDK 8 的掩护下解析 javascript 的方法。他们现在在 Java 9 中将其作为主线。太好了!

这意味着您不需要包含任何库,而是我们可以依赖 java 人员的官方实现。以编程方式解析 javascript 更容易实现,而无需进入 java 代码的禁忌领域。

应用程序可能是您希望将 javascript 用于规则引擎的地方,该规则引擎在运行时被解析并编译成其他语言。 AST 让您“理解”用简洁的 javascript 语言编写的逻辑,然后在其他语言或框架中生成不太漂亮的逻辑来执行或评估。

http://openjdk.java.net/jeps/236

以上链接的总结:

为 Nashorn 的 ECMAScript 抽象语法树定义支持的 API。

目标

提供接口类来表示 Nashorn 语法树节点。 提供工厂以创建已配置的解析器实例,并通过 API 传递 Nashorn 命令行选项来完成配置。 提供访问者模式 API 以访问 AST 节点。 提供示例/测试程序以使用 API。

非目标

AST 节点将尽可能表示 ECMAScript 规范中的概念,但它们不会完全相同。 ECMAScript 将尽可能采用 javac 树 API 的接口。 不会使用外部解析器/树标准或 API。 不会有脚本级解析器 API。这是一个 Java API,尽管脚本可以调用 Java 并因此使用该 API。

【讨论】:

【参考方案4】:

这里有两个用于 EcmaScript 的 ANTLR 或多或少有效或完整(参见本文中的 cmets)语法:

http://www.antlr.org/grammar/1206736738015/JavaScript.g(不完整?) http://www.antlr.org/grammar/1153976512034/ecmascriptA3.g(越野车?)

来自ANTLR 5 minute intro:

ANTLR 读取称为语法的语言描述文件并生成许多源代码文件和其他辅助文件。 ANTLR 的大多数用途都会生成以下工具中的至少一个(通常同时生成两者):

Lexer:它读取输入字符或字节流(即字符、二进制数据等),使用您指定的模式将其划分为标记,并生成标记流作为输出。它还可以使用 ANTLR 解析器自动理解和尊重的协议将一些标记(例如空格和 cmets)标记为隐藏。

解析器:它读取标记流(通常由词法分析器生成),并通过您指定的规则(模式)匹配您的语言中的短语,并且通常对匹配的每个短语(或子短语)执行一些语义操作.每个匹配项都可以调用自定义操作,通过 StringTemplate 编写一些文本,或生成抽象语法树以进行额外处理。

【讨论】:

那个语法充满了错误,尝试从中生成词法分析器:你不会成功。 由于正则表达式语法的歧义,自动构建的 JavaScript 解析器很难做到。 @miku,是的,first one 正确生成了词法分析器和解析器,但我没有看到正则表达式文字,/ ... / 在其中任何地方定义... :) 第一个不支持正则表达式文字或分号插入正确(在输入结束或大括号或包含行终止符的/*...*/ 注释之前)。第二个也不支持分号插入。 自动分号插入很难,因为从本质上讲,只有在不这样做会导致语法错误的情况下才必须这样做:- 对于 Javascript,不插入分号意味着解析器实际上是无用的。 【参考方案5】:

用于 java https://github.com/DigiArea/es5-model 的 EcmaScript 5 解析器

【讨论】:

【参考方案6】:

对我来说,最好的解决方案是在 rhino 下使用 acorn - https://github.com/marijnh/acorn。

我只是认为 caja 不再受到关注。

【讨论】:

在我看来,这并不能回答问题。 OP 要求编写(或至少在 Java 中使用)JavaScript 解析器。 Acorn 旨在用于 JavaScript。

以上是关于Java的Javascript解析器[关闭]的主要内容,如果未能解决你的问题,请参考以下文章

Python中的JavaScript解析器[关闭]

Javascript中的Markdown解析器[关闭]

JavaScript的XML解析器[关闭]

用纯 JavaScript 编写的用于嵌入式环境的 XML 解析器 [关闭]

Java类载入器 ClassLoader的解析

Java的智能日期/时间解析器[关闭]