课程实验报告
课程名称:编译原理(语法分析) 专业班级:信息安全1001班 学号: U201014608 姓名:
指导教师:骆婷
报告日期: 2010/11/8
计算机科学与技术学院
1 / 26
编译原理实验报告
1、实验目的
1) 设计并编制一个语法分析程序,加深对语法分析程序中递归下降分析方法的
理解;
2) 巩固对代码生成及报错处理等理论的认识; 3) 培养对完整系统独立分析和设计的能力; 4) 培养学生独立编程的能力;
2、实验要求
利用C语言编制递归下降分析程序,并对简单语言进行语法分析。
2.1 待分析的简单语法的语法
用扩充的BNF表示如下:
(1) <程序>::=begin <语句串> end (2) <语句串>::=<语句>{:语句} (3) <语句>::=<赋值语句> (4) <赋值语句>::=ID := <表达式> (5) <表达死>::=<项>{+<项>|-<项>} (6) <项>::=<因子>{*<因子>|/<因子>} (7) <因子>::=ID | NUM | ( <表达式> )
2.2语法分析程序的功能
输入单词串,以”#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出”error” 例如:
输入: begin a:=9;b:=0 end #
2 / 26
编译原理实验报告
输出: success
输入: begin a=9 end # 输出:error
3、词法分析程序的算法思想
算法的基本任务是从字符串中表示的源程序中识别出具有独立意义的单词符号,并通过其基本文法,正确规约到开始符号。 1) 全局变量的设置
在此程序中,需要设置两个个全局变量:关键字表retab[6]、当前识别的种别号syn。
其中retab中元素为“begin”“if”“then”“while”“do”“end”,在程序会扫描出标识符时,首先查关键字表。如果能找到匹配的单词,则该单词为关键字,否则为一般标识符。
syn用于每一步扫描中scanner 的返回值。在整个语法分析程序中均需要使用该全局变量。
2) 主程序main算法流程图
Y
开始 读取字符串到inputString int i =0;输入字符串长度inputLength Scanner() syn == -1 N 3 / 26
编译原理实验报告
lrparser() 结束 3) 扫描子程序scanner()的算法流程图
字母 数字运算符/界符 当前字符串 N 错误 Y syn=相应的种别 号
4) lrparser()的算法流程图
调用 ch =当前第一个字符 当前数字 syn=种别号 其他符号 是否关键字 syn=11 返回 调用 4 / 26
编译原理实验报告
N syn = 1 Y scanner() yucu() syn == 6 Y scanner() N syn == 0 N Y 成功,打印“success” 出错处理 5) 语句串分析程序yucu()的算法流程图
调用 statement() N syn ==26(;) 5 / 26
编译原理实验报告
Y scanner() 出错处理
6) statement语句分析算法流程图
调用 syn ==26(;) scanner() syn ==18(:=) 是 scanner() 否 expression() 出错处理 7) expression表达式分析算法流程图
调用 term() 是否+ 或- N 6 / 26
编译原理实验报告
Y scanner() term 出错处理
8) term分析函数算法流程图
调用 factor() N 是否* 或 / Y Scanner() 出错处理 9) factor分析函数算法流程图
调用 Y 是否标识符 N 是否整常数 Y N 是否(
Y
7 / 26
编译原理实验报告
scanner() ; expression() 出错处理 N 是否 ) Y scanner() ;返回 4、实验结果
1. 输入begin a:=9; x:= 2*3 end # 结果如下
2. 输入begin a=9end # 结果如下
5、实验感想及总结
本次实验和第一实验一样,框架已经给出,算法已经用类C语言写出,我们需要做的是将第一个实验和第二个实验很好的结合起来。由于第一次实验中不是按照书中的框架写出的代码,因此在第二次实验时传递参数时出现了问题,最后不得不利用全局变量syn解决。通过两次编译原理的实验,更加理解了词法语法分析的过程,促进了对课程的进一步学习。
8 / 26
编译原理实验报告
6、源代码
#include char GetChar(char *input,int *index,int length); intClearBlank(char *input,int (*index),int length); int reserve(char *s); void lrparser(char *input,intinputLength,int *index); void yucu(char *input,intinputLength,int *index); void factor(char *input,intinputLength,int *index); void statement(char *input,intinputLength,int *index); void expression(char *input,intinputLength,int *index); void term(char *input,intinputLength,int *index); char *retab[6]={\"begin\关键字intsyn=0; intmyIsAlpha(char ch) { if(islower(ch)==2 || isupper(ch)==1) { return 1; } else 9 / 26 编译原理实验报告 } { } return 0; void scaner(char *input,intinputLength,int *index) { 果 { s[nowPosition]='\\0';//添加结束标志 j=reserve(s); if(j==0) { syn=10; } else 10 / 26 char s[256]=\"\"; //保存当前的字符 char ch=GetChar(input,index,inputLength); intnowPosition=0; int j=0; if(myIsAlpha(ch)==1) //如果是字母 { while(((ch>='0' &&ch<='9') || (myIsAlpha(ch)==1 ) )&& *index { s[nowPosition]=ch; //添加到当前字符串中 } if((ch<'0' || ch>'9') &&(myIsAlpha(ch)==0 ) )//进行回退操作,并输出结 nowPosition++; ch=GetChar(input,index,inputLength); <=inputLength) 编译原理实验报告 { syn=j; } (*index)--; return; } else //超过范围 { s[nowPosition++]=ch; s[nowPosition]='\\0';//添加结束标志 j=reserve(s); if(j==0) { syn=10; } else { syn=j; } getchar(); exit(0);*/ return; } } else if(ch>='0' &&ch<='9') //如果是数字 { while(ch>='0' &&ch<='9'&& *index <=inputLength) 11 / 26 编译原理实验报告 { s[nowPosition]=ch; //添加到当前字符串中 nowPosition++; ch=GetChar(input,index,inputLength); } if(ch<'0' || ch>'9')//进行回退操作 { (*index)--; syn=11; return; } else //超过范围时 { s[nowPosition]=ch; syn=11; return; } } else { switch(ch) { case '+': { 12 / 26 编译原理实验报告 syn=13; return; } case '-': { syn=14; return ; } case '*': { syn=15; return ; } case '/': { syn=16; return ; } case '<': { ch=GetChar(input,index,inputLength); if(ch=='=') { syn=22; return ; } else if(ch=='>') { syn=21; return ; 13 / 26 编译原理实验报告 } else { syn=20; if(*index>inputLength) { return; } else { (*index)--; return ; } } } case '>': { ch=GetChar(input,index,inputLength); if(ch=='=') { syn=24; return ; } else { syn=23; 14 / 26 编译原理实验报告 if(*index>inputLength) { return; } else { (*index)--; return ; } } } case ':': { ch=GetChar(input,index,inputLength); if(ch=='=') { syn=18; return ; } else { if(*index>inputLength) { return; } else { (*index)--; return ; } 15 / 26 编译原理实验报告 } } case '=': { syn=25; return ; } case ';': {/* syn=26; return ; } case '(': { syn=27; return ; } case ')': { Syn=28; return ; } case '#': { syn=0; return ; } 16 / 26 编译原理实验报告 case ' ': { syn=-1; return ; } default: { printf(\"(非法符号)\"); } } } } int reserve(char *s) { if(strcmp(s,retab[0])==0) { return 1; } else if(strcmp(s,retab[1])==0) { return 2; } else if(strcmp(s,retab[2])==0) { return 3; } 17 / 26 编译原理实验报告 else else if(strcmp(s,retab[3])==0) return 4; { } if(strcmp(s,retab[4])==0) { return 5; } else if(strcmp(s,retab[5])==0) { return 6; } else { return 0; } } char GetChar(char *input,int *index,int length) { if(*index <= length) { (*index)++; return input[(*index)-1]; } 18 / 26 编译原理实验报告 else return 0; } intClearBlank(char *input,int (*index),int length) { while( (*index) != length) { if(input[(*index)] ==32 && (*index) != length) { ((*index))++; } else if( input[(*index)] ==32 && (*index) == length) { printf(\"\\n谢谢使用!\\n\"); getchar(); exit(0); } else { return 1; } } return 0; } 19 / 26 编译原理实验报告 void lrparser(char *input,intinputLength,int *index) { if (syn==1) { scaner(input,inputLength, index); while(syn==-1) { scaner(input,inputLength, index); } yucu(input,inputLength, index); if(syn == 6) { scaner(input,inputLength, index); while(syn==-1) { scaner(input,inputLength, index); } if(syn==0 ) { printf(\"success\\n\"); getchar(); return; } } } else { printf(\"error!\"); return; 20 / 26 编译原理实验报告 } } void yucu(char *input,intinputLength,int *index) { statement(input,inputLength, index); while (syn==26) { scaner(input,inputLength, index); while(syn==-1) { scaner(input,inputLength, index); } statement(input,inputLength, index); } return ; } void statement(char *input,intinputLength,int *index) { if(syn ==10) { scaner(input,inputLength, index); while(syn==-1) { scaner(input,inputLength, index); } if(syn==18) { scaner(input,inputLength, index); while(syn==-1) { 21 / 26 编译原理实验报告 scaner(input,inputLength, index); } expression(input,inputLength, index); } else { printf(\"输出赋值号错误!\\n\"); getchar(); exit(0); } } else { printf(\"输出语句错误!%d\\n\ getchar(); exit(0); } return ; } void expression(char *input,intinputLength,int *index) { term(input,inputLength, index); while(syn == 13|| syn ==14) { scaner(input,inputLength, index); while(syn==-1) { scaner(input,inputLength, index); 22 / 26 编译原理实验报告 } term(input,inputLength, index ); } return ; } void term(char *input,intinputLength,int *index) { factor(input,inputLength, index ); while(syn == 15|| syn ==16) { scaner(input,inputLength, index); while(syn==-1) { scaner(input,inputLength, index); } factor(input,inputLength, index ); } return ; } void factor(char *input,intinputLength,int *index) { if(syn==10 || syn==11) { scaner(input,inputLength, index); 23 / 26 编译原理实验报告 while(syn==-1) { scaner(input,inputLength, index); } } else if(syn ==27) { scaner(input,inputLength, index); while(syn==-1) { scaner(input,inputLength, index); } expression(input,inputLength, index ); if(syn==28) { scaner(input,inputLength, index); while(syn==-1) { scaner(input,inputLength, index); } } else { printf(\"输出)错误\"); getchar(); exit(0); 24 / 26 编译原理实验报告 } } else { printf(\"输出表达式错误\"); getchar(); exit(0); } return ; } void main(void) { char inputString[80]; inti =0; intinputLength=0; char ch; printf(\"请输入字符串\ printf(\"请输入字符串:\"); while((ch =getchar()) != 10) { inputString[inputLength++]=ch; } inputLength--; printf(\"\\n输出序列:\"); scaner(inputString,inputLength, &i); 25 / 26 编译原理实验报告 while(syn==-1)//去除前面的所有空格 { scaner(inputString,inputLength, &i); } lrparser(inputString, inputLength,&i); printf(\"\\n谢谢使用,按任何键退出!\\n\"); getchar(); } 26 / 26 因篇幅问题不能全部显示,请点此查看更多更全内容