编译原理
语法分析器
实验报告
班级:
学号:
姓名:
实验名称 语法分析器
一、实验目的
1、根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。
2、本次实验的目的主要是加深对自上而下分析法的理解。
二、实验内容
[问题描述]
递归下降分析法:
0.定义部分:定义常量、变量、数据结构。
1.初始化:从文件将输入符号串输入到字符缓冲区中。
2.利用递归下降分析法分析,对每个非终结符编写函数,在主函数中调用文法开始符号的函数。
LL(1)分析法:
模块结构:
1、定义部分:定义常量、变量、数据结构。
2、初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体等);
3、运行程序:让程序分析一个text文件,判断输入的字符串是否符合文法定义的规则;
4、利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示简单的错误提示。
[基本要求]
1. 对数据输入读取
2. 格式化输出分析结果
2.简单的程序实现词法分析
public static void main(String args[]) {
LL l = new LL();
l.setP();
String input = "";
boolean flag = true;
while (flag) {
try {
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
System.out.println();
System.out.print("请输入字符串(输入exit退出):");
input = br.readLine();
} catch (Exception e) {
e.printStackTrace();
}
if(input.equals("exit")){
flag = false;
}else{
l.setInputString(input);
l.setCount(1, 1, 0, 0);
l.setFenxi();
System.out.println();
System.out.println("分析过程");
System.out.println("----------------------------------------------------------------------");
System.out.println(" 步骤 | 分析栈 | 剩余输入串 | 所用产生式 ");
System.out.println("----------------------------------------------------------------------");
boolean b = l.judge();
System.out.println("----------------------------------------------------------------------");
if(b){
System.out.println("您输入的字符串"+input+"是该文法的一个句子");
}else{
System.out.println("您输入的字符串"+input+"有词法错误!");
}
}
}
}
//实现各函数并且加注释
三、编程并上机调试运行
运行结果如下图:
四、实验小结
通过这次实验,我对语法分析有了更深刻的了解,对它的形成有了更清楚得认识。本次实验我主要是基于试验资料上的程序流程图和程序框架完成的。由一个简单一些的产生式得出程序的各个分函数。同时,感谢老师的细心与耐心指导。
第二篇:编译原理 简单样本语言的词法分析器
昆明理工大学信息工程与自动化学院学生实验报告
( 2012 —2013 学年第 1 学期)
课程名称:编译原理 开课实验室: 信自楼44 年月 日
一、实验目的及内容
设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。
二、实验原理及基本技术路线图(方框原理图或程序流程图)
对给定的程序通过词法分析器弄够识别一个个单词符号,并以二元式(单词种别码,单词符号的属性值)显示。而本程序则是通过对给定路径的文件的分析后以单词符号和文字提示显示。
三、所用仪器、材料(设备名称、型号、规格等或使用软件)
Windows下的visual c++6.0;
四、实验方法、步骤(或:程序代码或操作过程)
#include <iostream>
#include<string>
using namespace std;
#define MAX 22
char ch =' ';
string key[15]={"begin","end","if","then","else","while","write","read",
"do", "call","const","char","until","procedure","repeat"};
int Iskey(string c){ //关键字判断
int i;
for(i=0;i<MAX;i++) {
if(key[i].compare(c)==0) return 1;
}
return 0;
}
int IsLetter(char c) { //判断是否为字母
if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1;
else return 0;
}
int IsDigit(char c){ //判断是否为数字
if(c>='0'&&c<='9') return 1;
else return 0;
}
void analyse(FILE *fpin){
string arr="";
while((ch=fgetc(fpin))!=EOF) {
arr="";
if(ch==' '||ch=='\t'||ch=='\n'){}
else if(IsLetter(ch)){
while(IsLetter(ch)||IsDigit(ch)) {
if((ch<='Z')&&(ch>='A')) ch=ch+32;
arr=arr+ch;
ch=fgetc(fpin);
}
fseek(fpin,-1L,SEEK_CUR);
if (Iskey(arr)){cout<<arr<<"\t$关键字"<<endl;}
else cout<<arr<<"\t$普通标识符"<<endl;
}
else if(IsDigit(ch)){
while(IsDigit(ch)||ch=='.'&&IsDigit(fgetc(fpin))){
arr=arr+ch;
ch=fgetc(fpin);
}
fseek(fpin,-1L,SEEK_CUR);
cout<<arr<<"\t$无符号实数"<<endl;
}
else switch(ch){
case'+':
case'-' :
case'*' :
case'=' :
case'/' :cout<<ch<<"\t$运算符"<<endl;break;
case'(' :
case')' :
case'[' :
case']' :
case';' :
case'.' :
case',' :
case'{' :
case'}' :cout<<ch<<"\t$界符"<<endl;break;
case':' :{ch=fgetc(fpin);
if(ch=='=') cout<<":="<<"\t$运算符"<<endl;
else {cout<<"="<<"\t$运算符"<<endl;;
fseek(fpin,-1L,SEEK_CUR);}
}break;
case'>' :{ch=fgetc(fpin);
if(ch=='=') cout<<">="<<"\t$运算符"<<endl;
if(ch=='>')cout<<">>"<<"\t$输入控制符"<<endl;
else {cout<<">"<<"\t$运算符"<<endl;
fseek(fpin,-1L,SEEK_CUR);}
}break;
case'<' :{ch=fgetc(fpin);
if(ch=='=')cout<<"<="<<"\t$运算符"<<endl;
else if(ch=='<')cout<<"<<"<<"\t$输出控制符"<<endl;
else if(ch=='>') cout<<"<>"<<"\t$运算符"<<endl;
else{cout<<"<"<<"\t$运算符"<<endl;
fseek(fpin,-1L,SEEK_CUR);}
}break;
default : cout<<ch<<"\t$无法识别字符"<<endl;
}
}
}
void main(){
char in_fn[30];
FILE * fpin;
cout<<"请输入源文件名(包括路径和后缀名):";
for(;;){
cin>>in_fn;
if((fpin=fopen(in_fn,"r"))!=NULL) break;
else cout<<"文件路径错误!请输入源文件名(包括路径和后缀名):";
}
cout<<"\n********************分析如下*********************"<<endl;
analyse(fpin);
fclose(fpin);
}
五、实验过程原始记录( 测试数据、图表、计算等)
源程序为:
# include<stdio.h>
int main()
{
double r,s,h,v;
printf("r,h=?");
scanf("%lf,%lf",&r,&h);
s=3.1415926*r*r;
v=s*h;
printf("r=%.2f,s=%.2f,h=%.2f,v=%.2f\n\n",r,s,h,v);
return 0;
}
六、实验结果、分析和结论(误差分析与数据处理、成果总结等。其中,绘制曲线图时必须用计算纸或程序运行结果、改进、收获)
词法分析器主要特点是不依靠语法,而只依靠词法,即处理一个单词时不依赖于外部单词的信息,因此词法分析器一般都很简单。语法分析时,调用词法分析器,根据已知文法利用递归向下分析,检查语法错误。在分析时,一是把词法分析器当成语法分析的一部分,另一种是把词法分析器当成编译程序的独立部分。在前一种情况下,词法分析器不断地被语法分析器调用,每调用一次词法分析器将从源程序的字符序列拼出一个单词,并将其Token值返回给语法分析器。后一种情况则不同,词法分析器不是被语法分析器不断地调用,而是一次扫描全部单词完成编译器的独立一遍任务。这次实验刚开始我的时候我是对照课本先把代码输入,编译的时候只有很少的错误,很快我就把错误修改正确,在连接的时候,有错误,我还没讲要分析的文件名写入,写入后运行正确。这从实验学到了很多知识,对词法分析器有了很多了解。
注:教师必须按照上述各项内容严格要求,认真批改和评定学生成绩。