MP1.2 Cool Lexer

本次实验是完成 Cool 语言的词法分析部分. 主要内容为: 参考 Cool 语言的 Manual, 写出 Cool 的 各类token 的正规表达式, 用 flex词法描述文件表达, 并且增加错误处理. 完成这次实验后, 你会得到一个 lexer 的可执行文件, 它读入一个 Cool 程序, 输出一个 Token 序列;此外, lexer 对错误的程序也应该有较好的处理. 这个 lexer 将在 MP1.3 中使用到.

下面介绍本次实验的要求, 并提供一些 flex 相关的资料.

1. 文件说明

在做 MP1.1 中,已经要求你把 cool-support, reference-binariessrc 复制到了你的 mp1 目录下. 如果你上次确实交了作业, 现在你的目录结构应该是这个样子:

PBXXXXXXX                            : git 根目录
├── README-git
└── mp1/
    ├── answer.txt                   : 上一次的作业
    ├── cool-support
    │   ├── include
    │   └── src
    ├── reference-binaries
    └── src
        ├── Makefile
        ├── bison_test_bad.cl
        ├── bison_test_good.cl
        ├── cool.flex
        ├── cool.y
        └── flex_test.cl

mp1/src/ 目录下, 执行

$ make lexer

会编译生成 lexer 可执行文件, 第一次执行这个命令时会将 cool-support 里的文

件也链接到该目录下.

实验涉及到的就是现在目录下的这些文件:

├── Makefile
├── bison_test_bad.cl             : 在mp1.3 中使用
├── bison_test_good.cl            : 在mp1.3 中使用
├── cool-lex.cc                   : flex 根据 cool.flex 生成的词法分析器源码
├── cool.flex                     : 你要完成的的 flex 文件
├── cool.y                        : 在mp1.3 中使用
├── flex_test.cl                  : 一个 cool 程序, 用于测试
├── handle_flags.cc -> ../cool-support/src/handle_flags.cc
|                                 : lexer 命令行选项的处理
├── lexer
├── lextest.cc -> ../cool-support/src/lextest.cc
|                                 : main 函数在这里
├── stringtab.cc -> ../cool-support/src/stringtab.cc
|                                 : 需要用到的函数, 参见 stringtab.h
├── utilities.cc -> ../cool-support/src/utilities.cc
└                                 : 需要用到的函数, 参见 utilities.h

你需要修改的文件为

  • cool.flex
    一个 flex 词法描述文件的框架. 编译生成的 lexer 只是把输入原样输出. 为了完成实验, 你需要添加Cool 的词法元素的正规表达式和一些辅助函数, 辅助函数请直接放在这个文件里.

  • flex_test.cl
    包含一些 cool 语言的测试输入. 仅通过这个测试是不够的. 你应该充分测试你的 lexer.

    我们的会用我们的测试例子来测试你的程序. 你不用提交这个文件.

lexer 的运行方式为:

$ ./lexer flex_test.cl

handle_flags.cc 里了解更多命令行选项. 其他文件请勿修改.

2. 对词法分析器的要求

你应该根据 Cool manual : CoolAid 中的 Section 10 的 Figure 1 (P16) 来完成词法规则的定义. 返回的 Token 的类型定义在 cool-support/include/cool-parse.h.(涉及到 flex 与 bison 的合作, 请利用后面的资源了解这个过程).

a. 基本要求

  • 完成关键词的分析.

  • 完成行号的记录, 变量 curr_lineno 用来记录源码的行号(已经定义).

  • 程序中一个词法单位(lexeme) 往往出现多次, 比如一个变量名. 为了节省时间和空间, 编译器会把这些词法单元用一个 string table 保存. 在 cool-support 里面提供了一个 string table 的实现. 有三种 String Table: 字符串的、整型常量的、标识符的. 请填好这三个 String Table.

此外,不用检查整型常量是否合适. 特殊的 Identifier (如 Object, Int, self 等)暂时不用特殊处理, 以后再说.

b. 错误处理与错误恢复

所有的错误都会传给以后实验中的 parser. 遇到错误时, 返回 ERROR 这个 token , 并且给 yylval.error_msg 赋值一个代表错误说明的字符串.

下面是本实验要处理的错误. 这些情况返回 ERROR token, 下面说的返回字符串是指通过变量yylval.error_msg 返回.

  • 遇到无效字符(不可能是任何 token 的开头)时, 返回包含这个字符的字符串, 并从下个字符开始继续分析.

  • 字符串过长, 或者包含了无效字符,则报错 "String constant too long" / "String contains null character". 在这个字符串的结束处开始继续分析, 不要为这个字符串生成错误记号之前生成一个string token.

  • 如果一个字符串包含非转义的换行, 则报错 "Unterminated string constant", 并从下一行开始恢复词法分析 -- 这里假设程序员忘记加 close-quote (即右引号). 在生成错误记号前不产生一个 string token.

  • 如果在字符串/注释中遇到了 EOF, 则报错 "EOF in string constant/comment". 不要为这个注释生成 token.

  • 在注释之外的地方遇到了 *), 报错 "Unmatched *)", 而不是生成 * ) 两个 token.

实验的难点在于对 string 和 comment 的词法分析, 建议放到最后实现, 需要使用到 Start Condition 的功能.

建议先理解代码, 了解 lexer 是怎么运行的, 利用好现有代码, 结合 A Tour of the Cool Support Code 先理解 cool-support 里面的代码再开始写. 不要反复造轮子, 可以使用utilities.h 里面的函数.

3. 提交要求

你提交的文件目录应该是这个样子:

PBXXXXXXXX                             : git 根目录
├── README-git
└── mp1/
    ├── answer.txt
    ├── cool-support
    ├── reference-binaries
    └── src
        ├── READEME(.md)       *********: 说明文档
        ├── Makefile
        ├── bison_test_bad.cl
        ├── bison_test_good.cl
        ├── cool.flex          *********: 你的主要工作在这
        ├── cool.y
        └── flex_test.cl

README 中说明你实现了哪些功能, 并尽可能给出自己实现的说明文档.

cool.flex 里面记得多写点注释.

提交前先运行

$ make realclean

4. 资料

flex 和 bison

本实验内容参考UIUC Compiler 课程的 Project MP1

results matching ""

    No results matching ""