实验一、词法分析程序实验
专业:商软二班 姓名:朱小彬 学号:201506110050
一、实验目的
编制一个词法分析程序。
二、实验内容和要求
实验内容:输入一段字符串,从字符串表示的源程序中识别出具有独立意义的单词符号,根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
实验要求:输入:源程序字符串;
输出:二元组(种别,单词本身);
待分析语言的词法规则。
三、 实验方法、步骤及结果测试
1. 源程序名:cifafenxi.c
可执行程序名:cifafenxi.exe
2. 原理分析及流程图
设置3个初值变量和一个关键字表:
1) char token[8] 用来存放构成单词符号的字符串;
2) double sum 用来存放无符号整数或者浮点数;
3) int syn 用来存放单词符号的种别码;
关键字表: char *rwtab[6]={“begin”,”if”,”then”,”while”,”do”,”end”};
设置重要的全局变量:
1) char ch 用来存放当前镀金的源程序字符;
2) char prog[80] 用来存放所有用户输入的字符;
3) int isDecimal 是否为浮点数,值为1表示为浮点数,否则不是浮点数
4) double decimal 双精度,浮点数的小数部分
5) int isE 是否为指数形式表示的浮点数,值为1:表示是指数形式表示的浮点数
6) int index 指数形式的幂
7) int isNeg 是否为负数幂,值为1:表示为负数幂
设置关键的函数:
void scanner() 词法扫描程序
getchar() 从控制台读取一个字符数据
int strcmp( char *str1,char *str2),字符串的比较
double pow( double x,double y) 计算x的y次幂
流程:
1) 记录下输入的源程序字符串
2) 调用scanner()函数对字符串进行各种关键字、运算符和界符、数字的扫描匹配,并且给出相应的种别码,输出单词二元组
3. 主要程序段及其解释:
1. getchar() 该函数用来接收用户输入:
借助do……while()循环来记录用户输入的源程序字符串
do{
ch = getchar(); //将用户输入的字符读入到ch变量中
prog[p++] = ch; //将字符存于数组中
}while(ch != ‘#’); //当用户输入’#’号时,结束输入。
2. scanner() 该函数用来扫描源程序字符串并进行区别分类
1) 如果是字母字符,则进行关键字的匹配:
if(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))) //ch是字母字符
{
while(((ch>='a')&&(ch<='z'))||((ch>='A')&&(ch<='Z'))||((ch>='0')&&(ch<='9')))
{
token[m++]=ch; //ch=>token 以便进行关键字的匹配
ch=prog[p++]; //读下一个字符
}
token[m++]=' ';
p--; //回退一格
syn=10; //标识符
//判断是否是"begin","if","then","while","do","end"标识符中的一个
for(n=0;n<6;n++)
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
2) 对数字进行判断,并且进行数值的计算:
else if((ch>='0')&&(ch<='9')) //对数字进行识别
{
IsNum: //在此处设置一个goto的标识符以便实现“数字识别代码段”的复用
if(isSignal==1)
{
//token[m++]='-';
}
while((ch>='0')&&(ch<='9'))
{
sum=sum*10+ch-'0'; //ch中数字本身是当做字符存放的
ch=prog[p++];
}
if(ch=='.')
{
isDecimal=1;
ch=prog[p++];
while((ch>='0')&&(ch<='9'))
{
//pow(x,y)计算x的y次幂
temp=(ch-'0')*pow(0.1,++count);
decimal=decimal+temp;
//AddToDec();
ch=prog[p++];
}
sum=sum+decimal;
}
if(ch=='e'||ch=='E')
{
isExp=1;
ch=prog[p++];
if(ch=='-')
{
isNegative=1;
ch=prog[p++];
}
while((ch>='0')&&(ch<='9'))
{
//指数
index=index*10+ch-'0';
ch=prog[p++];
}
//10的幂
//123e3代表123*10(3)
if(isNegative)
sum=sum*pow(0.1,index);
else
sum=sum*pow(10,index);
}
if(isSignal==1)
{
sum=-sum;
isSignal=0;
}
p--;
syn=11;
}
3) 对界符和运算符进行判断:
else switch(ch)
{
case '<':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='>')
{
syn=21; //<>对应21
token[m++]=ch;
}
else if(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
{
syn=20;
p--;
}
break;
case '>':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=24;
token[m++]=ch;
}
else
{
syn=23;
p--;
}
break;
case ':':
m=0;
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=18;
token[m++]=ch;
}
else
{
syn=17;
p--;
}
break;
case '+':
temp2=prog[p];
if((temp2>='0')&&(temp2<='9'))
{
isSignal=2;
ch=prog[p++];
goto IsNum;
}
syn=13;
token[m++]=ch;
break;
case '-':
temp2=prog[p];
if((temp2>='0')&&(temp2<='9'))
{
isSignal=1;
ch=prog[p++];
goto IsNum; //转到数字的识别
}
syn=14;
token[m++]=ch;
break;
case '*':
syn=15;
token[m++]=ch;
break;
case '/':
syn=16;
token[m++]=ch;
break;
case '=':
syn=25;
token[m++]=ch;
break;
case ';':
syn=26;
token[m++]=ch;
break;
case '(':
syn=27;
token[m++]=ch;
break;
case ')':
syn=28;
token[m++]=ch;
break;
case'#':
syn=0;
token[m++]=ch;
break;
default:
syn=-1;
}
}
4. 运行结果及分析
符合实验内容以及要求,能识别出输入字符串所对应的单词符号。
四、实验总结
刚开始入门,对于程序不知道如何下手,好长时间都没有思路,后查询相关的资料以及相应的代码后,慢慢理解分析,最终写出实验报告。