设计目的:
1、 理解有限自动机的作用
2、 利用转态图和状态表表示有限自动机 3、 以程序实现有限自动机的运行过程
设计内容:(注:题目详细要求)
利用状态表和有限自动机的运行原理编制程序,使得程序能够识别一个输入串是否为一个有效的符号串,具体可以选择下面之一:无符号定点实数、自然数、整数、十六进制数或其它自己定义的符号串。
一、分析原理
词法分析:就是从左至右逐个字符地对源程序进行扫描,产生单词序列,用以语法分析。 在这里,我们先把文法转换成有穷自动机,然后构造出状态表,再由状态表构造出程序。
二、分析的算法
将G[<无符号数>]文法转换成有穷自动机:
构造状态矩阵;将有穷自动机的状S1 S2 ??Sn及输入的字a1 a2 ??am 构成一个n*m的矩阵。
输入 状态 0 1 d 1 1 . 2 2 e 4 4 +/- ε Z 1
2 3 4 5 6 Z 3 3 6 6 6 4 Z Z 5 再写一个程序,把状态矩阵用二维数组表示。程序通过输入的字符转换状态,从而可以识别出单词。
本程序的关键在状态表和缓冲区的运用。首先定义了一个布尔型函数ReadALine把输入的字符串送到缓冲区中;然后定义了布尔型函数Run 和Getchar实现对输入字符串的正确性判断,更改Run函数可以改变程序功能:如可将状态表改变成识别“偶数”的有限自动机的状态表。
三、程序流程图
2
开始初始化输入句子判断是否退出标志N判断是否被接受?YN接受Y不接受输出错误位置结束 四、课程设计出现的问题及解决的方法
刚开始写该程序时,虽然感觉个人的编程能力不错,但由于对编译原理的自动机的实现掌握不足,难以入手。但经过对问题的更深入了解和分析,再通过网上和书本的资料的细读,最后终于把程序编写出来了。程序中,碰到的最大的问题就是状态表的构造和如何把它转变为一个程序的实现过程。解决的方法当然是看书。
五、课程设计的体会
首先,题目给出的文法是有小毛病的。我个人认为<无符号数>不可能推出 . <十进制数> 或者
3
e <指数部分>的。在写这个程序是只要对编译原理书本词法分析分析很熟悉就可以比较容易地写出该程序。通过这次课程设计,我对程序的编译和运行有了更进一步的了解,更好地掌握了编译原理的词法分析过程。
六、程序清单
#include
//状态表相关存储信息:
#define STATE_NUMBER 7 //状态数目
#define CHAR_NUMBER 4 //输入字符的种类: . ; d ; e/E ; +/- #define DOT 0 //输入数字在状态表中位于第0列 #define DIGIT 1 //小数点位于状态表的第1列 #define E 2 //E位于状态表的第2列
#define AD 3 //+/-运算符位于状态表的第3列
//State[][]为状态表,以整数组形式存放,0,1,2,3,4,5,6表示状态,-1表示没有此状态 int State[STATE_NUMBER][CHAR_NUMBER]= { };
int Q[STATE_NUMBER] = {0,0,1,0,1,1,0}; //终态标志:0非终态,1终态。 int index=0;//错误坐标
//缓冲区:
//输入缓冲区:由专门函数操作(ReadALine(),GetChar()) #define BUFFER_SIZE 1000 //表达式缓冲区大小
char Buffer[BUFFER_SIZE]; //表达式缓冲区,以'\\0'表示结束 int ipBuffer = 0; //表达式缓冲区当前位置序号 char ch; //存放取得的一个字符
//函数声明:
int Run(); //对存储在缓冲区的一行字符串(以'#'结束)进行运行 void Init(); //全局初始化
int ReadALine(); //从键盘读一行(没有空格),存于表达式缓冲区Buffer[]中 char GetChar(); //从缓冲区取一个字符,返回该字符的同时将它存于全局变量ch中
4
{1,2,3,-1}, {-1,4,-1,-1}, {1,2,3,-1}, {-1,5,-1,6}, {-1,4,3,-1}, {-1,5,-1,-1}, {-1,5,-1,-1}
//主程序: void main() {
Init();
while(ReadALine()) //读一行成功,对它进行判断 {
if(Run()) //对该行进行运行,看是否能被接受? printf(\接受\\n\\n\ else }
//对存储在缓冲区的一行字符串(以'#'结束)进行运行 //返回:如果是无符号定点实数,返回true;否则返回:false int Run() {
int S=0; //S存放运行时的当前状态,目前为初态
index=0;
while(GetChar()!='#') {
index++;
if(ch >= '0' && ch <= '9') //数字
S = State[S][DIGIT]; //将状态转换成输入数字后的状态 else if(ch == '.') //小数点
S = State[S][DOT]; //将状态转换成输入小数点后的状态
else if(ch == 'e'||ch == 'E') //e
S = State[S][E]; //将状态转换成输入e后的状态 S = State[S][AD]; //将状态转换成输入+或-后的状态 return 0;
else if(ch == '+'||ch == '-') //+或-符号 else if(ch == NULL )
{ }
printf(\不接受\\n\
printf(\错误位置在第%d个字符!\\n\\n\//显示错误位置
}
else //其他都为非法字符 return 0;
if(S == -1) //处于非法状态 return 0; }
//运行结束,判断S是否为终态 if(Q[S] == 1) //终态 return 1; else //非终态 return 0; }
5