单词符号种别识别程序设计.docx
《单词符号种别识别程序设计.docx》由会员分享,可在线阅读,更多相关《单词符号种别识别程序设计.docx(20页珍藏版)》请在冰豆网上搜索。
![单词符号种别识别程序设计.docx](https://file1.bdocx.com/fileroot1/2022-10/11/8e5a2181-83b9-4185-a7ba-4c0ac385622d/8e5a2181-83b9-4185-a7ba-4c0ac385622d1.gif)
单词符号种别识别程序设计
实验二单词符号种别识别程序设计
一、实验目的
通过C语言词法分析程序的实现理解编译程序过程中词法分析对单词的种别识别过程。
二、实验重难点
单词识别
三、实验内容与要求
1.阅读教材P2-P3词法分析部分内容,明确词法分析的任务。
2.阅读实验案例,明确实验要求、模块流程图和程序实现方案;
3.参考实验案例,完成简单的词法分析程序设计。
四、实验学时
4课时
五、实验设备与环境
C语言编译环境
六、实验案例
1.待分析的简单的词法
(1)关键字:
beginifthenwhiledoend
所有的关键字都是小写。
(2)运算符和界符
:
=+-*/<<=<>>>==;()#
(3)其他单词是标识符(ID)和整型常数(SUM),通过以下正规式定义:
ID=letter(letter|digit)*
NUM=digitdigit*
(4)空格由空白、制表符和换行符组成。
空格一般用来分隔ID、SUM、运算符、界符和关键字,词法分析阶段通常被忽略。
2.各种单词符号对应的种别码见表6.1:
表6.1各种单词符号对应的种别码
单词符号
种别码
单词符号
种别码
begin
1
:
17
if
2
=
18
then
3
<
20
while
4
!
=
21
do
5
<=
22
end
6
>
23
{
7
>=
24
}
8
==
25
++
9
;
26
lettet(letter|digit)*
10
(
27
dightdight*
11
)
28
+
13
--
29
-
14
\
30
*
15
!
31
/
16
#
0
3.词法分析程序的功能:
输入:
所给文法的源程序字符串。
输出:
二元组(syn,token或sum)构成的序列。
其中:
syn为单词种别码;
token为存放的单词自身字符串;
sum为整型常数。
例如:
对源程序beginx:
=9;ifx>9thenx:
=2*x+1/3;end#的源文件,经过词法分析后输出如下序列:
(1,begin)(10,x)(18,:
=)(11,9)(26,;)(2,if)……
4.词法分析程序的算法思想:
算法的基本任务是从字符串表示的源程序中识别出具有独立意义的单词符号,其基本思想是根据扫描到单词符号的第一个字符的种类,拼出相应的单词符号。
(1)主程序示意图:
主程序示意图如图6-1所示。
其中初值包括以下两个方面:
Ø关键字表的初值:
关键字作为特殊标识符处理,把它们预先安排在一张表格中(称为关键字表),当扫描程序识别出标识符时,查关键字表。
如能查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表为一个字符串数组,其描述如下:
Char*rwtab[6]={“begin”,“if”,“then”,“while”,“do”,“end”,};
否
是
图6-1主程序流程图
Ø程序中需要用到的主要变量为syn,token和sum
(2)扫描子程序的算法思想:
首先设置3个变量:
①token用来存放构成单词符号的字符串;②sum用来存放整型单词;③syn用来存放单词符号的种别码。
扫描子程序主要部分流程如图6-2所示。
是
否
字母
数字其他
运算符、符号
界符等符号
否
是
图6-2扫描子程序算法流程图
5.词法分析程序的C语言程序源代码:
#include
#include
#include
#include
#include
#include
charprog[80],ch;
intp,m,n;
chartoken[8];
intsyn,sum;
char*rwtab[6]={"begin","if","then","while","do","end"};//关键字表初始化
scaner();//声明一个函数名为scanser()的子函数
main()
{p=0;
printf("\npleaseinputastring(endwith'#'):
\n");
do{
scanf("%c",&ch);//用%c控制输入则空格等表示有效输入,用%S控制,空格等表示输入结束
prog[p++]=ch;
}while(ch!
='#');//遇到“#”,输入结束
p=0;
do{
scaner();
switch(syn)
{case11:
printf("(%-10d%5d)\n",sum,syn);
/*种别为数字时;%-10d:
表示输出共占10位,%5d共占5位,右对齐左端补空格*/
break;
case-1:
printf("youhaveinputawrongstring\n");
getch();
exit(0);
default:
printf("(%-10s%5d)\n",token,syn);
break;
}
}while(syn!
=0);//“#”,syn=0
getch();
}
scaner()
{sum=0;
for(m=0;m<8;m++)token[m]=NULL;//token[8]赋初值为空,token存放待识别的单词
ch=prog[p++];
m=0;
while((ch=='')||(ch=='\n'))ch=prog[p++];//空格或回车,不用判断,直接进入下一个单词
/*如果这是一个字符串,拼字符串,判断种别码*/
if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))//如果首字母为字母,拼出完整字符串
{
/*lettet(letter|digit)判断后续字符是不是数字或字母,如果是就往下拼;如果不是,结束拼字符串*/
while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9')))
{token[m++]=ch;
ch=prog[p++];
}
p--;//使得prog[p]为下一个带处理的字符
syn=10;
/*查关键字表,进一步判断这个字符串是标识符还是关键字*/
for(n=0;n<6;n++)
if(strcmp(token,rwtab[n])==0)
{syn=n+1;
break;
}
}
/*如果这是一个数串,拼数,判断种别码*/
elseif((ch>='0')&&(ch<='9'))
{while((ch>='0')&&(ch<='9'))
{sum=sum*10+ch-'0';
ch=prog[p++];
}
p--;
syn=11;
}
/*如果这是一个界符、运算符,判断种别码*/
elseswitch(ch)
{/*如果是<打头,判断是<还是<=*/
case'<':
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{syn=22;
token[m++]=ch;
}
else
{syn=20;
p--;
}
break;
/*如果是>打头,判断是<还是>=*/
case'>':
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{syn=24;
token[m++]=ch;
}
else
{syn=23;
p--;
}
break;
/*如果是+打头,判断是+还是++*/
case'+':
token[m++]=ch;
ch=prog[p++];
if(ch=='+')
{syn=9;
token[m++]=ch;
}
else
{syn=13;
p--;
}
break;
/*如果是-打头,判断是-还是--*/
case'-':
token[m++]=ch;
ch=prog[p++];
if(ch=='-')
{syn=29;
token[m++]=ch;
}
else
{syn=14;
p--;
}
break;
/*如果是!
打头,判断是!
=还是!
*/
case'!
':
ch=prog[p++];
if(ch=='=')
{syn=21;
token[m++]=ch;
}
else
{syn=31;
p--;
}
break;
/*如果是=打头,判断是==还是=*/
case'=':
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{syn=25;
token[m++]=ch;
}
else
{syn=18;
p--;
}
break;
case'*':
syn=15;
token[m++]=ch;
break;
case'/':
syn=16;
token[m++]=ch;
break;
case'(':
syn=27;
token[m++]=ch;
break;
case')':
syn=28;
token[m++]=ch;
break;
case'{':
syn=7;
token[m++]=ch;
break;
case'}':
syn=8;
token[m++]=ch;
break;
case';':
syn=26;
token[m++]=ch;
break;
case'\"':
syn=30;
token[m++]=ch;
break;
case'#':
syn=0;
token[m++]=ch;
break;
case':
':
syn=17;
token[m++]=ch;
break;
default:
syn=-1;
break;
}
token[m++]='\0';//给字符串加上字符串结束标志
}
6.结果分析:
输入beginx:
=9;ifx>9thenx:
=2*x+1/3;end#后经词法分析输出如下序列:
(begin1)(x10)(:
17)(=18)(911)(;26)(if2)……如图6-3所示:
图6-3
七、简单的词法分析程序的设计
1.ThedefinitionofPofaprovidedcontext-freegrammarisasbelow:
P={
<标识符>→<字母><字母数字串>
<字母数字串>→<字母><字母数字串>|<数字><字母数字串>|<下划线><字母数字串>|ε
<无符号整数>-→<数字><数字串>
<数字串>→<数字><数字串>|ε
<加法运算符>→+
<减法运