banner
DIYgod

Hi, DIYgod

写代码是热爱,写到世界充满爱!
github
twitter
bilibili
telegram
email
steam
playstation
nintendo switch

一个完整编译器的实现(一) 词法分析

GitHub 地址 各阶段源码 各阶段说明集合

为了将一个程序从一种语言翻译成另一种语言,编译器必须首先把程序的各种成分拆开,并搞清其结构和含义,然后再用另一种方式把这些成分组合起来。编译器的前端执行分析,后端进行合成。

而分析一般分为 3 种:词法分析 语法分析 语义分析

本阶段进行的是词法分析,目的是将输入文件分解成一个个独立的词法符号,即单词。

根据虎书的提示,在本阶段分了三个模块:

1. 错误处理模块(errormsg.c errormsg.h):用来产生含文件名和行号的报错信息
2. 词法分析模块(lexical.lex token.h):通过 Lex 进行词法分析
3. 常用工具模块(util.c util.h):定义一些常用的函数

词法分析模块与错误处理模块:两者通过 errormsg.h 中声明的变量和函数进行通信:EM_tokPos 变量传递每个单词以字符为单位的位置;EM_newline () 函数记录行号;EM_error () 输出报错信息。

错误处理模块与常用工具模块:错误处理模块使用 util.h 中声明的 checked_malloc () 分配内存函数

另外还包含了 驱动程序(driver.c)测试文件(test.c) makefile

下面主要介绍本阶段最重要的词法分析模块。

tokens.h:定义词法单词常量以及 yylval

上述代码定义了 yylval,yylval 是一个表示不同语义值的集合,其中的 ival cval dval sval 分别用来保存 整数 字符 浮点数 字符串 单词的语义值。

这段定义了一些常数,这些常数供 lexical.lex 使用,它们指明被匹配的是何种类型的单词。

lexical.lex:Lex 的源文件,可以通过 Lex 生成一个词法分析器

Lex 是一个可以将正则表达式转换城词法分析器的生成器,它由词法规范生成一个 C 程序(lex.yy.c)。该规范包含一个正则表达式和一个动作。这个动作将单词类型(可能和其他信息一起)传给编译器的下一处理阶段。

第一部分,即位于 %{...%} 之间的部分,包含有若干由此文件其余部分 C 代码使用的 include 和声明。

第二部分,即位于 %}...%% 之间的部分,包含正则表达式的简写形式和状态说明,比如你可以写上

那么第三部分中就可以用 {digits} 代替 [0-9]+ 了。

第三部分,即位于 %% 后面的部分,包含正则表达式和动作。每个动作返回一个 int 类型的值(token.h 定义的常数),指出匹配的是哪一种单词。
其中有两条匹配的原则来消除二义性:
规则优先:对于一个特定的最长初始子串,第一个与之匹配的正则式决定这个子串的单词类型;
最长匹配:通过规则优先确定正则式之后,子串取与正则式匹配的最长的字符串。

几个变量:yytext 是正则式匹配的字符串;yyleng 是所匹配的字符串的长度;charPos 追踪每一个单词的位置,并告知 EM_tokPos。

 

词法分析 Done.

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.