编译原理课内实验报告
学生姓名 石磊
专业/班级 计算机26
学 号 2120505140
所在学院 电信学院
提交日期 20##-12-2
一:实验目的:
1.强化对系统软件综合工程实现能力的训练;
2.加强对语法分析原理、方法和基本实现技术的理解;
二:实验内容
1. 用C语言或者其他的高级语言作为宿主语言完成C0语言的词法分析器的设计和实现。
2. 针对if语句的文法编写一个递归下降分析程序,输出结果为抽象语法树。注意,if语句文法中的表达式E采用四则运算表达式的文法;抽象语法树的格式自行设计,如果需要降低难度的话,也可用具体语法树而不用抽象语法树作为输出。
三:实验功能描述
1. 编写C0语言的语法分析器的源程序并调试通过。其中语法分析程序既可以自己手动去完成,也可以利用YACC自动生成。
2. 通过测试程序的验收;
四:功能描述:
该语法分析器用yacc生成,针对if语句的文法编写的向下递归程序,输出结果为语法树,实现了实验目标,达到了实验要求。
五:实验程序代码
%{
#include <string.h>
#include <stdlib.h>
#include "yystype.h"
#include "y.tab.h"
#include "treedisp.h"
int yycount = 0;
extern YYSTYPE yylval;
#define NSYMS 20
struct symtab {
char *name;
double value;
} symtab[NSYMS];
struct symtab *symlook(char *s);
#define NRSVS 10
struct rsvtab {
char *name;
int id;
} rsvtab[NRSVS] = {
{"if", IF},
{"else", ELSE},
{"while", WHILE},
{"for", FOR},
{"other", OTHER},
{"var", VAR}
};
int rsvlook(char *s);
%}
digit [0-9]
integer {digit}+
eq "=="
pl "+"
mi "-"
mu "*"
di "/"
sc ";"
as "="
identifier [a-zA-Z][a-zA-Z0-9_]*
delim [ \n\t]
ws {delim}+
other "other"
%%
{integer} {
//yylval = atoi(yytext);
rec_token("INTEGER");
return INTEGER;
}
{identifier} {
if (rsvlook(yytext) != 0) {
rec_token("RESERVED");
return rsvlook(yytext);
}
rec_token("SYMBOL");
return SYMBOL;
{eq} { rec_token("OPR"); return EQ; }
{pl} { rec_token("OPR"); return PL; }
{mi} { rec_token("OPR"); return MI; }
{mu} { rec_token("OPR"); return MU; }
{di} { rec_token("OPR"); return DI; }
{as} { rec_token("OPR"); return ASSIGN; }
{sc} { rec_token("SC"); return SC; }
\( { rec_token("LB"); return LB; }
\) { rec_token("RB"); return RB; }
{ws} ;
. {
printf("error: %s\n", yytext);
yyerror("Illigal input.");
}
%%
char *buffer[20];
void rec_token(char *s) {
yylval.token_id = ++yycount;
yylval.text = strdup(yytext);
sprintf(buffer, "%s(%s)", s, yytext);
name_node(yycount, buffer);
}
int rsvlook(char *s) {
struct rsvtab *sp;
for (sp = rsvtab; sp < &rsvtab[NRSVS]; ++sp) {
if (sp->name && !strcmp(sp->name, s))
return sp->id;
}
return 0;
}
struct symtab *symlook(char *s) {
struct symtab *sp;
for (sp = symtab; sp < &symtab[NSYMS]; ++sp) {
if (sp->name && !strcmp(sp->name, s))
return sp;
if (!sp->name) {
sp->name = strdup(s);
return sp;
}
}
yyerror("Too many symbols.");
exit(1);
}
测试代码:
if (1+1)
if (2*3+5)
if (3*4+9)
if (5*3+2)
other;
else
other;
else
other;
else
other;
else
b=2*3+5;
测试结果:
stseq
├── statement
│ └── mifst
│ ├── RESERVED(if)
│ ├── LB(()
│ ├── exp
│ │ └── term
│ │ └── factor
│ │ └── INTEGER(1)
│ ├── RB())
│ ├── mifst
│ │ ├── RESERVED(if)
│ │ ├── LB(()
│ │ ├── exp
│ │ │ ├── term
│ │ │ │ ├── term
│ │ │ │ │ └── factor
│ │ │ │ │ └── INTEGER(2)
│ │ │ │ ├── OPR(*)
│ │ │ │ └── factor
│ │ │ │ └── INTEGER(3)
│ │ │ ├── OPR(+)
│ │ │ └── exp
│ │ │ └── term
│ │ │ └── factor
│ │ │ └── INTEGER(5)
│ │ ├── RB())
│ │ ├── mifst
│ │ │ ├── RESERVED(if)
│ │ │ ├── LB(()
│ │ │ ├── exp
│ │ │ │ ├── term
│ │ │ │ │ ├── term
│ │ │ │ │ │ └── factor
│ │ │ │ │ │ └── INTEGER(3)
│ │ │ │ │ ├── OPR(*)
│ │ │ │ │ └── factor
│ │ │ │ │ └── INTEGER(4)
│ │ │ │ ├── OPR(+)
│ │ │ │ └── exp
│ │ │ │ └── term
│ │ │ │ └── factor
│ │ │ │ └── INTEGER(9)
│ │ │ ├── RB())
│ │ │ ├── mifst
│ │ │ │ ├── RESERVED(if)
│ │ │ │ ├── LB(()
│ │ │ │ ├── exp
│ │ │ │ │ ├── term
│ │ │ │ │ │ ├── term
│ │ │ │ │ │ │ └── factor
│ │ │ │ │ │ │ └── INTEGER(5)
│ │ │ │ │ │ ├── OPR(*)
│ │ │ │ │ │ └── factor
│ │ │ │ │ │ └── INTEGER(3)
│ │ │ │ │ ├── OPR(+)
│ │ │ │ │ └── exp
│ │ │ │ │ └── term
│ │ │ │ │ └── factor
│ │ │ │ │ └── INTEGER(2)
│ │ │ │ ├── RB())
│ │ │ │ ├── statement
│ │ │ │ │ ├── RESERVED(other)
│ │ │ │ │ └── SC(;)
│ │ │ │ ├── RESERVED(else)
│ │ │ │ └── statement
│ │ │ │ ├── RESERVED(other)
│ │ │ │ └── SC(;)
│ │ │ ├── RESERVED(else)
│ │ │ └── statement
│ │ │ ├── RESERVED(other)
│ │ │ └── SC(;)
│ │ ├── RESERVED(else)
│ │ └── statement
│ │ ├── RESERVED(other)
│ │ └── SC(;)
│ ├── RESERVED(else)
│ └── mifst
│ ├── SYMBOL(b)
│ ├── OPR(=)
│ ├── exp
│ │ ├── term
│ │ │ ├── term
│ │ │ │ └── factor
│ │ │ │ └── INTEGER(2)
│ │ │ ├── OPR(*)
│ │ │ └── factor
│ │ │ └── INTEGER(3)
│ │ ├── OPR(+)
│ │ └── exp
│ │ └── term
│ │ └── factor
│ │ └── INTEGER(5)
│ └── SC(;)
└── stseq
└── (empty)
六:实验心得
在本次实验中,我耗费了大量时间来设计分析设计。用一天的时间来思考,用了两个多小时在纸上设计演算,编程总共用了七八个小时。基于上次语法分析的实验,终于利用flex设计出了语法分析器并成功输出语法分析树。实验中遇到的最大困难是无法输出语法树,经过在网上以及书本上等多种渠道的学习,最终得以解决问题。虽然耗费大量了时间,但我很开心,因为通过本次实验,我又掌握了不少知识,使自己的能力得到了极大的提升。
通过本次实验,更加明白在学习生活中,应该学会积极主动的自主探索,,只有这样,才能使自己的能力有所提升,才能真正掌握知识,将所学知识用于实践。
编译原理—词法分析器实验报告
一、实验目的:
1.设计、编制、调试一个词法分析子程序-识别单词,加深对词法分析原理的理解。
2.掌握在对程序设计语言的源程序扫描的过程中,将其分解后各类单词的语法分析方法。
二、实验要求:
1. 对给定的程序通过词法分析器弄够识别一个个单词符号,并以二元式(单词种别码,单词符号的属性值)显示。而本程序则是通过对给定路径的文件的分析后以单词符号和文字提示显示。
2. 本程序自行规定:
(1)关键字"begin","end","if","then","else","while","write","read",
"do", "call","const","char","until","procedure","repeat"
(2)运算符:"+","-","*","/","="
(3)界符:"{","}","[","]",";",",",".","(",")",":"
(4)其他标记 如字符串,表示以字母开头的标识符。
(5)空格、回车、换行符跳过。
在屏幕上显示如下:
( 1 , 无符号整数)
( begin , 关键字 )
( if , 关键字 )
( +, 运算符 )
( ; , 界符 )
( a , 普通标识符 )
三、使用环境:
Window vista 下的 Visual Studio 2008;
四、实验步骤
1.查询资料,了解词法分析器的工作过程与原理。
2.分析题目,整理出基本设计思路。
3.实践编码,将设计思想转换用c语言编码实现,编译运行。
4.测试功能,多次设置包含不同字符,关键字的待解析文件,仔细察看运行结果,检测该分析器的分析结果是否正确。通过最终的测试发现问题,逐渐完善代码中设置的分析对象与关键字表,拓宽分析范围提高分析能力。
五、流程图
五、调试程序:
1.举例说明
文件位置:C:\TEST.txt
目标程序如下:
Int main()
{
i=10;
j=100;
n=1;
sum=0;
mult=1;
while (i>0) {n=n+1;i=i-1;}
if (j>=50) then sum=sum+j; else {mult=mult*(j+1);sum=sum+i;}
if (i<=10) then sum=sum-i; else mult=mult+i/2;
if (i==j) then sum=sum-j; else mult=mult-j/2;
if (n>1) then n=n-1; else n=n+1;
if (n<2) then n=n+2; else n=n-2;
}
2.运行结果:
六、程序源代码:
#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);
cout<<endl;
cout<<"按任意键结束"<<endl;
int a;
cin>>a;
}
六、实验心得:
通过此次实验,让我了解到如何设计、编制并调试词法分析程序,加深对词法分析原理的理解;熟悉了构造词法分析程序的手工方式的相关原理,使用某种高级语言(例如C++语言)直接编写此法分析程序。另外,也让我重新熟悉了C++语言的相关内容,加深了对C++语言的用途的理解。在本次实验中,我纠正了一个一直以来的概念错误:main不是关键字,它定义为程序的入口,是主函数!在本实验中,虽然我把main初始化在关键字表
(字符指针类型数组)*Key[10]中,当与该数组中字符串进行比较时,若与main匹配成功,则返回2,若为其他关键字则返回1,以此来把main从关键字中区别出来。
在本实验中的关键字表只初始化了几个常用的关键字,还可继续扩充(只需扩大数组,向其中补充要添加的关键字)。
编译原理实验报告编译原理实验报告1编译原理实验报告一实验内容设计编制并调式一个语法分析程序加深对语法分析原理的理解二实验目的及要求…
学号20xx2798专业软件工程姓名薛建东实验日期20xx0408教师签字成绩实验报告实验名称LL1语法分析实验目的通过完成预测分…
目录一语法分析方法11判断为算符优先文法12求FirstVT集和LastVT集13根据FirstVT和LastVT集构造算符优先表…
编译原理实验报告词法分析器学院计算机科学与技术时间20xx69一问题描述选择计算机高级程序语言之一C语言运用恰当的词法分析技术线路…
实验报告姓名班级同组人项目氢氧化钠标准溶液浓度的标定课程分析化学学号一实验目的1学会称量瓶电子天平滴定管等常用滴定仪器的准备和使用…
实验报告一题目Gauss列主元消去法摘要求解线性方程组的方法很多主要分为直接法和间接法本实验运用直接法的Guass消去法并采用选主…
数据分析课程实验报告学院理学院专业信息与计算科学班级姓名学号一实验题目所做实验属于哪一部分的内容例如一元线形回归及其在SPSS中的…
光亮镀锌及化学镀镍1实验目的11学习和实践氯化钾光亮镀锌的实验室基本操作流程了解电镀的基本原理和工艺12学习并掌握化学镀镍的原理及…
编译原理实验报告实验名称实验类型指导教师专业班级姓名学号实验地点实验成绩编写语法分析程序上机实验蒋勇软件1002班20xx1东6A…