c++ - 解析 C++ 的复杂性

标签 c++ parsing theory big-o compiler-theory

出于好奇,我想知道关于解析 C++ 的一些“理论”结果是什么。

让 n 成为我的项目的大小(例如,在 LOC 中,但由于我们将处理 big-O 它不是很重要)

  • C++ 的解析时间复杂度是 O(n) 吗?如果不是,复杂性如何?
  • C(或 Java 或任何语法意义上更简单的语言)是否在 O(n) 中解析?
  • C++1x 是否会引入更难解析的新特性?

非常感谢引用!

最佳答案

我认为出于问题的目的,不同的人以不同的方式解释了“解析”一词。

从狭义的技术意义上讲,解析只是验证源代码是否与语法匹配(或者甚至可能构建树)。

有一个相当普遍的民间定理,它说您根本无法解析 C++(在这个意义上),因为您必须解析要解析的某些符号的含义。那个民间定理是完全错误的。

它源于使用“弱”(LALR 或回溯递归下降)解析器,如果它们错误地选择了文本的局部歧义部分的几个可能的子解析(this SO thread discusses an example),则完全失败由于有时会做出这样的选择。使用此类解析器解决困境的方法是在解析发生时收集符号表数据,并将额外的检查混入解析过程中,以强制解析器在遇到此类选择时做出正确的选择。这是以名称和类型解析与解析显着纠缠为代价的,这使得构建这样的解析器非常困难。但是,至少对于遗留的 GCC,他们使用了 LALR,它是解析的线性时间,如果你包括解析器所做的名称/类型捕获,我认为它不会更昂贵(解析后还有更多工作要做,因为我不不要以为他们什么都做)。

至少有两个使用“纯”完成的 C++ 解析器实现 GLR parsing技术,它只是承认解析可能在本地不明确,并在没有注释或显着开销的情况下捕获多个解析。 GLR 解析器是线性时间,没有局部歧义。它们在歧义区域的成本更高,但实际上,标准 C++ 程序中的大部分源文本都属于“线性时间”部分。所以有效率是线性的,甚至可以捕获歧义。两个已实现的解析器都在解析后进行名称和类型解析,并使用不一致来消除不正确的歧义解析。 (这两个实现是 Elsaour (SD's) C++ Front End 。我不能代表 Elsa 的当前能力(我认为它多年来没有更新),但我们的实现了所有 C++11 [2015 年 1 月编辑:现在完整的 C++14 编辑 2017 年 10 月:现在完整的 C++17] 包括 GCC 和 Microsoft 变体)。

如果您采用严格的计算机科学定义,即一种语言被扩展定义为一组任意字符串(语法应该是有意编码的简洁方法)并将解析视为“检查程序的语法是否正确"那么对于 C++,您已经展开模板以验证每个模板是否确实完全展开。模板中隐藏着一台图灵机,因此理论上检查 C++ 程序是否有效是不可能的(没有时间限制)。真正的编译器(遵守标准)对它们将执行多少模板展开设置了固定的限制,实际内存也是如此,因此在实践中 C++ 编译器会完成。但是从这个意义上说,他们可以花任意长的时间来“解析”一个程序。我认为这是大多数人关心的答案。

实际上,我猜大多数模板实际上都非常简单,因此 C++ 编译器的平均完成速度与其他编译器一样快。只有疯狂到用模板编写图灵机的人才会付出沉重的代价。 (观点:代价实际上是将复杂的东西硬塞到模板上的概念成本,而不是编译器执行成本。)

关于c++ - 解析 C++ 的复杂性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4172342/

相关文章:

python - 模逆计算卡住了

javascript - 如何生成 "composite key"(这又叫什么)?

c++ - 从命令行获取参数的问题

c++ - haskell 中用多态性替换条件的等效模式是什么?

c++ - C/C++ 解析器/词法分析器如何区分指针的 '*' 和乘法的 '*'?

parsing - 我如何在 Rebol 中解析这个?

c++ - 使用 lex 和 yacc 打印标记

c++ - 递归矩阵乘法算法计算失败

jquery - 使用 jQuery 解析 Atom feed 时遇到问题

theory - Kinect手势识别理论