ANTLR 和 parboiled 在 Java 中解析有什么区别?
- 初学者在解析中哪个更容易使用?
- 哪个更具可扩展性?(从简单到复杂的语法)
- 哪个对AST构建有更好的支持?
- 哪个会为语法错误产生更好的错误或警告消息?
- 哪个解决的问题更少?(例如左递归、移位/归约冲突、归约/归约冲突)
- 与其他开源工具的比较也值得赞赏
ANTLR 和 parboiled 在 Java 中解析有什么区别?
Parboiled 看起来是一个非常酷的工具。对于初学者来说可能更容易,因为它只是使用“解析器组合器”习语的纯编程。我认为这会变得非常冗长且难以阅读,尽管 Java 语法看起来并没有我看到的那么糟糕。我无法评论它的 AST 构造,但 ANTLR 4 生成解析树而不是 AST。它声称有很好的错误消息/恢复,但这是可疑的,因为它基于解析器表达式语法,只有在看到整个输入后才能检测到错误(最坏的情况)。它也无法识别语法中的歧义(不是冲突、歧义)。两种工具都不会宣布解析冲突。ANTLR 4 处理算术表达式之类的直接左递归,但通常这两种工具都不能处理左递归。ANTLR 要求您为其解析器解释器使用一个库,例如 parboiled,但如果您想让它生成解析器,您必须学会使用该工具。目前,ANTLR 4 可以在 Java、C#、JavaScript、Python 2、Python 3 中生成解析器。
今天,Parboiled 主要是 scala 工具。因此,如果您使用的是 scala,它可能是大多数情况下更好的解决方案。
ANTLR 对初学者来说应该容易得多。它更容易开始。
Parboiled 是一个 scala 库。您将获得开箱即用的语法亮点和类型检查。Parboiled1 在大多数 IDE 中都能正常工作。Parbiled2 没有(很快会在 Idea 中修复)。该库使用宏表达式,大多数 IDE 对此并不满意。这就是为什么您将所有东西都变成红色的原因。
但两者都很容易开始。
在我看来,Parboiled 更具可扩展性。因为您正在编写 scala 代码。您可以将解析器分解为多个 scala 特征,并将它们相互混合。您可以创建 DateTime 解析器,并将其混合到 LogEvent 解析器或 $PROTOCOL_NAME 解析器。并轻松地重复使用它们。对于 parboiled1,您可以在运行时做一些顽皮的事情。好吧,它给了你力量。在某些情况下,您可以即时构建解析器。例如,您有日期时间格式,定义为字符串。您可以读取格式字符串并为其生成适当的解析器。甚至 Parboiled2 也是可能的(它在编译期间做了很多事情)。我不知道 ANTLR 是否可行。
我喜欢 AST 的 Parboiled 方法。它希望您定义ADT。因此,在理想情况下,您将拥有一个不可变的案例类树。您可以在树节点中添加一些“类似 dsl”的东西。例如,您可以为您的节点定义“\”方法,该方法返回具有指定名称的子节点。
case class Node(value: String) {
....
def \ (childName: String): Option[Node] =
this.children.find(child => child.name == childName)
}
然后使用它:
city \ "3rd street" \ "23"
这使得使用 AST 变得更加容易。我希望它有所帮助。
好吧,如果我必须将作为最近使用这两个框架作为解析框架的新手的开发人员进行比较,那么我有以下比较。
ANTLR | 煮熟的 | |
---|---|---|
1 | 一般来说,它有更好的文档,有自己的网站,有一本书(Terrence Parr 的 The Definitive ANTLR reference),在 git 中有多个示例。 | 它的文档有限,仅在 git 中可用。 |
2 | 有针对不同 IDE 的 ANTLR 插件,允许查看规则的语法图,检查 parseTree 的输入。它对编写规则有很大帮助。 | 它没有任何适用于 IDE 的插件。 |
3 | 它是一个java框架,用java编写。 | 这是一个 Scala 库/框架,如果我们在 Scala 中编写解析器,它就很好。Parboiled2 不支持 java。因此,如果我们必须在 java 中使用它,我们需要旧的 Parboiled1。 |
4 | 在 Antlr 中,我们将解析规则或语法分别编写在 .g4 文件中。我们需要先生成语法对应的*.java文件。每次我们更改语法时都会重新生成。 | 在 Parboiled 中,我们必须在 java 本身中编写解析规则和语法。 |
5 | 在 antlr 中,我们通过将输入传递给生成的 *.java antlr 类来获得 ParseTree(类似于 AST)。 | 在 parboiled 中,我们必须使用抽象数据类型并使用值堆栈来推送和弹出值,同时编写语法以获取 AST。 |
因此,在使用了这两个之后,我发现 Antlr 更易于使用和学习。