解析C语言乱序

时间:2013-02-05 14:42:15

标签: c parsing compiler-construction programming-languages

严格按顺序解析C,即在使用之前必须声明所有内容;特别是,必须在这些类型的变量之前声明类型。这是有道理的,因为如果你不知道什么是类型的名称和什么不是,那么语法将是模棱两可的,例如, a * b取决于a是否为某个类型命名。

另一方面,一些C系列语言具有放宽此限制的理想属性(从而消除了对头文件的手动操作)。我正在为一个C-superset语言编写一个解析器,这个语言同样也放宽了限制,所以现在我需要弄清楚如何去做。

我遇到的一种方法是做两次传球。第一遍通过一切,利用顶层的所有东西必须是声明而不是声明的事实,并获取所有类型。在这个阶段,函数体未被检查,只是被匹配作为由匹配大括号分隔的标记流。第二遍解析函数体。函数中的局部声明必须按顺序排列,但这不是一个真正的问题。

这个方法中我有没有想到的任何绊脚石?

C ++,Java,C#等编译器通常如何处理那些不需要按顺序声明的语言部分?

3 个答案:

答案 0 :(得分:2)

解析时不必进行名称解析。首先,如果您正在设计一个“类C”语言(而不是新的C实现),您可以定义语法,以便语法中的声明,表达式,方法等都是明确的。然后解析顺序无关紧要。 (这也可以通过将预处理器以结构化方式集成到语言中来解决预处理器疾病。)

如果您坚持使用类C语法,则可以使用容忍歧义的解析器,例如,happy to process "x*y;"并将其作为表达式和声明保存,直到获得更多数据。在极端情况下,只需将其视为基于约束的解决方案。 C和C ++坚持首先要知道定义,因为最初的编译器内存空间非常有限,你不能只保留所有内容;那不再是真的。解析时,您不必坚持知道答案。

我们在DMS Software Reengineering Toolkit中使用GLR解析器,非常乐意解析C和C ++ 11。我们在解析后命名解析;这隔离了解析和名称解析,使前端更清晰,更易于管理。

答案 1 :(得分:1)

C ++ 确实需要按顺序声明。

请记住,C和C ++是一个完全不同的球赛。他们正在使用积极的古老链接器技术(C,因为它古老的,C ++因为它几乎与C链接器一样古老且兼容)。两者都会产生直接在CPU上运行的二进制文件,而无需运行时支持。

Java和C#有很多改进依赖的链接器,以及一个庞大的运行时支持系统。

要么有利有弊。 C / C ++方法的一个缺点是必须在编译时解决所有问题,因为在运行时应用程序是独立的。专业人员是在编译时解决所有问题,因此在运行时,应用程序可以单独使用。

答案 2 :(得分:0)

几乎所有编译器都会进行两次传递。另一种方法是允许在语法本身中声明变量,这会使语法更难以手工解析,但不需要第二次传递。