在C编译器中编译过程中的词法和句法分析是什么?

时间:2012-06-23 19:18:30

标签: c parsing compilation preprocessor lexical-analysis

编译过程中的词法和句法分析是什么?预处理是否在词法和句法分析之后发生?

5 个答案:

答案 0 :(得分:14)

考虑以下代码:

     int a = 10;
     if (a < 4)
     {
          printf("%d", a);
     }

词法分析阶段:您识别每个单词/标记并为其指定含义。 在上面的代码中,首先要确定 i ,然后是 n ,然后是 t ,然后空格是 int < / strong>,它是一个语言关键字; 1 后跟 0 ,空格是 10 ,等等。

语法分析阶段:验证代码是否遵循语言语法(语法规则)。例如,您检查运算符的LHS上是否只有一个变量(考虑语言C),每个语句都以; 终止,如果通过条件/布尔语句等。

与其他人提到的一样,通常,预处理在词法分析或句法分析之前发生。

答案 1 :(得分:2)

词法分析发生 BEFORE 语法分析。这是合乎逻辑的,因为当需要调用宏时,必须首先识别标识符的边界。这是通过词法分析完成的。在语法分析开始之后。请注意,在开始语法分析之前,编译器通常不会生成完整的预处理源。他们读取源一次选择一个lexema,如果需要进行预处理,并将结果提供给句法分析。

在一个案例中,词法分析发生两次。这是粘贴缓冲。看一下代码:

#define En(x) Abcd ## x ## x

enum En(5)
{
    a, b = 20, c, d
};

此代码定义名称为Abcd55的枚举。在宏扩展期间处理##时,数据将放入内部缓冲区。之后,这个缓冲区的扫描就像一个小的#include。在扫描期间,编译器会将缓冲区的内容分解为lexemas。可能会发生扫描的lexemas的边界与放入缓冲区的原始lexemas的边界不匹配。在上面的例子中,3个lexemas放入缓冲区,但只检索了一个。

答案 2 :(得分:1)

预处理在词法分析之前发生 注释被过滤掉,#define,...然后,编译器生成带有扫描器/词法分析器(词法分析)的标记。之后编译器生成用于语法分析的分析树

答案 3 :(得分:0)

有例外情况,但通常会出现这样的情况:

  • 预处理 - 将程序文本转换为程序文本
  • 词法分析 - 将程序文本转换为“令牌”,它基本上是带有属性的小整数
  • 句法分析 - 将程序文本转换为抽象语法

“抽象语法”的定义可能有所不同。在一次通过编译器中,抽象语法相当于tartget代码。但是这些日子通常是树或DAG逻辑上代表程序的结构。

答案 4 :(得分:0)

当我们谈论C编程语言时,我们应该注意到该语言有一个ISO(ANSI)标准。以下是C99的最后公开草案(ISO / IEC 9899:1999):www.open-std.org/jtc1/sc22/wg14/www/docs/n1124.pdf

有一节“5.1.1.2翻译阶段”,说明如何解析C程序。有阶段:

...多字节,三字符和反斜杠处理的一些步骤......

  

3)。源文件被分解为预处理令牌和序列   空格字符(包括注释)。

这是预处理的词法分析。只有预处理程序指令,标点符号,字符串常量,标识符,注释在这里被激活。

  

4)。执行预处理指令,扩展宏调用

这是预处理本身。此阶段还将包含来自#include的文件,然后它将删除预处理指令(如#define#ifdef和其他)

...处理字符串文字...

  

7)。分隔标记的空白字符不再重要。每   预处理令牌转换为令牌。由此产生的代币是   语法和语义分析和翻译为翻译单位。

转换为令牌意味着语言关键字检测和常量检测。 这是最终词汇分析的一步;句法和语义分析。

所以,你的问题是:

  

预处理是否在词法和句法分析之后发生?

需要进行一些词法分析来进行预处理,所以顺序是: lexical_for_preprocessor,preprocessing,true_lexical,other_analysis。

PS:Real C编译器的组织方式可能略有不同,但必须的行为方式与标准编写方式相同。