当前位置:文档之家› 编译原理实验报告2-词法分析程序的设计

编译原理实验报告2-词法分析程序的设计

实验2 词法分析程序的设计一、实验目的掌握计算机语言的词法分析程序的开发方法。

二、实验内容编制一个能够分析三种整数、标识符、主要运算符和主要关键字的词法分析程序。

三、实验要求1、根据以下的正规式,编制正规文法,画出状态图;标识符<字母>(<字母>|<数字字符>)*十进制整数0 | ((1|2|3|4|5|6|7|8|9)(0|1|2|3|4|5|6|7|8|9)*)八进制整数0(1|2|3|4|5|6|7)(0|1|2|3|4|5|6|7)*十六进制整数0x(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)(0|1|2|3|4|5|6|7|8|9|a|b|c|d|e|f)*运算符和界符+ - * / > < = ( ) ;关键字if then else while do2、根据状态图,设计词法分析函数int scan( ),完成以下功能:1)从文本文件中读入测试源代码,根据状态转换图,分析出一个单词,2)以二元式形式输出单词<单词种类,单词属性>其中单词种类用整数表示:0:标识符1:十进制整数2:八进制整数3:十六进制整数运算符和界符,关键字采用一字一符,不编码其中单词属性表示如下:标识符,整数由于采用一类一符,属性用单词表示运算符和界符,关键字采用一字一符,属性为空3、编写测试程序,反复调用函数scan( ),输出单词种别和属性。

四、实验环境PC微机DOS操作系统或Windows 操作系统Turbo C 程序集成环境或Visual C++ 程序集成环境五、实验步骤1、根据正规式,画出状态转换图;2、根据状态图,设计词法分析算法;观察状态图,其中状态2、4、7、10(右上角打了星号)需要回调一个字符。

声明一些变量和函数:ch: 字符变量,存放最新读进的源程序字符。

strToken: 字符串变量,存放构成单词符号的字符串。

GetChar(): 子函数,将下一输入字符读到ch中,搜索指示器前移一字符位置。

GetBC(): 子函数,检查ch中的字符是否为空白。

若是,则调用GetChar()直至ch 中进入一个非空白字符。

Concat(): 子函数,将ch中的字符连接到strToken之后。

IsLetter(): 布尔函数,判断ch中的字符是否为字母。

IsDigit(): 布尔函数,判断ch中的字符是否为数字。

Reserve(): 整型函数,对strToken中的字符串查找保留字表,若它是一个保留字则返回它的编码,否则返回0。

SearchOp(): 整型函数,对ch查找运算符和界符,若它是一个运算符或界符,则返回它的编码,否则返回0。

Retract(): 子函数,将搜索指示器回调一个字符位置,将ch置为空白字符。

ProError(): 错误处理函数。

关键字保存在字符数组中,定义编码为相对数组首地址的位置+ 1。

保留子表顺序如下:{ if ,then ,else ,while, do } ,则相应编码为:1,2,3,4,5。

运算符和界符保存在字符数组中,编码定义与关键字相同,顺序如下:{ + ,- , * , / , > , < , = , ( , ) , ;},编码为:1~10。

