当前位置:文档之家› 语法分析器(含完整源码)教学文稿

语法分析器(含完整源码)教学文稿

语法分析器(含完整源码)语法分析实验报告一、实验目的:1. 了解单词(内部编码)符号串中的短语句型结构形成规律。

2. 理解和掌握语法分析过程中语法分析思想(LL,LR)的智能算法化方法。

二、实验内容:构造自己设计的小语言的语法分析器:1. 小语言的语法描述(语法规则)的设计即文法的设计;2. 把文法形式符号中所隐含的信息内容挖掘出来并用LL或LR 的资料形式(分析表)表示出来;3. 语法分析的数据输入形式和输出形式的确定;4. 语法分析程序各个模块的设计与调试。

主要设备和材料:电脑、winxp操作系统、VC语言系统三、实验分工:081四、实验步骤:1、语法规则①<程序>::= {<变量定义语句>|<赋值语句>|<条件语句> |<循环语句> }②<变量定义语句>::=var 变量{,变量};③<赋值语句>::=变量:= <表达式>;④<表达式>::=标识符{运算符标识符};⑤<标识符>::=变量|常量⑥<运算符>::=+ | - | * | / | >= | <=⑦<条件语句>::=<if语句>[<else语句>]⑧<if语句>::= if(表达式) then[begin] {赋值语句|条件语句| 循环语句}[end]⑨<else语句>::= [begin] {赋值语句|条件语句| 循环语句} [end]⑩<循环语句>::=while(表达式) [begin] {赋值语句| 条件语句| 循环语句} [end]<输出语句>::=prn 表达式--注1:若if语句、else语句、循环语句中出现begin,后面的end必须出现,即begin与end同对出现--注2:if、while后的"(",")"表示终结符,而不是定义成分优先的说明符号2、分析表:( ) : = 变量常量,;运算符变量定义->②->②->②->②赋值语句->③->③->③->③ ->③条件语句->⑦->⑦->⑦->⑦->⑦->⑦->⑦循环语句->⑩->⑩->⑩->⑩->⑩->⑩->⑩输出语句->->->分析表(续):while var begin end if then prn 变量定义->②赋值语句条件语句->⑦->⑦->⑦->⑦循环语句->⑩->⑩->⑩输出语句-> 3、调试和测试五、源代码(见附录):六、实验总结:本实验在词法分析的基础上,对提取出的标识符进行语法判断。

对已有的语法规则运用LL(1)文法判别并进行构造分析表时,遇到的最大困难是:当发生规约冲突时,该如何处理。

如对于产生式s-->aAb,当对a进行规约时,满足语法规则的β(用户输入串中当前要进行规约的标识符)只有有限种,而不满足的却有无限种情况。

当发生规约冲突时,如何在这无限种情况中,确定冲突的具体信息,以便用户查找。

在反复的尝试和验证中,我们发现发生冲突的用户输入串满足一定的规律,且按这种规律可以把这无限种情况化归为有限类,于是我们找出其中规律并进行划分,然后再对这些有限类冲突进行处理。

七、实验心得:通过这次实验有以下几点收获:1. LR(1)的构造使得对理论的知识理解的更加透彻。

其中LR(1)分析表构造了很多遍,一直无法得到正确结果,这是恒心的考验。

2.在写程序中用类数组来存放单词属性使得对单词各项值的调用更加方便,特别是对出错信息的检测有很大的作用。

3.本实验是在词法基础上的更进一步,在词法程序上添加语法程序,更加理解二者之间的关系。

词法分析为语法分析提供了词法单元,方便分析,使程序模块化,易于读懂。

