青岛理工大学实 验 报 告实验课程: 编译原理实验日期: 2014 年 5月28 日 交报告日期:2014 年6月4日 成绩: 实验地点:现代教育技术中心101(计算机实验室)计算机工程 学院,计算机科学与技术 专业, 班级:计算113实验指导教师: 批阅教师:一、实验目的设计、编制并调试一个词法分析程序,加深对词法分析原理的理解。
二、实验要求1. 待分析的简单语言的词法1) 关键字:begin if then while do end 所有关键字都是小写。
2) 运算符和界符::= + – * / < <= <> > >= = ; ( ) #3) 其他单词是标识符(ID )和整型常数(NUM ),通过以下正规式定义:ID=letter (letter| digit )* NUM=digit digit *4) 空格由空白、制表符和换行符组成。
空格一般用来分隔ID 、NUM,运算符、界符和关键字,词法分析阶段通常被忽略。
2.各种单词符号对应的种别码3.词法分析程序的功能输入:所给文法的源程序字符串。
输出:二元组(syn,token或sum)构成的序列。
其中:syn为单词种别码;token为存放的单词自身字符串;sum为常数。
例如:对源程序begin x:=9; if x>0 then x:=2*x+1/3; end# 经词法分析后输出如下序列:(1,beigin) (10,x) (18,:=) (11,9) (26,;) (2,if)......三、算法思想1.主程序示意图主程序示意图如下所示:其中初值包括如下两个方面。
1)关键字表的初值。
关键字作为特殊标识符处理,把它们预先安排在关键字表,当扫描程序识别出标识符时,查关键字表。
若查到匹配的单词,则该单词为关键字,否则为一般标识符。
关键字表作为一个字符串数组,其描述如下:char *rwtab[22] = {"begin","if","else","then","while","do","for","switch","case","until","break","goto","constant","return","int","float","double","string","char","short","long","end"};2)程序中的主要变量为syn,token和sum。
2.扫描子程序的算法思想首先设置3个变量:①token用于存放构成单词符号的字符串;②sum用于存放整型单词;③syn用于存放单词符号的种别码。
3.词法分析程序流程图四、结果分析及讨论1.正确输入演示输入测试语句:begin int i=12; if(i>=12) y=1; else z=1; end# 运行结果如下所示:分析:测试语句中不存在无法识别的字符,运行正确。
2.错误输入输入测试语句:begin do x=@; while(z=$); end#运行结果如下:分析:测试语句中存在无法识别的符号@、$,因此出现报错提示,提示中将显示无法识别的符号所在行号。
五、总结通过此次实验,使我们了解到如何设计、编制并调试词法分析程序。
在实验的过程中加深了对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理;能够根据识别语言单词的状态转换图,使用某种高级语言直接编写词法分析程序。
六、源程序代码#include<stdio.h>#include<string.h>#include<iostream.h>char prog[80],token[8];char ch;int syn,p,m=0,n,row=0,sum=0;char *rwtab[22]={"begin","if","else","then","while","do","for","switch","case","until","break","goto","constant","return","int","float","double","string","char","short","long","end"};void scaner(){for(n=0;n<8;n++)token[n]=NULL;ch=prog[p++];while(ch==' '){ch=prog[p];p++;}if((ch>='a'&&ch<='z') || (ch>='A'&&ch<='Z')) // 数字&字母组合{m=0;while((ch>='0'&&ch<='9') || (ch>='a'&&ch<='z') || (ch>='A'&&ch<='Z')){token[m++]=ch;ch=prog[p++];}token[m++]='\0';p--;syn=23;for(n=0;n<22;n++)if(strcmp(token,rwtab[n])==0) // 字符串比较,判断是否为关键字{syn=n+1; // 出现关键字,种别码+1break;}}else if((ch>='0' && ch<='9')) // 数字组合{{sum=0;while((ch>='0' && ch<='9') || ch=='.'){sum=sum*10+ch-'0';ch=prog[p++];}}p--;syn=24;if(sum>32767) // 数据范围越界syn=-1;}else switch(ch){case'<': m=0;token[m++]=ch;ch=prog[p++];if(ch=='>') // 符号:<>{syn=34;token[m++]=ch;}else if(ch=='=') // 符号:<={syn=35;token[m++]=ch;}else // 符号:<{syn=36;p--;}break;case'>': m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') // 符号:>={syn=37;token[m++]=ch;}else // 符号:>{syn=38;p--;}break;case':': m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') // 符号::={syn=31;token[m++]=ch;}else // 符号::{syn=30;p--;}break;case'*': syn=26; token[0]=ch; break; // 符号:*case'/': syn=27; token[0]=ch; break; // 符号:/case'+': syn=28; token[0]=ch; break; // 符号:+case'-': syn=29; token[0]=ch; break; // 符号:-case'=': syn=38; token[0]=ch; break; // 符号:=case';': syn=39; token[0]=ch; break; // 符号:;case'(': syn=40; token[0]=ch; break; // 符号:(case')': syn=41; token[0]=ch; break; // 符号:)case'#': syn=00; token[0]=ch; break; // 符号:#case'\n': syn=-2; break; // 换行操作,修改行数default: syn=-1; break; // 无法识别,报错}}void main(){cout<<""<<endl;cout<<" ********************************"<<endl;cout<<" 1. ANALYSIS OF STRING"<<endl;cout<<" 2. EXIT THE PROGEAM"<<endl;cout<<" ********************************"<<endl;int choose;cout<<" [ Please enter your choice ]:"<<endl;scanf("%d",&choose);if(choose==1) // 根据用户选择进行操作{p=0;row=1;cout<<" ---------------------------------------------------"<<endl;cout<<" [ Please input a string like 'begin ******* end#' ]:"<<endl;do{cin.get(ch);prog[p++]=ch;}while(ch!='#');p=0;cout<<" ---------------------------------------------------"<<endl;cout<<" [ The analysis process is as follows ]:"<<endl;do{// 对用户输入字符串进行分析scaner();switch(syn){// 数字输出:(种别码,常数)case 24: cout<<" ("<<syn<<","<<sum<<")"<<endl; break;// 报错输出:输出错误行数case -1: cout<<" Error in row "<<row<<"!"<<endl; break;case -2: row=row++; break;// 其他输出:(种别码,单词符号)default: cout<<" ("<<syn<<","<<token<<")"<<endl;break;}}while (syn!=0);cout<<" [ Analysis of the end ]"<<endl;main();}}。