出于好奇,我想知道关于解析 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++ 程序中的大部分源文本都属于“线性时间”部分。所以有效率是线性的,甚至可以捕获歧义。两个已实现的解析器都在解析后进行名称和类型解析,并使用不一致来消除不正确的歧义解析。 (这两个实现是 Elsa 和 our (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/