附录:#include <iostream>#include <fstream>#include <string>#include <math.h>#include <ctype.h>#include <cstdlib>using namespace std;#define Max 655 //最大代码长度#define WordMaxNum 256 //变量最大个数#define DigitNum 256 //常量最大个数#define MaxKeyWord 32 //关键字数量#define MaxOptANum 8 //运算符最大个数#define MaxOptBNum 4 //运算符最大个数#define MaxEndNum 11 //界符最大个数typedef struct DisplayTable{int Index; //标识符所在表的下标int type; //标识符的类型int line; //标识符所在表的行数char symbol[20]; //标识符所在表的名称}Table;int TableNum = 0; //display表的表项总数char Word[WordMaxNum][20]; //标识符表char Digit[WordMaxNum][20]; //数字表int WordNum = 0; //变量表的下标int DigNum = 0; //常量表的下标bool errorFlag = 0; //错误标志int TableIndex = -1; //display 表的下标索引int beginCount = 0;//遇到begin加1,遇到end减1int ifCount = 0; //遇到if加1Table *table = new Table[Max];//关键字const char* const KeyWord[MaxKeyWord] = {"and","array", "begin","case","char","constant","do","else","end","false", "for","if","input","integer","not","of","or","output", "packed","procedure","program","read","real","repeat","set", "then", "to", "type", "until", "var","while", "with","prn"};// 单目运算const char OptA[] = {'+','-','*','/','=','#','<','>'};//双目运算符const char *OptB[] = {"<=",">=",":=","<>"};// 界符const char End[] = {'(', ')' , ',' , ';' , '.' , '[' , ']' , ':' , '{' , '}' , '"'};void error(char str[20],int nLine, int errorType){errorFlag = 1;cout <<" \nError : ";switch(errorType){case 1:cout << "第" << nLine-1 <<"行" << str << " 变量的长度超过限制!\n";break;case 2:cout << "第" << nLine-1 <<"行" << str << " 小数点错误!\n";break;case 3:cout << "第" << nLine-1 <<"行" << str << " 常量的长度超过限制!\n";break;}//switch}//errorvoid Scanner(char ch[],int chLen,int nLine){int chIndex = 0;while(chIndex < chLen) //对输入的字符扫描{/****************处理空格和tab***************************/ //忽略空格和tabwhile(ch[chIndex] == ' ' || ch[chIndex] == 9 ){ chIndex ++; }/*************************处理换行符*********************/ //遇到换行符,行数加1while(ch[chIndex] == 10){ nLine++;chIndex ++;}/***************************标识符**********************/ if( isalpha(ch[chIndex])) //以字母、下划线开头{char str[256];int strLen = 0;//是字母、下划线while(isalpha(ch[chIndex]) || ch[chIndex] == '_' ){str[strLen ++] = ch[chIndex];chIndex ++;while(isdigit(ch[chIndex]))//不是第一位,可以为数字{str[strLen ++] = ch[chIndex];chIndex ++;}}str[strLen] = 0; //字符串结束符if(strlen(str) > 20) //标识符超过规定长度,报错处理{error(str,nLine,1);}else{int i;for(i = 0;i < MaxKeyWord; i++) //与关键字匹配//是关键字,写入table表中if(strcmp(str, KeyWord[i]) == 0){strcpy(table[TableNum].symbol,str);table[TableNum].type = 1; //关键字table[TableNum].line = nLine;table[TableNum].Index = i;TableNum ++;break;}if(i >= MaxKeyWord) //不是关键字{table[TableNum].Index = WordNum;strcpy(Word[WordNum++],str);table[TableNum].type = 2; //变量标识符strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;TableNum ++;}}}/**************************常数**************************/ else if(isdigit(ch[chIndex])) //遇到数字{int flag = 0;char str[256];int strLen = 0;//数字和小数点while(isdigit(ch[chIndex]) || ch[chIndex] == '.') {//flag表记小数点的个数,0时为整数,1时为小数,2时出错if(ch[chIndex] == '.')flag ++;str[strLen ++] = ch[chIndex];chIndex ++;}str[strLen] = 0;if(strlen(str) > 20) //常量标识符超过规定长度20,报错处理{error(str,nLine,3);}if(flag == 0){table[TableNum].type = 3; //整数}if(flag == 1){table[TableNum].type = 4; //小数}if(flag > 1){error(str,nLine,2);}table[TableNum].Index = DigNum;strcpy(Digit[DigNum ++],str);strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;TableNum ++;}/*************************运算符************************/ else{//用来区分是不是无法识别的标识符,0为运算符,1为界符int errorFlag;char str[3];str[0] = ch[chIndex];str[1] = ch[chIndex + 1];str[2] = '\0';int i;for( i = 0;i < MaxOptBNum;i++)//MaxOptBNum)if(strcmp(str,OptB[i]) == 0){errorFlag = 0;table[TableNum].type = 6;strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;table[TableNum].Index = i;TableNum ++;chIndex = chIndex + 2;break;}if(i >= MaxOptBNum){for( int k = 0;k < MaxOptANum; k++)if(OptA[k] == ch[chIndex]){errorFlag = 0;table[TableNum].type = 5;table[TableNum].symbol[0] =ch[chIndex];table[TableNum].symbol[1] = 0;table[TableNum].line = nLine;table[TableNum].Index = k;TableNum ++;chIndex ++;break;}/*************************界符************************/for(int j = 0;j < MaxEndNum;j ++)if(End[j] ==ch[chIndex]){errorFlag = 1;table[TableNum].line = nLine;table[TableNum].symbol[0] = ch[chIndex];table[TableNum].symbol[1] = 0;table[TableNum].Index = j;table[TableNum].type = 7;TableNum ++;chIndex ++;}/********************其他无法识别字符*****************/ //开头的不是字母、数字、运算符、界符if(errorFlag != 0 && errorFlag != 1){char str[256];int strLen = -1;str[strLen ++] = ch[chIndex];chIndex ++;while(*ch != ' ' || *ch != 9 || ch[chIndex] != 10){str[strLen ++] = ch[chIndex];chIndex ++;}str[strLen] = 0;table[TableNum].type = 8;strcpy(table[TableNum].symbol,str);table[TableNum].line = nLine;table[TableNum].Index = -2;TableNum ++;}}}}}/**************把十进制小数转为16进制******************/ void Trans(double x,int p) //把十进制小数转为16进制{int i=0; //控制保留的有效位数while(i<p){if(x==0) //如果小数部分是0break; //则退出循环else{int k=int(x*16); //取整数部分x=x*16-int(k); //得到小数部分if(k<=9)cout<<k;elsecout<<char(k+55);};i++;};};/***********************语法错误*************************/ void Gerror(int errorType,int nIndex){errorFlag = 1;switch(errorType){case 1:cout << "第" << table[nIndex].line <<"行:" <<table[nIndex].symbol <<" 应该为赋值号:= \n";break;case 2:cout << "第" << table[nIndex].line <<"行:" << table[nIndex].symbol <<" 应为变量 \n";break;case 3:cout << "第" << table[nIndex].line <<"行:" << table[nIndex].symbol <<" 应为逗号 \n";break;case 4:cout << "第" << table[nIndex].line <<"行:" << table[nIndex].symbol <<" 应为分号 \n";break;case 5:cout << "第" << table[nIndex].line <<"行:" << table[nIndex].symbol <<" 应为运算符 \n";break;case 6:cout << "第" << table[nIndex].line <<"行:" << table[nIndex].symbol <<" 应为变量或常量 \n";break;case 7:cout << "第" <<table[TableIndex].line <<"行 "<< table[nIndex].symbol << "与"<<table[TableIndex + 1].symbol<<"之间缺少运算符 \n";break;case 8:cout << "第" << table[nIndex].line <<"行:" <<table[nIndex + 1 ].symbol <<" 应为'(' \n";break;case 9:cout << "第" <<table[TableIndex].line <<"行 "<< table[TableIndex].symbol << "与"<<table[nIndex + 1].symbol <<"之间缺少'(' \n";break;case 10:cout << "第" << table[TableIndex - 1].line<< " 行: 缺少'then'" << endl;break;case 11:cout << "第" << table[TableIndex].line << " 行:"<<table[nIndex].symbol << "应为then \n";break;case 12:cout << "第" << table[TableIndex].line << " 行: end 后不能接 " <<table[TableIndex].symbol <<endl;break;case 13:cout << "第" << table[nIndex].line <<"行:"<< table[nIndex - 1].symbol <<"与 "<<table[TableIndex].symbol <<"之间缺少变量 \n";break;case 14:cout << "第" <<table[nIndex ].line <<"行 "<< table[nIndex ].symbol << "后缺少';' \n";break;case 15:cout << "第" << table[TableIndex].line << " 行:"<<table[nIndex].symbol << "应为')' \n";break;case 16:cout << "第" << table[TableIndex].line<< " 行,begin 后不能接 "<<table[TableIndex].symbol << endl;break;}}/************************表达式判断********************/ bool express(){while(1 ){if(table[TableIndex].type==2||table[TableIndex].type == 3 ){if(table[TableIndex].type==3&&table[TableIndex+ 1].type == 2 && table[TableIndex].line == table[TableIndex + 1].line){Gerror(7,TableIndex); //出错信息:该处缺少运算符//TableIndex = TableIndex + 2;TableIndex ++;}if(table[TableIndex].line != table[TableIndex + 1].line){// Gerror(14,TableIndex); //出错信息:该语句缺少分号return 1;}TableIndex ++;}else{if(table[TableIndex].type == 5||table[TableIndex].type == 6) {Gerror(13,TableIndex);TableIndex ++;}else{Gerror(6,TableIndex); //出错信息:该处应为变量或常量}TableIndex ++;}if(table[TableIndex].type ==5|| table[TableIndex].type ==6 )TableIndex ++;else if(table[TableIndex].type == 7)return 1;else if(TableIndex >= TableNum) //|| ){Gerror(14,TableIndex); //出错信息:该语句缺少分号return 1;}else{Gerror(5,TableIndex); //出错信息:此处应为运算符TableIndex ++;}}}/*******************赋值语句判断*************************/ bool Assign() //赋值语句的判断{TableIndex ++;if(strcmp( ":=" , table[TableIndex].symbol) == 0){TableIndex ++;}else{Gerror(1,TableIndex); //出错信息:赋值号应该为":="TableIndex ++;}if(express()) //":="后可以为变量或常量{if(strcmp(";",table[TableIndex].symbol) == 0){return 1;}else{if(TableIndex >= TableNum){Gerror(14,TableIndex); //出错信息:该语句缺少分号return 1;}else if(table[TableIndex].line != table[TableIndex +1].line){Gerror(14,TableIndex); //出错信息:该语句缺少分号return 1;//TableIndex ++;}}}else{Gerror(6,TableIndex); //出错信息:":="后应为变量或常量TableIndex ++;}return 0;}/**********************语句判断*************************/ bool judge() //条件、循环、初始化语句的判断{/**************************begin********************** /if(strcmp("begin",table[TableIndex].symbol)==0) //匹配begin{beginCount ++;if(table[TableIndex + 1].type == 7){TableIndex ++;cout << "第" << table[TableIndex].line<< " 行,begin 后不能接 "<<table[TableIndex].symbol << endl;return 1;}}/**************************end***********************/if(strcmp("end",table[TableIndex].symbol) == 0) //匹配end {beginCount --;if(TableIndex < TableNum)if(table[TableIndex+1].type==7||table[TableIndex+ 1].type == 8){TableIndex ++;Gerror(12,TableIndex);return 1;}}/**************************else**********************/if(strcmp("else",table[TableIndex].symbol) == 0) //匹配else{ifCount --;return 1;}if(strcmp("prn",table[TableIndex].symbol) == 0) //匹配prn{TableIndex ++;if(table[TableIndex].type == 2 ||table[TableIndex].type == 3) // prn 后为变量或常量{TableIndex ++;//语句结束,“;”0) {return 1;}else{Gerror(4,TableIndex);//出错信息:此处应为";"}} //ifelse{Gerror(2,TableIndex);//出错信息:此处应为变量TableIndex ++;}}//if_prn/**********************var变量定义**********************/if(strcmp("var",table[TableIndex].symbol) == 0)// var a,b,c; {TableIndex ++;if(table[TableIndex].type != 2){Gerror(13,TableIndex);else Gerror(2,TableIndex);//出错信息:此处应为变量}TableIndex ++;if(strcmp(",",table[TableIndex].symbol) !=0){Gerror(3,TableIndex); //出错信息:此处应为","TableIndex ++;}while(1){while(strcmp(",",table[TableIndex].symbol)==0){TableIndex = TableIndex + 1;if(table[TableIndex].type !=2){Gerror(2,TableIndex);//出错信息:此处应为变量TableIndex ++;}TableIndex ++;}if(strcmp(";",table[TableIndex].symbol)==0){return 1;}else{Gerror(4,TableIndex);//出错信息:此处应为分号";"return 0;}}}/*****************if语句判断************************///if语句else if(strcmp("if",table[TableIndex].symbol) == 0){ifCount ++; //if个数加1if(table[TableIndex +1].type == 2 || table[TableIndex + 1].type == 3){Gerror(9,TableIndex); //出错信息:此处缺少')'TableIndex ++;}else if(strcmp("(",table[TableIndex + 1].symbol) != 0) {Gerror(8,TableIndex);//出错信息:此处应为分号"("}TableIndex = TableIndex + 2;if(express()){if(strcmp(")",table[TableIndex].symbol) == 0) //'('匹配{TableIndex ++;if(strcmp("begin",table[TableIndex ].symbol) == 0) {beginCount ++;if(table[TableIndex + 1].type == 7){Gerror(16,TableIndex);TableIndex ++;return 1;}Gerror(10,TableIndex);//出错信息:此处缺少"then"return 0;}if(strcmp("then",table[TableIndex].symbol) != 0){Gerror(11,TableIndex);//出错信息:此处应为"then"return 0;}//if_thenelse{return 1;}}//if_)else{Gerror(15,TableIndex);return 0;}} //if_express}//if_if//return 1;}int main(){ifstream in;ofstream out;char in_file_name[26],out_file_name[26];char ch[Max];cin.getline(ch,Max,'#');int nLine = 1;/**********************调用词法分析**********************/ Scanner(ch, strlen(ch),nLine);//for(int i = 0; i < TableNum;i ++)// cout << table[i].type<< " "<<table[i].symbol<< " "<<table[i].Index<<""<<table[i].line<< endl;/**********************调用语法分析**********************/ cout << endl << "语法分析结果:\n "<< endl;while(TableIndex <= TableNum){TableIndex ++;if(table[TableIndex].type == 1)judge();else if(table[TableIndex].type == 2)Assign(); //赋值语句}if(ifCount < 0){errorFlag = 1;cout << "程序缺少if \n";}if(beginCount <0){errorFlag = 1;cout << "程序缺少begin \n";}if(beginCount >0){errorFlag = 1;cout << "程序缺少end \n";}if(errorFlag == 0){cout << "语法分析成功!"; }return 0;}。

相关主题