【问题标题】:Deterministic Context-Free Grammar versus Context-Free Grammar?确定性上下文无关语法与上下文无关语法?
【发布时间】:2014-04-26 15:51:30
【问题描述】:

我正在阅读我的比较语言课笔记,我有点困惑......

上下文无关文法和确定性上下文无关文法有什么区别?我正在专门阅读有关 CFG 的解析器是 O(n^3) 和 DCFG 的编译器是 O(n) 的具体情况,并且并不真正了解时间复杂度的差异如何如此之大(更不用说我是仍然对使 CFG 成为 DCFG 的特征感到困惑)。

非常感谢您!

【问题讨论】:

标签: parsing programming-languages big-o context-free-grammar context-free-language


【解决方案1】:

从概念上讲,它们很容易理解。上下文无关文法是可以用 BNF 表达的文法。 DCFG 是可以编写可用解析器的子集。

在编写编译器时,我们只对 DCFG 感兴趣。原因是“确定性”大致意味着要在解析中的任何点应用的下一个规则由到目前为止的输入和有限量的前瞻确定。 Knuth 在 1960 年代发明了 LR() 编译器,并证明它可以处理任何 DCFG。从那以后,一些改进,特别是 LALR(1) 和 LL(1),定义了可以在有限内存中解析的语法,以及我们可以用来编写它们的技术。

如果我们知道 BNF 是其中一种语法,我们也有自动从 BNF 派生解析器的技术。 Yacc、Bison 和 ANTLR 都是熟悉的例子。

我从未见过 NDCFG 的解析器,但在解析的任何时候,它都可能需要考虑整个输入字符串以及可以应用的每个可能的解析。不难看出为什么它会变得相当大和缓慢。


我应该指出,许多真实的语言是不完美的,因为它们不是完全上下文无关的,不是明确的或偏离理想的 DCFG。 C/C++ 是一个很好的例子,但还有很多其他例子。这些语言通常由特殊用途的规则处理,例如语义或句法谓词、特殊情况回溯或其他不影响性能的“技巧”。


cmets 指出某些类型的 NDCFG 很常见,许多工具都提供了处理它们的方法。一个常见的问题是模棱两可。通过引入简单的局部语义规则来解析歧义语法相对容易,但当然这只能生成可能的解析树之一。 NDCFG 的通用解析器可能会生成所有解析树,并且可能允许在任意条件下过滤这些树。我一个都不知道。

左递归不是 NDCFG 的功能。它对 LL() 解析器的设计提出了特别的挑战,但对于 LR() 解析器来说没有问题。

【讨论】:

  • 根据您在此处提供的定义,ANTLR 4 适用于 NDCFG。
  • @280Z28:见编辑。 ANTLR 可以处理与 DCFG 的某些有限偏离,大多数解析器生成器也可以。
  • ANTLR 4 使用具有歧义检测和分辨率的非回溯无限前瞻预测机制。它可以为任何不包含间接或隐藏左递归的 NDCFG 提供一个有效的解析树(直接左递归很好)。
  • 查看 GLR 和 GLL 解析,了解 NDCFG 的实用解析器。用 DCFG 解析 C++ 是一场噩梦,因为事实上大部分语法确实是模棱两可的。我们使用 GLR 直接解析 C++。请参阅stackoverflow.com/questions/243383/… 进行扩展讨论。
猜你喜欢
  • 2012-01-04
  • 2013-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-03
  • 1970-01-01
相关资源
最近更新 更多