如何在编译器中实现反斜杠转义序列?

时间:2011-12-26 07:19:49

标签: c compiler-construction operating-system embedded-linux

我只是想知道在编译器中如何实现反斜杠转义序列? 如果我们在字符串中写“\ n”,编译器如何用新行字符替换它?编译器如何用“退格符”替换“\ b”?

我问,因为我写了代码:

#include<stdio.h>
main()
{
    printf("Hello \c");
}

输出结果为:

Hello 
Exited: ExitFailure 7 

我在编曲键盘中运行它,我正在阅读KnR书籍问题编号1.2。

先谢谢

3 个答案:

答案 0 :(得分:8)

要理解这一点,您必须了解编译器的工作原理。编译器通常采用的第一步称为词法分析(简称lexing)。词法分析是指编译器获取输入代码并将其分解为可识别的部分。为此,它通常使用正则表达式来识别不同的部分。它识别的一个部分是字符串文字,它是一个引用的字符串,如"Hello"。字符串文字的正则表达式通常看起来像"([^\"]|\"|\\|\n|\b)*"。其中,在英语中,是指以双引号开头并以双引号结尾的字符列表,其间有1)任何不是双引号或反斜杠的字符2)反斜杠然后是双引号引用3)反斜杠然后另一个反斜杠4)反斜杠然后是n 5)反斜杠然后是b。该中间图案重复零次或多次。 (注意:在实际编译器中,反斜杠后可能出现的字符列表通常更长)。寻找这种模式可以让它找到字符串文字。

然后,一旦识别出字符串文字,找出实际放入内存的字符串,就必须进行第二层处理,即通过字符串文字并处理反斜杠。它只是从头到尾读取,寻找反斜杠序列。每个反斜杠序列都被替换为不同的字符。 \"变为"\\变为\\n成为换行符。 \b成为退格符,等等。为了确定放在哪里,它只是使用一个表格来显示该序列的放置位置。

答案 1 :(得分:5)

经典的解释在肯·汤普森的着名文章'Reflections on Trusting Trust'中提供(也可以从许多other sources获得,包括他的接受书ACM Turing Award Lectures: The First Twenty Years 1966-1985)当他与Dennis Ritchie一起获得ACM图灵奖时发表演讲。

除此之外,它描述了如何将\v添加到无法识别它的编译器中:

  

C允许字符串构造指定初始化的字符数组。   字符串中的各个字符可以转义为表示   不可打印的角色。例如,

"Hello world\n"
     

表示字符“\n”的字符串,表示新行   字符。

     

图2.1是C编译器中代码的理想化   解释字符转义序列。这是一个了不起的一块   码。它以完全可移植的方式“知道”字符代码是什么   为任何字符集中的新行编译。然后知道的行为   允许它重新编译自己,从而使知识永久化。

     

假设我们希望改变C编译器以包含序列“\v”   表示垂直制表符。图2.1的扩展是   显而易见,如图2.2所示。然后我们重新编译C   编译器,但我们得到一个诊断。显然,自二进制版本   编译器不知道“\v”,来源不合法C.我们   必须“训练”编译器。在它“知道”“\v”的含义之后,我们就会知道   新的变化将成为合法的C.我们在ASCII图表上查找a   垂直制表符是十进制的11.我们将源代码改为图   2.3。现在旧的编译器接受新的源代码。我们安装了   结果二进制作为新的官方C编译器,现在我们可以写了   便携式版本我们在图2.2中的方式。

     

这是一个深刻的概念。它和我一样接近“学习”程序   看到。你只需告诉它一次,然后就可以使用它了   自引用定义。

     

图2.1

c = next();
if (c != '\\')
    return(c);
c = next();
if (c == '\\')
    return('\\');
if (c == 'n')
    return('\n');
     

图2.2

c = next();
if (c != '\\')
    return(c);
c = next();
if (c == '\\')
    return('\\');
if (c == 'n')
    return('\n');
if (c == 'v')
    return('\v');
     

图2.3

c = next();
if (c != '\\')
    return(c);
c = next();
if (c == '\\')
    return('\\');
if (c == 'n')
    return('\n');
if (c == 'v')
    return(11);

答案 2 :(得分:4)

以下是编译器的绝佳概述。它列出了组件: Difference between compilers and parsers?

简短的回答是编译器是一个字符串识别器。它会看到符合规则的内容(基于上下文),然后决定结果应该是什么。

这是一篇相关文章,其中一篇文章也推荐了Jonathan Leffler推荐的内容。 What's the Magic Behind Escape(\) Character

整个编译器的另一个简短答案是语法。