电子科技大学
实 验 报 告
学生姓名: 学号: 指导教师:
实验地点: 计算机软件实验室 实验时间:
一、实验室名称:计算机学院软件工程实验室
二、实验项目名称:词法分析器的设计与实现
三、实验学时:4学时
四、实验原理
1.编译程序要求对高级语言编写的源程序进行分析和合成,生成目标程序。词法分析是对源程序进行的首次分析,实现词法分析的程序为词法分析程序。
2.词法分析的功能是从左到右逐个地扫描源程序字符串,按照词法规则识别出单词符号作为输出,对识别过程中发现的词法错误,输出相关信息。
3.状态转换图是有限有向图,是设计词法分析器的有效工具。
五、实验目的
通过设计词法分析器的实验,使同学们了解和掌握词法分析程序设计的原理及相应的程序设计方法,同时提高编程能力。
六、实验内容
实现求n!的极小语言的词法分析程序,返回二元式作为输出。
七、实验器材(设备、元器件)
1. 操作系统:Windows 7
2. 开发工具:visual studio 2008
八、实验步骤
(1)启动VC6.0,创建空白工程项目。选择菜单中的“文件”->“新建”->“项目”,在弹出的对话框中,左边的“项目类型”框中,选择“Visual C++ 项目”,在右边框中,选择“空项目(.Net)”,在对话框下边,选择工程文件存放目录及输入名称,如Example1,单击“确定”。
(2)建立相应的单词符号与种别对照表;
(3)根据状态转换图编写相应的处理函数;
(4)完成词法分析器;
(5)编译与调试以上程序;
(6)生成相应的*.dyd文件,作为后面语法分析的输入文件。
九、实验数据及结果分析
将源文件与.exe放在同一目录下
打开.exe,输入源文件名称,输出文件名称,错误输出名称
Out.dyd里部分内容
可以对源程序进行词法分析,如果有错给出出错信息和所在行数,如果无错则生成二元式文件。
十、实验结论
本实验程序较好地完成了词法分析程序的设计与实现,能够对所给文法的程序进行词法分析,在没有词法错误的时候生成相应的二元式文件。该实验程序可一次性给出源程序中的词法错误。
十一、总结及心得体会
通过该实验,对词法分析程序的设计,以及运用C语言进行编程有了更深刻的理解,同时加深了自己对词法分析程序的原理的理解与掌握,提高了自己的动手能力。
十二、对本实验过程及方法、手段的改进建议
程序设计合理,代码可进一步优化。
报告评分:
指导教师签字:
本实验参考源代码如下:
Val.h:
#include <cstring>
#include <cstdio>
#include <stdio.h>
#include <string.h>
int type=0;
char val[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char errval[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
void to_outfile();
void to_errfile();
Function.h
using namespace std;
bool isletter(char c) //判别是否字母
{
if(c>64&&c<91||c>96&&c<123)
return true;
return false;
}
bool isdigital(char c) //判别是否数字
{ if(c>47&&c<58)
return true;
return false;
}
int match_reserve(char *p)//匹配保留字
{
if(!(strcmp(p,"begin")))
{
type=1;
strcpy(val,"begin");
to_outfile();
return 1;
}
else if(!(strcmp(p,"end")))
{
type=2;
strcpy(val,"end");
to_outfile();
return 1;
}
else if(!(strcmp(p,"integer")))
{
type=3;
strcpy(val,"integer");
to_outfile();
return 1;
}
else if(!(strcmp(p,"if")))
{
type=4;
strcpy(val,"if");
to_outfile();
return 1;
}
else if(!(strcmp(p,"then")))
{
type=5;
strcpy(val,"then");
to_outfile();
return 1;
}
else if(!(strcmp(p,"else")))
{
type=6;
strcpy(val,"else");
to_outfile();
return 1;
}
else if(!(strcmp(p,"function")))
{
type=7;
strcpy(val,"function");
to_outfile();
return 1;
}
else if(!(strcmp(p,"read")))
{
type=8;
strcpy(val,"read");
to_outfile();
return 1;
}
else if(!(strcmp(p,"write")))
{
type=9;
strcpy(val,"write");
to_outfile();
return 1;
}
else
return 0;
}//match
void match_small(char *p,int tempc)//非保留字、非运算符匹配
{
char t[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
strcpy(t,p);
int k=0;
int state=0;
for(k;k<tempc;k++)
{
if(isletter(t[k]))
{
state=1;
break;
}
}
if(state==0)
{
type=11;
strcpy(val,p);
to_outfile();
}
else
{
type=10;
strcpy(val,p);
to_outfile();
}
}
///////////////////////////////////////////////匹配双运算符
void match_double_operator(char *p)
{
if(!(strcmp(p,":=")))
{
type=20;
strcpy(val,":=");
to_outfile();
}
else if(!(strcmp(p,"<>")))
{
type=13;
strcpy(val,"<>");
to_outfile();
}
else if(!(strcmp(p,"<=")))
{
type=14;
strcpy(val,"<=");
to_outfile();
}
else if(!(strcmp(p,">=")))
{
type=16;
strcpy(val,">=");
to_outfile();
}
}
//////////////////////////////////////////////////匹配单个运算符
void match_single_operator(char *p)
{
if(!(strcmp(p,"<")))
{
type=15;
strcpy(val,"<");
to_outfile();
}
else if(!(strcmp(p,">")))
{
type=17;
strcpy(val,">");
to_outfile();
}
else if(!(strcmp(p,"-")))
{
type=18;
strcpy(val,"-");
to_outfile();
}
else if(!(strcmp(p,"*")))
{
type=19;
strcpy(val,"*");
to_outfile();
}
else if(!(strcmp(p,"=")))
{
type=13;
strcpy(val,"=");
to_outfile();
}
else if(!(strcmp(p,"(")))
{
type=21;
strcpy(val,"(");
to_outfile();
}
else if(!(strcmp(p,")")))
{
type=22;
strcpy(val,")");
to_outfile();
}
else if(!(strcmp(p,";")))
{
type=23;
strcpy(val,";");
to_outfile();
}
else
{
type=0;
strcpy(val,p);
strcpy(errval,p);
to_outfile();
to_errfile();
}
}
Scanner.cpp
#include<iostream>
#include"val.h"
#include<fstream>
#include "function.h"
using namespace std;
ifstream sourcefile;/////源程序文件
ofstream outfile;//打开分析结果二元表
ofstream errfile;//打开错误记录表
char buffer[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};//读入缓冲区
char temp[15]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
char tail[2]={0,0};
void to_outfile()
{
outfile<<val;
outfile<<" ";
outfile<<type;
for(int i=0;i<15;i++)
{
val[i]=0;
}
outfile<<"\n";
outfile<<"\n";
}
void to_errfile()
{
errfile<<errval;
errfile<<" ";
errfile<<type;
for(int i=0;i<15;i++)
{
errval[i]=0;
}
errfile<<"\n";
outfile<<"\n";
}
int main(int argc,char *argv[]){
static char SourceFileName[256];
static char OutputFileName[256];
static char ErrorFileName[256];
int count=0;//读字符计数器
cout<<"Please input the path and the filename of your source file:"<<endl;
cin>>SourceFileName;
sourcefile.open(SourceFileName);
if(!sourcefile.is_open()){
cout<<"Open failed! Please Check The Path!"<<endl<<endl;
cin.get();
return 0;
}
cout<<"Please input the filename of your output file:"<<endl;
cin>>OutputFileName;
cout<<"Please input the filename of your error file:"<<endl;
cin>>ErrorFileName;
outfile.open(OutputFileName);
errfile.open(ErrorFileName);
while(sourcefile>>buffer){//当还有数据可读(没读到EOF的时候)读入一个单词长度的字符(读到空格或回车)
if(buffer[0]==0){
break;
}
int next=0;//指针指向缓存数组
int small=0;//非运算符(标识符)数组长度
while((next<15)&&(buffer[next]!=0)){//遍历所有单词字符
if((isletter(buffer[next]))||(isdigital(buffer[next]))){//将字母和数字加入small数组
small++;
tail[0]=buffer[next];
strcat(temp,tail);
next++;
if(buffer[next]==0){///////////////如果非运算符处于单词末尾 处理small数组
if(temp[0]!=0){
int fm=match_reserve(temp);//匹配保留字
if(fm==1){
for(int j=0;j<15;j++){
temp[j]=0;
}
tail[0]=0;
tail[1]=0;
small=0;
}
if(fm==0){//匹配保留字不成功
match_small(temp,small);
for(int j=0;j<15;j++){
temp[j]=0;
}
tail[0]=0;
tail[1]=0;
small=0;
}
}
}
}
else{//遇到运算符
////////////////////////先对small数组即标识符处理
if(temp[0]!=0){
int fm=match_reserve(temp);//匹配保留字
if(fm==1){
for(int j=0;j<15;j++){
temp[j]=0;
}
tail[0]=0;
tail[1]=0;
small=0;
}
if(fm==0){
match_small(temp,small);
for(int j=0;j<15;j++){
temp[j]=0;
}
tail[0]=0;
tail[1]=0;
small=0;
}
}
/////////////////////////////////////////处理双操作符,向后展望一个字符
if(((buffer[next]==':')&&(buffer[next+1]=='='))||((buffer[next]=='<')&&(buffer[next+1]=='='))||((buffer[next]=='>')&&(buffer[next+1]=='='))||((buffer[next]=='<')&&(buffer[next+1]=='>'))){
tail[0]=buffer[next];
tail[1]=buffer[next+1];
match_double_operator(tail);
next+=2;
tail[0]=0;
tail[1]=0;
}
//////////////////////////////////////////处理单操作符
else{
tail[0]=buffer[next];
match_single_operator(tail);
next++;
tail[0]=0;
tail[1]=0;
}
}//else
}//while
for(int q=0;q<15;q++){
buffer[q]=0;
}
}//while
sourcefile.close();
outfile.close();
errfile.close();
return 0;
}//main
电子科技大学
实 验 报 告
学生姓名:学号: 指导教师:
实验地点:计算机软件实验室 实验时间:
一、实验室名称:计算机学院软件工程实验室
二、实验项目名称:递归下降分析器的设计与实现
三、实验学时:12学时
四、实验原理
1.语法分析是对源程序经过词法分析后转换成的单词流按方法规则进行判断,对能构成正确句子的单词流,给出相应的语法树;对不能构成正确句子的单词流判断其语法错误并做出相应处理。
2.语法分析方法有自上而下和自下而上的分析方法。在不含左递归的文法G中,如果对每一个非终结符的所有候选式的第一个终结符都是两两不相交的(即无公共左因子),则可能构造出一个不带回溯的自上而下的分析程序,这个分析程序由一组递归过程组成,每个过程对应文法的一个非终结符。这样的分析程序称为递归下降分析程序。
七、实验目的
通过设计递归下降分析器的设计与实现实验,使同学们掌握自上而下的递归分析法的语法分析原理和程序设计方法。
八、实验内容
根据给定的方法,编写相应的递归下降的语法分析程序,实现对词法分析后的单词序列的语法检查和程序结构的分析,生成相应的变量名表和过程名表,并将编译中语法检查出来的错误写入相应的文件。
语法错分类:
(1)缺少符号错;
(2)符号匹配错
(3)符号无定义或重复定义。
七、实验器材(设备、元器件)
1.操作系统:Windows XP
2.开发工具:VC6.0
3.普通PC即可
十、实验步骤
(1)启动VC6.0,创建空白工程项目。选择菜单中的“文件”->“新建”->“项目”,在弹出的对话框中,左边的“项目类型”框中,选择“Visual C++ 项目”,在右边框中,选择“空项目(.Net)”,在对话框下边,选择工程文件存放目录及输入名称,如Example1,单击“确定”。
(2)消除文法中的左递归;
(3)实现对方法进行递归向下的分析过程;
(4)利用词法分析器生成的二元式文件*.dyd进行语法分析;
(5)编译与调试以上程序;
十一、实验数据及结果分析
可以对源程序进行语法分析,图中给出了出错行数及出错类型。
十一、实验结论
本实验程序较好地完成了递归下降分析器的设计与实现,能够对所给文法的程序进行语法分析,生成变量名表和过程名表,如果源程序有语法错误则给出出错类型及所在行数。
十一、总结及心得体会
通过该实验,对递归下降分析程序的设计,以及运用C语言进行编程有了更深刻的理解,同时加深了自己对语法分析程序的原理的理解与掌握,提高了自己的动手能力。
十二、对本实验过程及方法、手段的改进建议
程序设计合理,代码可进一步优化。
报告评分:
指导教师签字:
本实验参考源代码如下:
#include <vector>
#include <string>
#include <iostream>
#include <stdio.h>
using namespace std;
struct variable
{
string vname,vproc,vtype;
int vkind,vlev,vadr;
} var;
struct procedure
{
string pname,ptype;
int plev,fadr,ladr;
} proc;
vector <variable> v_table;
vector <procedure> p_table;
string sym;
int val,cur_line,cur_level;
bool ended=false;
void clean_output()
{
freopen("example.dys","w",stdout);
fclose(stdout);
freopen("example.var","w",stdout);
fclose(stdout);
freopen("example.pro","w",stdout);
fclose(stdout);
freopen("SynAnalyze.err","w",stdout);
fclose(stdout);
}
void advance()
{
freopen("example.dys","a+",stdout);
cin>>sym>>val;
printf("%16s %2d\n",sym.c_str(),val);
if (sym=="EOF") ended=true;
while(sym=="EOLN")
{
cur_line++;
cin>>sym>>val;
printf("%16s %2d\n",sym.c_str(),val);
}
}
void error(int type)
{
freopen("SynAnalyze.err","a+",stdout);
switch(type)
{
case 0: printf("LINE %d: variable \"%s\" previously
declared.\n",cur_line,sym.c_str());break;
case 1: printf("LINE %d: missing declaration here.\n",
cur_line);break;
case 2: printf("LINE %d: missing executive statement
here.\n",cur_line);break;
case 3: printf("LINE %d: expected \"end\" here.\n",
cur_line);break;
case 4: printf("LINE %d: expected \"begin\" here.\n",
cur_line);break;
case 5: printf("LINE %d: missing \';\' here.\n",
cur_line);break;
case 6: printf("LINE %d: brackets doesn't matched.\n",
cur_line);break;
case 7: printf("LINE %d: illegal variable here.\n",
cur_line);break;
case 8: printf("LINE %d: missing \'(\' here.\n",
cur_line);break;
case 9: printf("LINE %d: illegal declaration here.\n",
cur_line);break;
case 10: printf("LINE %d: illegal executive statement
here.\n",cur_line);break;
case 11: printf("LINE %d: variable \"%s\"
undeclared.\n",cur_line,sym.c_str());break;
case 12: printf("LINE %d: missing \"else\" here.\n",
cur_line);break;
case 13: printf("LINE %d: missing \"then\" here.\n",
cur_line);break;
case 14: printf("LINE %d: illegal operator here.\n",
cur_line);break;
default: printf("LINE %d: unknown error\n",cur_line);
}
advance();
fclose(stdout);
}
void init()
{
clean_output();
val,cur_line=1;
cur_level=0;
v_table.clear();
p_table.clear();
proc.pname="";
proc.ptype="";
proc.plev=0;
proc.fadr=0;
proc.ladr=-1;
p_table.push_back(proc);
return;
}
void v_add(int vkind)
{
for (int i=p_table[cur_level].fadr;i<=p_table[cur_level].ladr;i++)
{
if (v_table[i].vname==sym && v_table[i].vlev==cur_level && v_table[i].vkind==vkind)
{
error(0);
return;
}
}
var.vname=sym;
var.vproc=p_table[cur_level].pname;
var.vtype="integer";
var.vkind=vkind;
var.vlev=cur_level;
var.vadr=v_table.size();
v_table.push_back(var);
p_table[cur_level].ladr++;
}
bool v_check()
{
for (int i=p_table[cur_level].fadr;i<=p_table[cur_level].ladr;i++)
{
if (v_table[i].vname==sym && v_table[i].vlev==cur_level)
{
return true;
}
}
return false;
}
void A();
void B();
void C();
void D();
void E();
void F();
void G();
void H();
void I();
void J();
void A()
{
if (sym=="begin")
{
advance();
if (sym=="integer")
{
advance();
B();
}
else error(1);
if (sym==";")
{
while (sym==";")
{
advance();
if (sym=="integer")
{
advance();
B();
}
else
{
break;
}
}
}
else error(2);
C();
while (sym==";")
{
advance();
C();
}
if (sym=="end")
{
advance();
return;
}
else error(3);
}
else error(4);
}
void B()
{
if (val==10)
{
v_add(0);//加入变量
advance();
}
else if (sym=="function")
{
advance();
if (val==10)
{
advance();
proc.pname=sym;
cur_level++;
proc.ptype="integer";
proc.plev=cur_level;
proc.fadr=v_table.size();
proc.ladr=v_table.size()-1;
p_table.push_back(proc);
if (sym=="(")
{
advance();
if (val==10)
{
v_add(1);//加入形参
advance();
if (sym==")")
{
advance();
if (sym==";")
{
advance();
A();
cur_level--;
}
else error(5);
}
else error(6);
}
else error(7);
}
else error(8);
}
else error(7);
}
else error(9);
}
void C()
{
if (sym=="read")
{
advance();
D();
}
else if (sym=="write")
{
advance();
D();
}
else if (val==10)
{
advance();
E();
}
else if (sym=="if")
{
advance();
I();
}
else error(10);
}
void D()
{
if (sym=="(")
{
advance();
if (val==10)
{
if (v_check()==true)//检查变量是否存在
{
advance();
if (sym==")")
{
advance();
}
else error(6);
}
else error(11);
}
else error(7);
}
else error(8);
}
void E()
{
if (sym==":=")
{
advance();
F();
}
else error(14);
}
void F()
{
G();
while (sym=="-")
{
advance();
F();
}
}
void G()
{
H();
while (sym=="*")
{
advance();
H();
}
}
void H()
{
if (sym=="F")
{
advance();
if (sym=="(")
{
advance();
F();
if (sym==")")
{
advance();
}
else error(6);
}
else error(8);
}
else if (val==10)
{
if (v_check()==true)//检查变量是否存在
{
advance();
}
else error(11);
}
else if (val==11)
{
advance();
}
else error(10);
}
void I()
{
J();
if (sym=="then")
{
advance();
C();
if (sym=="else")
{
advance();
C();
}
else error(12);
}
else error(13);
}
void J()
{
F();
if (val>=12&&val<=17)
{
advance();
F();
}
else error(14);
}
int main()
{
freopen("example.dyd","r",stdin);
init();
advance();
A();
return 0;
}