Antlr4 "primitive"递归



按照 http://blog.ptsecurity.com/2016/06/theory-and-practice-of-source-code.html#java--and-java8-grammars,我试图在相当复杂的语法中减少左递归。 据我了解,递归的非原始形式可能会导致内存和处理时间方面的性能问题。

所以我试图在我的语法中重构这些规则,只使用"原始"递归。 当然,那篇博文是我唯一一次看到关于Antlr的"原始"递归一词。 所以我只是猜测它的含义/意图。 在我看来,这意味着一个规则,它将自己称为最多只有一个规则分支的 lhs。 正确?

目前我有一个表达式规则,如下所示:

expression
: expression DOUBLE_PIPE expression         # ConcatenationExpression
| expression PLUS expression                # AdditionExpression
| expression MINUS expression               # SubtractionExpression
| expression ASTERISK expression            # MultiplicationExpression
| expression SLASH expression               # DivisionExpression
| expression PERCENT expression             # ModuloExpression
...
;

...包括相当多的子规则,这些子规则也可以追溯到expression. 但这些是唯一具有直接递归的。

如果我理解正确,将这些重构为"原始"递归将如下所示:

expression
: binaryOpExpression                        # BinaryOpExpression
...
;
binaryOpExpression
: expression DOUBLE_PIPE expression         # ConcatenationExpression
| expression PLUS expression                # AdditionExpression
| expression MINUS expression               # SubtractionExpression
| expression ASTERISK expression            # MultiplicationExpression
| expression SLASH expression               # DivisionExpression
| expression PERCENT expression             # ModuloExpression
;

首先,这是正确的重构吗?

其次,这真的有助于性能吗? 归根结底,它仍然是相同的决定,所以我并不真正了解这如何帮助性能(除了可能产生更少的 ATNConfig 对象(。

谢谢

我以前没有在这种情况下听说过"原始递归",作者可能只是想在 ANTLR4 中命名一种特定形式的递归。

事实上,ANTLR4 中有 3 种相关的递归形式:

  • 直接左递归:从规则中的第一个规则引用(到同一规则(的递归。例如:a: ab | c;
  • 间接左递归
  • :不直接来自同一规则的左递归。例如:a: b | c; b: c | d; c: a | e;(在ANTLR4中不允许(
  • 右递归:规则中的任何其他递归。例如:a: ba | c;.然而,名称"右递归"仅在二进制表达式的情况下是正确的,但通常用于与一般的左递归区分开来。

话虽如此,很明显您的重写是错误的,因为它会产生间接的左递归,而 ANLTR4 不支持。直接左递归通常不是问题(从内存或性能的角度来看(,因为ANTLR4将它们转换为非递归ATN规则图。

可能成为问题的是右递归,因为它们是通过代码递归(运行时中的递归函数调用(实现的,这可能会耗尽 CPU 堆栈。我见过无法在单独线程中解析的大表达式的情况,因为我无法将线程堆栈大小设置为更大的值(主线程堆栈大小通常可以通过链接器设置进行调整(。

对于后一种情况,我发现它很有用,是减少语法中相互调用的解析器规则的数量。当然,将某些表达式元素放在不同的规则中(例如andExpressionorExpressionbitExpression等(是结构、可读性等问题,但这可能会导致相当深的调用堆栈,这可能会耗尽 CPU 堆栈和/或需要大量时间来处理它们。

相关内容

  • 没有找到相关文章

最新更新