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

问题描述:

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

+0

你在说什么语言?请添加相关标签。 –

+0

@OliCharlesworth完成! – Raulp

+0

预处理发生在链接完成之前。所有的宏在编译前都被替换。 – squiguy

考虑以下代码:

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

词法分析阶段:你确定每个词/令牌和分配的意义吧。 在上面的代码中,通过识别随后Ñ随后然后空间是字INT,而且它是一种语言关键字开始; 其次是和一个空格是一个数字等等。

句法分析阶段:验证代码是否遵循语言语法(语法规则)。例如,您检查一个操作符的LHS是否只有一个变量(考虑语言C),每个语句是否由终止;,即如果后跟一个条件/布尔语句等

像其他人一样,通常预处理发生在词法分析或语法分析之前。

预处理发生在词法分析之前iirc 评论过滤掉#define,...之后,编译器使用扫描器/词法分析器(词法分析)生成标记。之后编译器生成的分析树,这些都为句法分析

+0

“预处理发生在词法分析之前iirc评论被过滤出来,..”感谢这个信息! – Raulp

+0

如果你想将它与自然语言进行比较,预处理就是从文本中获取文本。你过滤的东西如图片......然后你会得到词汇,这是词法分析,你正在寻找词汇,然后你做语法,这是如何构建句子,语法,... – Nicolas

也有例外,但它通常爆发这样的:

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

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

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

在一种情况下,词法分析发生两次。这是粘贴缓冲。看看代码:

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

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

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

+0

不应该是'lexemes'吗?'Lexemas'是西班牙语。 – Pharap

+0

也许..我在想什么拉丁文,即罗马文, –

+0

不是,它绝对是西班牙文:http://en.wiktionary。组织/维基/ lexema – Pharap

当我们谈论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,预处理,true_lexical,other_analysis。 PS:Real C编译器可能会以稍微不同的方式组织,但它的必须的行为与标准中写入的方式相同。