实验二 词法分析程序设计

一、实验目的

1. 学习和掌握词法分析程序的构造

2. 学习Tiny的词法分析器

二、实验内容与要求

  1. 实验内容

TINY 语言的词法由TINY Syntax.ppt 描述;

TINY 语言的词法分析器由TINY Scanner.rar 的C 语言代码实现;

TINY+语言的词法由TINY+ Syntax.doc 描述。

任务:理解TINY 语言的词法及词法分析器的实现,并基于该词法分析器,

实现拓展语言TINY+的词法分析器。

要求:

1) TINY+词法分析器以TINY+源代码为输入,输出为识别出的token 序列;

2) 词法分析器以最长匹配为原则,例如‘:=’应识别为赋值符号而非单独的‘:’及‘=’;

3) Token 以(种别码,属性值)表示,包含以下类型的种别码:

  • KEY 为关键字;
  • SYM 为系统特殊字符;
  • ID 为变量;
  • NUM 为数值常量;
  • STR 为字符串常量。

4) 识别词法错误。词法分析器可以给出词法错误的行号并打印出对应的出错消息,主要包含以下类型的词法错误:

  • 非法字符。即不属于TINY+字母表的字符,比如$就是一个非法字符;
  • 字符串匹配错误,比如右部引号丢失,如‘scanner
  • 注释的右部括号丢失或匹配错误,如{this is an example

三、实验步骤与过程

1. 理解TINY 语言的词法及词法分析器的实现

首先我们来观察Global.h文件,其中包含了词法分析器中包含的全局变量。

以下全局变量分别用于表示源代码文件、输出text文件、中间代码文件以及当前行号。

以下为枚举类型的保留字TokenType,可以看到 TINY 语言中的关键字 KEY 和系统特殊字符 SYM 也是在这里定义的。

以下是6个跟踪标志EchoSource、TraceScan、TraceParse、TraceAnalyze、TraceCode、Error。

EchoSource为真时表示源程序在解析期间以行号回显到列表文件。

TraceScan为真时表示每个token都被扫描器识别,然后将token信息打印到列表文件。

TraceParse为真时表示语法树以线性化形式打印到列表文件(对子项使用缩进)。

TraceAnalyze为真时表示要报告给列表文件的符号表插入和查找。

TraceCode为真时表示生成代码时要写入 TM 代码文件的注释。

Error为真时表示如果发生错误,将会程序进行下一步。

接下来我们来观察scan.h和scan.c文件,它们是作为词法分析的源程序。

以下为枚举类型的保存状态StateType,可以看到共有START, INASSIGN, INCOMMENT, INNUM, INID, DONE 6个状态。

以下为保存标识符tokenString,其长度为MAXTOKENLEN+1。

以下全局变量分别用于表示读取一行字符保存、指示缓存中第几个字符、当前缓存中字符串长度以及错误标识。

以下是结构体reservedWords,其用于保存保留字结构,方便查询。

以下是函数getNextChar,它的作用是获取缓存中下一个字符。

以下是函数ungetNextChar,它的作用是如果文件没有结束,那么直接将linepos减去1就可以重新读取该字符以实现回吐的目的。

以下是函数reservedLookup,它的作用是根据getToken返回的字符,在保留字数组中进行查找。如果找到,说明该词素为保留字,返回保留字的类型。否则返回ID表示该词素的类型为ID。

以下是函数getToken,也是该文件的主要功能,它的作用是返回标识符,以下对函数进行详细分析。

首先函数声明了4个标号,其中tokenStringIndex用于保存标识符,currentToken用于保存要返回的Token,state则表示当前的状态,其初值为开始状态start,save表示是否需要保存到 tokenString。

接下来进入循环,循环条件为state不等于DONE,先调用getNextChar函数获取缓存中下一个字符并放到临时变量c中,再根据state的状态值进行下一步,如果是开始状态START,则判断c是哪种字符(数字、字母、冒号、空格、换行符、制表符、左括号),然后设置对应的state状态值,比如如果c是数字,就把state设为数值常量状态INNUM。

如果c不是以上情况,那么再判断c是否为系统特殊字符或EOF,如果都不是,说明这是一个非法字符,以上是state为start的情况。

如果state是INCOMMENT,说明是注释状态,不用进行保存。

如果state是INASSIGN,则查看c是否为'=',如果不是,则不合法,并调用ungetNextChar函数回退一个字符以及把ERROR赋给currentToken。

如果state是INNUM,则查看c是否为数字,如果不是,则调用ungetNextChar函数回退一个字符。

如果state是INID,则查看c是否为字符,如果不是,则调用ungetNextChar函数回退一个字符。

如果state在这里已经为DONE或者state为其他状态,说明程序出现问题,有BUG。

接下来如果save为真,而且tokenStringIndex长度合法,则把c赋值给tokenString字符数组。

如果state为DONE,说明读取结束,并把终结符赋给tokenString字符数组,再判断currentToken是否为ID,如果是,则调用reservedLookup函数查看标识符是否为保留字。

然后判断TraceScan是否为真,如果为真,则将token信息打印到列表文件,最后把currentToken返回。

然后我们来观察util.h和util.c文件,它们是作为词法单元输出程序。

比较重要的是printToken函数,它被词法分析程序scan.c调用,用来输出所识别到的词法单元的内容以及词素。

最后我们来观察main.c文件,它则是作为编译器入口,其中设置了编译选项,从中读取文件,然后传递给词法分析器。

2. 实现拓展语言TINY+的词法分析器

下面,我们基于以上的知识与TINY词法分析器,来实现TINY+的词法分析器。

首先要添加识别下图红框中新的关键字。

我们在Global.h中的枚举类型TokenType中添加新的关键字,如下图所示。

其中因为TRUE和FALSE已经被define了,所以要换成TRUE1和FALSE1来表示。

这里我们还要修改MAXRESERVED的值到正确的数量,否则程序会出问题。

接下来修改scan.c中的reservedWords,添加新的关键字。如下图所示。

然后还要修改util.c中的printToken函数,添加新的关键字对应的case。如下图所示。

至此,我们完成了对新的关键字的添加。

下面我们添加识别下图红框中新的系统特殊字符。

我们同样在Global.h中的枚举类型TokenType中添加新的系统特殊字符GT(>)、LE(<=)、GE(>=)、COMMA(,)、UPDOX(')、PERCENT(%)、DOUBLETIMES(**),如下图所示。

对于单个字符组成且没有特殊情况的系统特殊字符,我们可以直接在scan.c中的getToken函数添加对该特殊字符的判断。如下图:

然后因为词法分析器是以最长匹配为原则,而要添加的系统特殊字符中有1个符号以上组成的特殊字符(<=,>=,**),所以我们的词法分析器要对这些情况进行额外判断,修改scan.c中的枚举类型StateType,添加新的状态INLT,INGT,INTIMES。

而上引号(')因为涉及到字符串常量STR,所以也要额外进行判断,添加新的状态INUPDOX。

下面在scan.c中的getToken函数添加在state为start状态时对最长匹配原则的判断。

接着在下方添加对新的状态的判断。如果读到了下一个符号,说明这是一个由2个符号组成的系统特殊字符,如果没读到,则说明这是单个系统特殊字符,调用ungetNextChar函数回退一个字符并把该单个系统特殊字符返回。

然后还要修改util.c中的printToken函数,添加新的特殊字符对应的case。

至此,我们完成了对新的系统特殊字符的添加。

下面我们添加识别下图红框中变量ID的规则。原本的词法分析器对于ID只有对字母alpha的判断,因此要实现 TINY+语言的词法我们需要添加对数字digit的判断。

然后我们只需在scan.c中的getToken函数,在state为INID状态时添加对数字的判断就行了。

下面我们添加识别字符串常量STR, 对于TINY+语言     ,STR是由两个上引号(')加上中间任意字符除去上引号组成的,并且不会多于一行。

我们先在scan.c中的getToken函数添加在state为start,读到上引号的情况。

接着如果读到下一个上引号,那么这就是一个字符串常量STR,如果这一行结束前还没读到下一个上引号,则代表语法错误,把出错消息和出错状态返回。

最后修改util.c中的printToken函数,添加字符串常量STR对应的case。

接下来我们来完善词法分析器,识别其他词法错误。

对于TINY+语言,注释部分是可以多于一行但不能嵌套的。下面来添加识别注释的右部括号丢失与匹配错误。

非法字符,即不属于TINY+字母表的字符,如果词法分析器识别到一个非法字符,则输出对应的出错信息,也就是在state为start状态时对字符的判断会去到default阶段,我们在这里加上出错消息。

TINY+字母表的字符中,有符号":="却没有符号":",所以如果识别到":"之后没有读到"=",那么这就是语法错误了。我们在对应的状态加上对错误的判断与错误信息。

至此,我们完成了对拓展语言TINY+的词法分析器的实现,下面我们来对词法分析器进行测试。

提供的测试代码:

tiny+1.txt

tiny+2.txt

自己编写测试文件:

tiny+_bugTest.txt

对所有的可能错误情况都进行了测试,可以看到错误信息正确给出。

四、实验结论或心得体会

顺利的完成了实验,通过这次实验,我学习和掌握了Tiny的词法分析器以及词法分析程序的构造,并根据以上知识完成了对拓展语言TINY+的词法分析器的实现,在词法分析器加入识别词法错误。总的来说是一次不错的体验。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值