二元表算法如下:ch=’‘ ; strToken=””;GetBC();if(IsLetter()) {while(IsLetter() || IsDigit()){ Concat(); GetChar(); }Retract();If(Reserve()) printf("<%s , ->", strToken);else printf("<,0,%s >", strToken);}else if(‘1’ < =ch && ch <=’9’) {while(IsDigit()){ Concat(); GetChar(); }Retract();printf("<,1,%s >", strToken) ;}else if(ch==’0’) {GetChar();if(ch >= ‘1’ && ch <= ‘7’) {while(ch >= ‘0’ && ch <= ‘7’){ Concat(); GetChar(); }Retract();printf("<,2,%s >", strToken) ;}else if(ch==’x’) {GetChar();while(IsDigit() || ch>= ‘a’ && ch<=’f’){ Concat(); GetChar(); }Retract();printf("<,3,%s >", strToken);}else {Retract();printf(“<1,0> “) ;}}else if(SearchOp()) printf("<%c,- >", ch);else ProError();3、采用C或C++语言,设计函数scan( ),实现该算法;char GetChar(FILE* fp) { //读取文件中的一个字符char ch;ch = fgetc(fp);return ch;}char GetBC(FILE* fp) { //读取文件的字符直至ch不是空白char ch;do {ch = GetChar(fp);} while (ch == ' ' || ch == '\t' || ch == '\n');return ch;}void Concat(char ch ,char strToken[]) { //将ch中的字符连接到strToken之后char str[2];str[0] = ch;str[1] = '\0';strcat(strToken,str);}int IsLetter(char ch) { //布尔函数,判断ch中的字符是否为字母,是返回1,否则返回0int flag = 0;if (ch >= 'a' && ch <= 'z')flag = 1;return flag;}int IsDigit(char ch) { //布尔函数,判断ch中的字符是否为数字,是返回1,否则返回0int flag = 0;if (ch >= '0' && ch <= '9')flag = 1;return flag;}int Reserve(char strToken[]) { //整型函数,对strToken中的字符串查找保留字表,若它是一个保留字则返回它的编码,否则返回0int code = 0,i;char keyWord[6][6] = { "if", "then", "else", "while", "do" };for (i = 0; i < 5; i++) {if (strcmp(strToken, keyWord[i]) == 0) {code = i + 1;break;}}return code;}int SearchOP(char ch) { //整型函数,对strToken中的字符串查找运算符和界符,若它是一个运算符或界符,则返回它的编码,否则返回0int code = 0, i;char OP[11] = { '+', '-', '*', '/', '<', '>', '=', '(', ')', ';' };for (i = 0; i < 10; i++) {if (ch == OP[i]) {code = i + 1;break;}}return code;}char Retract(FILE* fp,char ch) { //子函数,将搜索指示器回调一个字符位置,将ch置为空白字符ch = ' ';fseek(fp, -1L, 1);return ch;}void ProError( ) { //错误处理函数printf("输入错误!\n");return;}FILE* scan(FILE* fp) { //输出单个二元式char ch;char strToken[10];strToken[0] = '\0'; //置strToken为空串ch = GetBC(fp); //先读取一个非空白的字符if (feof(fp)) return fp; //判断文件尾,是则返回调用程序if (IsLetter(ch)) { //判断标识符while (IsLetter(ch) || IsDigit(ch)) {Concat(ch, strToken);ch = GetChar(fp);}ch = Retract(fp,ch);if (Reserve(strToken)) { //判断关键字printf("<%s,->\n", strToken);}elseprintf("<0,%s>\n", strToken);}else if (ch >= '1' && ch <= '9') { //判断十进制整数while (IsDigit(ch)) {Concat(ch, strToken);ch = GetChar(fp);}ch = Retract(fp, ch);printf("<1,%s>\n", strToken);}else if (ch == '0') {ch = GetChar(fp);if (ch >= '1' && ch <= '7') { //判断八进制整数while (ch >= '0' && ch <= '7') {Concat(ch, strToken);ch = GetChar(fp);}ch = Retract(fp, ch);printf("<2,%s>\n", strToken);}else if (ch == 'x') { //判断十六进制整数ch = GetChar(fp);while (IsDigit(ch) || ch >= 'a' && ch <= 'f') {Concat(ch, strToken);ch = GetChar(fp);}ch = Retract(fp, ch);printf("<3,%s>\n", strToken);}else { //判断十进制的0ch = Retract(fp, ch);printf("<1,0>\n");}}else if (SearchOP(ch)) { //判断运算符和界符printf("<%c,->\n", ch);}else { //出错ProError();}return fp;}4、编制测试程序(主函数main);#include<iostream>using namespace std;#define NULL 0int main( ) {FILE* fp;if ((fp = fopen("C:\\Users\\Administrator\\Desktop\\Code.txt", "r")) == NULL) { //以只读方式打开文件,失败则退出程序printf("file can not open!");exit(0);}printf("词法分析结果如下:\n");while (!feof(fp)) { //若不是文件尾则执行循环fp = scan(fp); //输出单词种类、属性的二元式}fclose(fp); //关闭文件fp = NULL; //避免指向非法内存}5、调试程序:读入文本文件,检查输出结果。

相关主题