Skip to Content
Compiler

Lexical Analysis

2020-02-18Original-language archivelegacy assets may be incomplete

词法分析器的作用

  • 读入字符流,组成词素,输出词法单元
    • 过滤空白、换行、制表符、注释
    • 将词素添加到符号表
    • 逻辑上独立于语法分析,但通常和语法分析处于同一趟
  • 独立词法分析
    • 简化设计
    • 提高编译器效率
    • 增强编译器的可移植性
  • 概念
    • 词法单元 Token:<单元名,属性>
    • 模式 Pattern:描述了一类 Token 可能具有的形式
    • 词素 Lexeme:源程序中的字符序列

词法单元的规约(正则表达式)

  • 概念
    • 字符表:一个有穷符号的集合
    • 串:符号的有穷序列
    • 语言:给定字母表上串的可数集合
    • 前缀,后缀,子串
    • 连接:xyxy
    • 指数运算:xnx^n
  • 语言运算
    • LML\cup M
    • LMLM
    • L=i=0LiL^*=\cup_{i=0}^\infty L^i
    • L+=i=1LiL^+=\cup_{i=1}^\infty L^i
  • 正则表达式
    • 基本部分
      • L(ϵ)={ϵ}L(\epsilon)=\{\epsilon\}
      • L(a)={a}L(a)=\{a\}
    • 归纳部分
      • L((r)(s))=L(r)L(s)L((r)|(s))=L(r)\cup L(s)
      • L((r)(s))=L(r)L(s)L((r)(s))=L(r)L(s)
      • L((r))=L(r)L((r)^*)=L(r)^*
      • L((r))=L(r)L((r))=L(r)
    • 运算优先级 * 连接 |
    • 扩展
      • r+r+ = rrrr^*
      • r?r? = ϵr\epsilon|r
      • [a1an][a_1\cdots a_n] = a1a2ana_1|a_2\cdots|a_n
  • 正则集合:可以用正则表达式定义的语言
  • 正则定义:d1r1d_1\rightarrow r_1
    • 不能重复定义,不能与字母表重复

词法分析的识别(状态转换图)

  • Transition diagram
    • State: 识别词素时可能出现的情况
      • 状态是已处理部分的总结
      • 开始状态
      • 终止状态(带星号表示回退一个符号)
    • Edge:一个符号或多个符号
  • 保留字和标识符的处理
    • 法一:在符号表中先填保留字
    • 法二:建立高优先级的保留字
  • 构造词法分析器
    • State 记录当前状态
    • switch 跳转状态
    • if 对比边
    • 失败 fail()
    • 接受状态返回词法单元(*标记回退 forward 指针)

词法分析器生成工具及设计

  • Lex/Flex 编译器:lex.l (Lex compiler)-> lex.yy.c (C compiler)-> a.out
  • 声明部分
    • 常量
    • 正则定义
  • 转换规则
    • 模式 { 动作 }
  • 辅助函数
    • 各个动作的函数
  • 各部分用 %% 隔开
  • %{ %} 之间直接拷贝
%{
  //comment
}%
 
ws { \t\n}
 
%%
 
{ws} {/*no action*/}
if {return(IF)}
{id} {yylval = (int) installID(); return (ID);}
 
%%
 
int installID() {/* install lexeme */}
int installNum() {}
  • 冲突解决
    • 多个前缀匹配:选择最长的前缀
    • 多个模式匹配:选择前面的模式

有穷自动机

  • 有穷自动机:只回答 Yes/No
    • 状态有穷
    • 不确定有穷自动机 (NFA):边上符号限制,一个符号可出现在离开同一个状态的多条边上,ϵ\epsilon 可以做符号
    • 确定有穷自动机 (DFA)
  • 每个可以用正则表达式描述的语言,均可以用 NFA 和 DFA 来识别,反之亦然
  • NFA 定义
    • 有穷状态集合 SS
    • 输入符号集合 Σ\Sigma
    • 转换函数:Σ{ϵ}\Sigma\cup\{\epsilon\}
    • 开始状态:s0s_0
    • 接受状态:FF
  • 转换表表示法
    • 行头:条件
    • 列头:状态

正则表达式到 DFA

  • NFA -> DFA:子集构造法
    • 构造得到的 DFA 每个状态和 NFA 的状态子集对应
    • 最坏情况:2n2^n
    • 基本操作
      • ϵ\epsilon-closure(ss):从状态 ss 开始,只能通过 ϵ\epsilon 转换到的状态
      • ϵ\epsilon-closure(TT)
      • move(T,aT,a)
  • 正则表达式 -> NFA
    • 基本规则部分
      • 表达式 ϵ\epsilon
      • 表达式 aa
    • 归纳部分
      • sts|t
      • stst
      • ss^*
    • NFA 合并:引入新的开始状态
      • 转化为 DFA 中一个状态包含 NFA 中不同的结束状态:冲突
      • 关键字是其它模式的一个特例(优先选择特例)
  • DFA 状态数量最小化
    • 状态的可区分:如果存在串 xx 使从 s1s1s2s2 一个到达接受另一个到达非接受状态,则 xx 区分 s1s1s2s2
    • 最小化算法
      • 基本步骤:接受和非接受状态
      • 归纳步骤:sstt 可区分,且 ss'sstt'tt 有标号 aa 的边, ss'tt' 可区分
      • 最终没有区分开的态等价
    • 死状态:未定义时到达的状态