编译原理实验词法分析Word文件下载.docx
《编译原理实验词法分析Word文件下载.docx》由会员分享,可在线阅读,更多相关《编译原理实验词法分析Word文件下载.docx(15页珍藏版)》请在冰豆网上搜索。
运算符:
+-*/()
常数:
十进制实数
十进制整数
十六进制实数
十六进制整数
八进制实数
八进制整数
1.实验目的
实现一个词法分析程序,将输入字符串流分解成
单词流供语法分析使用。
2.实验要求
输入算术运算式,输出分解后的单词流,例如:
输入(0124.3+0x35a.4f)*12
输出:
运算符(
八进制实数0124.3
运算符+
十六进制实数0x35a.4f
运算符)
运算符*
十进制整数12
注意:
●输入可以是键盘输入,也可以是文件输入
●如果单词输入错误,必须有提示,例如:
输入12a+45*013468-0x23a3
输出
错误数据12a
运算符+
十进制整数45
运算符*
错误数据0123468
运算符-
十六进制整数0x23a3
//如(0124.3+0x35a.4f)*12
//如a+45*013468-0x23a3
#include<
string.h>
stdio.h>
//#include"
stdafx.h"
unionchars{//联合,可存储字符串,整型和浮点型
charpro_char[15];
intpro_number;
floatreal;
};
structdata{//将每个单元用一个结构来存储,其内容包括:
类型,所属的具体类型,以及属性值
charkind[7];
intid;
unioncharspro;
};
intscan(char*a);
//对每个用空格打断的单元进行进一步的分析,对其进行进一步的分类
voidPrints(chara[15],intid,inta_long);
//将分析后的每个token输出
voidsave(char*a,intid,intx);
//将分析后的结果保存到一个结构数组中
charnowChar[15];
//临时的存储单元,用来存储被空格打断以后单元
charkinds[11][8]={"
"
"
INT10"
INT8"
INT16"
IDN"
REAL10"
REAL8"
REAL16"
//单词的不同种别
structdatalink[100];
//用来存放词法分析以后的结果的结构数组
intlink_long=0;
//全局变量
intscan(char*a){
//intid;
inta_long=0;
intdoc=0;
while(*a!
=NULL){
nowChar[0]='
\0'
;
a_long=0;
doc=0;
//对数值的判断及处理
if('
0'
<
=*a&
&
*a<
='
9'
){//如果第一个字符为数值
nowChar[a_long]=*a;
*a++;
a_long++;
//对十六进制的判断及处理
if(nowChar[0]=='
(*a=='
x'
||*a=='
X'
))
{//如果第一个字符为0,且第二个字符为x,则为十六进制数
nowChar[a_long]=*a;
*a++;
a_long++;
=NULL&
(('
)||('
a'
f'
A'
F'
)||*a=='
.'
)){
//一直将此十六进制数完全读入,若为浮点型的,则加以标记
if(*a=='
)
doc=1;
}
nowChar[a_long]='
//判断输入的十六进制数是否合法
if(a_long==2)
{//输入的只有x,则输入错误
Prints(nowChar,7,a_long);
return0;
}
if(doc)//输入的十六进制数是浮点型的
Prints(nowChar,10,a_long);
//则将其具体的类型属性定为
else//输入的十六进制数是整型的
Prints(nowChar,3,a_long);
//则将其具体的类型属性定义为
continue;
}//对八进制的判断及处理
'
7'
)
{//如果第一个字符为0,且第二个字符,0~7,则为八进制数
)){
//一直将此八进制数完全读入,若为浮点型的,则加以标记
nowChar[a_long]='
if(doc)//输入的八进制数是浮点型的
Prints(nowChar,9,a_long);
else//输入的十六进制数是整型的
Prints(nowChar,2,a_long);
continue;
//对十进制数的判断及处理
else{
//一直将此十进制数完全读入,若为浮点型的,则加以标记
if(doc)//输入的十进制数是浮点型的
Prints(nowChar,8,a_long);
else//输入的十进制数是整型的
Prints(nowChar,1,a_long);
}//完成了对数值的判断及处理//对字符的判断及处理
nowChar[a_long]=*a;
//判断输入的字符是否为运算符或其他的分隔符
switch(nowChar[0]){
case'
+'
:
-'
*'
/'
>
case'
('
)'
Prints(nowChar,5,a_long);
//将其具体的类型属性定义为
default:
break;
}//判断输入的第一个字符是否为字母
if(('
=nowChar[0]&
nowChar[0]<
z'
Z'
while(*a!
)||(*a=='
_'
)))
{//一直将此字符串完全读入
//判断输入的字符串是否为特殊的标识符,若是,则将其具体类型值定义为
//判断输入的字符串是否为特殊的字符串if
if(a_long==2&
strcmp(nowChar,"
if"
)==0){
Prints(nowChar,6,a_long);
//判断输入的字符串是否为特殊的字符串then
if(a_long==4&
then"
//判断输入的字符串是否为特殊的字符串else
else"
//判断输入的字符串是否为特殊的字符串while
if(a_long==5&
while"
//判断输入的字符串是否为特殊的字符串do
do"
)==0){
Prints(nowChar,6,a_long);
//若输入的字符串不符合以上几种情况,则输入的为变量
//若输入的字符串为变量,则将其具体属性值定义为
Prints(nowChar,4,a_long);
//如果输入的既不是数值也不是字符串,则输入错误,将其具体类型之定义为
else{
Prints(nowChar,7,a_long);
return0;
}
}}
return1;
main(){
charbuf[100];
//用来存储从键盘上输入一串字符
char*tokenPtr;
//用来存储用空格打断后的单元
intid=1;
//用来存储具体的类型号
link_long=0;
while(id){
gets(buf);
//从键盘上输入一串字符
tokenPtr=strtok(buf,"
);
//用空格将字符串打断
while(id&
*tokenPtr!
=NULL){//分割出来的单元不为空
id=scan(tokenPtr);
//将此单元进行继续分析,并返回其具体的类型值
tokenPtr=strtok(NULL,"
//将字符串继续用空格进行分割
}}
printf("
\n\n"
getchar();
//将所分解后的单元存入结构数组中
voidsave(char*a,intid,intx,floaty){
inti;
if(link_long<
100){
link[link_long].id=id;
//将具体的类型值存入
if(id>
=5){if(id>
=8){//id=8,9,10
//若为浮点型的数值,则将浮点型的y值(转换后的)存入其属性当中且存入单词的种别
for(i=0;
i<
9&
kinds[id][i]!
i++)
link[link_long].kind[i]=kinds[id][i];
link[link_long].pro.real=y;
}//id=5,6,7
//若为标识符,则将单词种别定为自身,属性值定为空
for(i=0;
15&
a[i]!
link[link_long].kind[i]=a[i];
link[link_long].pro.pro_char[0]='
link[link_long].pro.pro_char[1]='
link_long++;
}//id=1,2,3,4
else{
8&
//若分解后的token为变量或者整型数值,则将其单词种别直接输出
if(id==4){//若token为变量,则将其属性值设为自身
for(i=0;
link[link_long].pro.pro_char[i]=a[i];
link[link_long].pro.pro_char[i]='
else//若token为整型数值,则将其相应的十进制数值赋给其属性值
link[link_long].pro.pro_number=x;
//继续存入下一个token
else
Full100\n"
//结构数组已经存满
return;
//将词法分析器分解后的结果输出出来
voidPrints(chara[15],intid,inta_long){
intx=0;
floaty=0;
//intfloat1;
//char*c;
if(id==1){//若为十进制整数
for(i=1;
a_long&
i++)
x=x*10+(a[i]-48);
printf("
INT10\t%s\n"
a);
save(a,id,x,y);
//存入结构数组
return;
if(id==2){//若为八进制整数
x=x*8+(a[i]-48);
//换算为十进制数
INT8\t%d\n"
x);
return;
if(id==3){//若为十六进制整数
for(i=2;
i++){
if('
=a[i]&
a[i]<
x=x*16+(a[i]-48);
else{
if('
)x=x*16+(a[i]-87);
else
x=x*16+(a[i]-55);
}
INT16\t%d\n"
if(id==4){//若为变量
IDN\t%s\n"
if(id==5||id==6){//若为标识符(+,-,*,/,++以及if,else,while,then,do)
%s\t-\n"
if(id==8){//若为十进制浮点型
for(i=strlen(a)-1;
i>
=0&
i--)
y=(y+(a[i]-48))/10;
y=y+x;
//整数部分与小数部分换算后相加
REAL10\t%f\n"
y);
if(id==9){//若为八进制浮点型
y=(y+(a[i]-48))/8;
REAL8\t%f\n"
if(id==10){//若为十六进制浮点型
i++)//将整数部分与小数部分分割开,并进行相应的换算
x=x*16+(a[i]-48);
for(i=strlen(a)-1;
y=(y+(a[i]-48))/16;
y=y+x;
printf("
REAL16\t%f\n"
save(a,id,x,y);
WrongEnter"
//所得的具体类型值为,则输入有错误
}