[编译原理读书笔记][第3章 词法分析]
标签(空格分隔): 未分类
本章我们主要讨论如何构建一个词法分析器
- 首先建立起每个词法单元的词法结构图或其他描述.
- 编写代码识别输入中出现的每个词素,并返回识别到词法单元的有关信息
词法分析器生成工具(lexical-analyzer generator)
- 描述出词素模式,然后将这些模式编译为具有词法分析功能的代码.
- 程序员只要在抽象很高的层次上描述软件,就能生成代码.
- 3.5节将介绍一个名为
Lex
分析器生成工具
正则表达式
- 正则表达式是一种很方便描述词素模式的方法.
我们将介绍正则表达式进行转换:
- 首先转换为不确定有穷自动机.
- 然后转换为确定又穷自动机.
驱动程序
就是模拟这些自动机的代码,使用自动机确定下一个词法单元.
驱动程序和自动机的规约形成词法分析器的核心部分.
3.1 词法分析器的作用
词法分析是编译的第一阶段.
词法分析器的主要任务是
- 1.读入源程序的输入字符
- 2.将他们组成词素,生成并输出一个词法单元序列,每个词法单元对应一个词素.
词法分析,语法分析,符号表的交互
getNextToken
所指示的调用使得词法单元从它的输入不断读取字符,直到识别到下一个词素为止.- 词法单元根据词生成一个词法单元返回给语法分析.
词法分析其余任务
- 过滤注释和空白
- 编译器生成的错误信息,和源代码的位置练习起来
有时候,词法分析分成两个级联处理
- 扫描阶段: 不生成词法的单元的简单处理:删除注释和将多个空白压缩成一个
- 分析极端:处理扫描阶段的输出,返回词法单元
3.1.1 词法分析及语法分析
把编译阶段的分析部分化为词法分析和语法分析阶段有如下几个原因:
- 最重要的考虑是简化编译器设计
- 提高编译器效率(因为能专精)
- 增强编译器的可移植性.
3.1.2 词法单元,模式和词素
三个相关但有区别的术语.
- 词法单元:由一个词法单元名和一个可选属性组成.
- 词法单元名:是一种表示某种词法单元的抽象符号.
- 比如一个关键词,标识符的输入字符序列.
- 词法单元名是由语法分析处理的输入符号.
- 通常用黑体字表示词法单元名
- 词法单元名:是一种表示某种词法单元的抽象符号.
- 模式:描述一个词法单元的词素可能具有的形式.
- 词法单元是关键词时:
- 模式是组成这个关键词的字符序列
- 对于标识符和其他词法单元:
- 模式是一个更加复杂的结构,可以和很多符号串匹配.
- 正则表达式
- 词法单元是关键词时:
- 词素:是源程序的一个字符序列.
- 和某个词法单元的模式匹配
- 被词法分析器识别为该词法单元的一个实例.
在很多程序设计语言中,下面类别覆盖了大多数词法单元
- 每个关键词有一个词法单元.
- 一个关键词的模式是他本身.
- 表示运算符的词法单元
- 表示所有标识符的词法单元
- 一个或多个表示常量的词法单元
- 每一个标点符号 有一个词法单元
3.1.3 词法单元的属性
- 词法单元的属性:如果多个词素可以和一个模式匹配,那么词法分析器必须向编译器的后续阶段提供被匹配词素的附加信息.
- 一个
标识符
的属性值是一个指向符号表中该标识符条目的指针.
- 一个
3.1.4 词法错误
如果没有其他组件帮助,词法分析器很难发现源代码的错误.
比如:
fi(a==f(x))
- 词法分析器会当做一个标识符作为词法单元传给语法分析器
- 这个错误将由语法分析器处理.
恐慌模式
:所有词法单元都无法和剩余输入的某个前缀相匹配时的策略- 我们从剩余的输入不断删除字符,直到词法分析器能够在剩余的开头发现一个正确的词法单元为止.
3.1.5 练习
<float> <id, limitedSquaare> <(> <id, x> <)> <{
>
<float> <id, x>
<return> <(> <id, x> <op,"<="> <num, -10.0> <op, "||"> <id, x> <op, ">="> <num, 10.0> <)> <op, "?"> <num, 100> <op, ":"> <id, x> <op, "*"> <id, x>
<}>
<text, "Here is a photo of"> <nodestart, b> <text, "my house"> <nodeend, b>
<nodestart, p> <selfendnode, img> <selfendnode, br>
<text, "see"> <nodestart, a> <text, "More Picture"> <nodeend