实验一 词法分析程序实验
实验一、词法分析程序实验
商业软件工程 蓝海鹏 201506110171
一、 实验目的
编制一个词法分析程序。
二、 实验内容和要求
实验内容:
- 对字符串表示的源程序
- 从左到右进行扫描和分解
- 根据词法规则:
单词符号 |
种别码 |
单词符号 |
种别码 |
begin |
1 |
: |
17 |
if |
2 |
:= |
18 |
then |
3 |
< |
20 |
while |
4 |
<= |
21 |
do |
5 |
<> |
22 |
end |
6 |
> |
23 |
l(l|d)*(标识符) |
10 |
>= |
24 |
dd*(整数) |
11 |
= |
25 |
+ |
13 |
; |
26 |
- |
14 |
( |
27 |
* |
15 |
) |
28 |
/ |
16 |
# |
0 |
- 识别出一个一个具有独立意义的单词符号
- 以供语法分析之用
- 发现词法错误,则返回出错信息。
实验要求:
输入:源程序字符串
输出:二元组(种别,单词符号本身)
三、 实验方法、步骤及结果测试
- 1. 源程序名:压缩包文件(rar或zip)中
源程序名: 171蓝海鹏.c
可执行程序名:171蓝海鹏.exe
- 2. 原理分析及流程图
1) 存储结构:一维顺序数组存储。
2) 算法关键定义:
01. 定义全局变量syn存放单词种别码
02. 定义数组prog存放整个字符串,数组token存放临时字符串
03. 定义数组keyword存放关键字
3) 流程图:
4) 关键函数的实现:
//获取字符串比较返回种别码
void scaner()
{
for(n=0;n<8;n++)//初始化token数组
{token[n]='\0';}
n=0;
ch=prog[p++];
while(ch==' ')
{ch=prog[p++];}
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))//判断输入的是否为关键字
{
do{
token[n++]=ch;
ch=prog[p++];
}while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9'));
syn=10;
for(n=0;n<6;n++) //在六个关键字中对比
{
if(strcmp(token,keyword[n])==0)
syn=n+1;
}
p--;
}
else if(ch>='0'&&ch<='9')//判断输入的是否为整数常数
{
p--;
do
{
token[n++]=prog[p++];
ch=prog[p];
}while(ch>='0'&&ch<='9');
syn=11;
return;
}
else
{
switch(ch)
{
case '+':syn=13;token[0]=ch;break;
case '-':syn=14;token[0]=ch;break;
case '*':syn=15;token[0]=ch;break;
case '/':syn=16;token[0]=ch;break;
case ':':syn=17;token[0]=ch;
ch=prog[p++];
if(ch=='='){token[1]=ch;syn++;}
else p--;
break;
case '<':syn=20;token[0]=ch;
ch=prog[p++];
if(ch=='>'){token[1]=ch;syn++;}
else if(ch=='='){token[1]=ch;syn=syn+2;}
else p--;
break;
case '>':syn=23;token[0]=ch;
ch=prog[p++];
if(ch=='='){token[1]=ch;syn++;}
else p--;
break;
case '=':syn=25;token[0]=ch;break;
case ';':syn=26;token[0]=ch;break;
case '(':syn=27;token[0]=ch;break;
case ')':syn=28;token[0]=ch;break;
case '#':syn=0;token[0]=ch;break;
default: printf("词法分析出错! 请检查是否输入非法字符\n");syn=-1;break;
}
}
}
- 3. 主要程序段及其解释:
源代码:
#include <stdio.h> #include <stdlib.h> #include <string.h> #define SIZE 100 int p=0,syn,n,i; //syn用于记录种别码,其为全局变量 char prog[SIZE],ch,token[8]; char *keyword[6]={"begin","then","if","while","do","end"};//定义关键字数组 void scaner(); //将prog数组中的数移到token数组进行比较,更新种别码 main() { p=0; printf("请输入源程序字符串(以'#'结束):\n"); do { ch=getchar(); prog[p++]=ch; }while(ch!='#');//将键盘输入的字符串录入数组prog p=0; do { scaner(); switch(syn) { case -1:printf("词法分析 出错\n");break; default :printf("<%d,%s>\n",syn,token);break; } }while(syn!=0);//输入#号,种别码syn为0,循环结束 printf("词法分析 成功\n"); getchar(); } void scaner() { for(n=0;n<8;n++)//初始化token数组 {token[n]='\0';} n=0; ch=prog[p++]; while(ch==' ') {ch=prog[p++];} if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))//判断输入的是否为关键字 { do{ token[n++]=ch; ch=prog[p++]; }while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')); syn=10; for(n=0;n<6;n++) //在六个关键字中对比 { if(strcmp(token,keyword[n])==0) syn=n+1; } p--; } else if(ch>='0'&&ch<='9')//判断输入的是否为整数常数 { p--; do { token[n++]=prog[p++]; ch=prog[p]; }while(ch>='0'&&ch<='9'); syn=11; return; } else { switch(ch) { case '+':syn=13;token[0]=ch;break; case '-':syn=14;token[0]=ch;break; case '*':syn=15;token[0]=ch;break; case '/':syn=16;token[0]=ch;break; case ':':syn=17;token[0]=ch; ch=prog[p++]; if(ch=='='){token[1]=ch;syn++;} else p--; break; case '<':syn=20;token[0]=ch; ch=prog[p++]; if(ch=='>'){token[1]=ch;syn++;} else if(ch=='='){token[1]=ch;syn=syn+2;} else p--; break; case '>':syn=23;token[0]=ch; ch=prog[p++]; if(ch=='='){token[1]=ch;syn++;} else p--; break; case '=':syn=25;token[0]=ch;break; case ';':syn=26;token[0]=ch;break; case '(':syn=27;token[0]=ch;break; case ')':syn=28;token[0]=ch;break; case '#':syn=0;token[0]=ch;break; default: printf("词法分析出错! 请检查是否输入非法字符\n");syn=-1;break; } } }
- 4. 运行结果及分析
分析:
第1个字符串是关键字,顺序第1输出二元组(1,begin);
第2个字符串是标识符,因为关键字为小写,其不为关键字,输出二元组(10,BEGIN);
第3个字符串是由字母和数字组成的标识符,输出二元组(10,lan171);
第4个字符串是整数,输出二元组(11,10);
第5个字符串是符号,输出二元组(13,+);
第6个字符串是结束,输出二元组(0,#);
四、 实验总结
刚刚接触编译原理这门课,其实很多概念不懂,课上也没有认真听课,这就做了一个实验,其实已经有了充足的时间准备。
- 通过本次实验,对词法分析程序的开发有了一定的认识;
- 在这次实验中,我对以前学习的C语言知识有了更深刻的认识。
问题:在“读下一个字符“的时候遇到少读或多读一个字符的情况。
(解决:通过多次调试将读字符的每种情况都考虑)