编译原理实验三
编译原理实验三-自下而上语法分析及语义分析x
上海电力学院编译原理课程实验报告实验名称:实验三自下而上语法剖析及语义剖析院系:计算机科学与技术学院专业年级:学生姓名:学号:指导老师:实验日期:实验三自上而下的语法剖析一、实验目的:经过本实验掌握LR剖析器的结构过程,并依据语法制导翻译,掌握属性文法的自下而上计算的过程。
二、实验学时:4学时。
三、实验内容依据给出的简单表达式的语法组成规则(见五),编制LR剖析程序,要求能对用给定的语法例则书写的源程序进行语法剖析和语义剖析。
关于正确的表达式,给出表达式的值。
关于错误的表达式,给出犯错地点。
四、实验方法采纳 LR剖析法。
第一给出 S- 属性文法的定义(为简易起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。
属性文法的定义可参照书137页表 6.1 ),并将其改造成用LR剖析实现时的语义剖析动作(可参照书145页表6.5 )。
接下来给出 LR剖析表。
而后程序的详细实现:LR剖析表可用二维数组(或其余)实现。
增添一个 val 栈作为语义剖析实现的工具。
编写总控程序,实现语法剖析和语义剖析的过程。
注:关于整数的辨别能够借助实验1。
五、文法定义简单的表达式文法以下:(1)E->E+T(2)E->E-T(3)E->T(4)T->T*F(5)T->T/F(6)T->F(7)F->(E)(8)F->i状态ACTION (动作)GOTO (变换)i + - * / ( ) # E T F0 S5 S4 1 2 31 S6 S12 acc2 R3 R3 S7 S13 R3 R33 R6 R6 R6 R6 R6 R64 S5 S4 8 2 35 R8 R8 R8 R8 R8 R86 S5 S4 9 37 S5 S4 108 S6 R12 S119 R1 R1 S7 S13 R1 R110 R4 R4 R4 R4 R4 R411 R7 R7 R7 R7 R7 R712 S5 S4 14 313 S5 S4 1514 R2 R2 S7 S13 R2 R215 R5 R5 R5 R5 R5 R5五、办理程序例和办理结果例示例 1:20133191*(20133191+3191)+ 3191#六、源代码【】#include<string>using namespace std;//单词结构定义struct WordType{int code;string pro;};//函数申明WordType get_w();void getch();void getBC();bool isLetter();bool isDigit();void retract();int Reserve(string str);string concat(string str);【】class Table_action{int row_num,line_num;int lineName[8];string tableData[16][8];public:Table_action(){row_num=16;line_num=8;lineName[0]=30;lineName[1]=7;lineName[2]=13;lineName[3]=8;lineName[4]=14;lineName[5]=1;lineName[6]=2;lineName[7]=15;lineName[8]=0;for(int m=0;m<row_num;m++)for(int n=0;n<line_num;n++)tableData[m][n]="";tableData[0][0]="S5";tableData[0][5]="S4";tableData[1][1]="S6";tableData[1][2]="S12";tableData[1][7]="acc";tableData[2][1]="R3";tableData[2][2]="R3";tableData[2][3]="S7";tableData[2][4]="S13";tableData[2][6]="R3";tableData[2][7]="R3";tableData[3][1]="R6";tableData[3][3]="R6"; tableData[3][4]="R6"; tableData[3][6]="R6"; tableData[3][7]="R6"; tableData[4][0]="S5"; tableData[4][5]="S4"; tableData[5][1]="R8"; tableData[5][2]="R8"; tableData[5][3]="R8"; tableData[5][4]="R8"; tableData[5][6]="R8"; tableData[5][7]="R8"; tableData[6][0]="S5"; tableData[6][5]="S4"; tableData[7][0]="S5"; tableData[7][5]="S4"; tableData[8][1]="S6"; tableData[8][2]="S12"; tableData[8][6]="S11"; tableData[9][1]="R1"; tableData[9][2]="R1"; tableData[9][3]="S7"; tableData[9][4]="S13"; tableData[9][6]="R1"; tableData[9][7]="R1"; tableData[10][1]="R4"; tableData[10][2]="R4"; tableData[10][3]="R4"; tableData[10][4]="R4"; tableData[10][6]="R4"; tableData[10][7]="R4"; tableData[11][1]="R7"; tableData[11][2]="R7"; tableData[11][3]="R7"; tableData[11][4]="R7"; tableData[11][6]="R7"; tableData[11][7]="R7"; tableData[12][0]="S5"; tableData[12][5]="S4"; tableData[13][0]="S5"; tableData[13][5]="S4"; tableData[14][1]="R2"; tableData[14][2]="R2";tableData[14][4]="S13";tableData[14][6]="R2";tableData[14][7]="R2";tableData[15][1]="R5";tableData[15][2]="R5";tableData[15][3]="R5";tableData[15][4]="R5";tableData[15][5]="R5";tableData[15][6]="R5";tableData[15][7]="R5";}string getCell(int rowN,int lineN){int row=rowN;int line=getLineNumber(lineN);if(row>=0&&row<row_num&&line>=0&&line<=line_num) return tableData[row][line];elsereturn"";}int getLineNumber(int lineN){for(int i=0;i<line_num;i++)if(lineName[i]==lineN)return i;return -1;}};【】class Table_go{int row_num,line_num;// 行数、列数string lineName[3];int tableData[16][3];public:Table_go(){row_num=16;line_num=3;lineName[0]="E";lineName[1]="T";lineName[2]="F";for(int m=0;m<row_num;m++)for(int n=0;n<line_num;n++)tableData[m][n]=0;tableData[0][0]=1;tableData[0][1]=2;tableData[0][2]=3;tableData[4][0]=8;tableData[4][1]=2;tableData[4][2]=3;tableData[6][1]=9;tableData[6][2]=3;tableData[7][2]=10;tableData[12][1]=14;tableData[12][2]=3;tableData[13][2]=15;}int getCell(int rowN,string lineNa){int row=rowN;int line=getLineNumber(lineNa);if(row>=0&&row<row_num&&line<=line_num) return tableData[row][line];elsereturn -1;}int getLineNumber(string lineNa){for(int i=0;i<line_num;i++)if(lineName[i]==lineNa)return i;return -1;}};【】class Stack_num{int i; //栈顶标记int *data; // 栈结构public:Stack_num() // 结构函数{data=new int[100];i=-1;}int push(int m)//进栈操作{i++;data[i]=m;return i;}int pop()// 出栈操作{i--;return data[i+1];}int getTop()//返回栈顶{return data[i];}~Stack_num() //析构函数{delete []data;}int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【】class Stack_str{int i;string *data; // 栈顶标记//栈结构public:Stack_str() // 结构函数{data=new string[50];i=-1;}int push(string m)//进栈操作{i++;data[i]=m;return i;}int pop()// 出栈操作{data[i]="";i--;return i;}string getTop() //返回栈顶{return data[i];}~Stack_str() //析构函数{delete []data;}int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【】#include<iostream>#include<string>#include"cifa.h"using namespace std;//重点字表和对应的编码string codestring[10]={"main","int","if","then","else","return","void","cout","endl"}; int codebook[10]={26,21,22,23,24,25,27,28,29};//全局变量char ch;int flag=0;/*// 主函数int main(){WordType word;cout<<"请输入源程序序列 :";word=get_w();while(word.pro!="#")//# 为自己设置的结束标记{cout<<"("<<word.code<<" ,"<<" “"<<word.pro<<" ”"<<")"<<endl;word=get_w();};return 0;}*/WordType get_w(){string str="";int code;WordType wordtmp;getch();//读一个字符getBC();//去掉空白符if(isLetter()){ // 以字母开头while(isLetter()||isDigit()){str=concat(str);getch();}retract();code=Reserve(str);if(code==-1){wordtmp.code=0;wordtmp.pro=str;}// 不是重点字else{wordtmp.code=code;wordtmp.pro=str;}//是重点字}else if(isDigit()){ //以数字开头while(isDigit()){str=concat(str);getch();}retract();wordtmp.code=30;wordtmp.pro=str;}else if(ch=='(') {wordtmp.code=1;wordtmp.pro="(";}else if(ch==')') {wordtmp.code=2;wordtmp.pro=")";}else if(ch=='{') {wordtmp.code=3;wordtmp.pro="{";}else if(ch=='}') {wordtmp.code=4;wordtmp.pro="}";}else if(ch==';') {wordtmp.code=5;wordtmp.pro=";";}else if(ch=='=') {wordtmp.code=6;wordtmp.pro="=";}else if(ch=='+') {wordtmp.code=7;wordtmp.pro="+";}else if(ch=='*') {wordtmp.code=8;wordtmp.pro="*";}else if(ch=='>') {wordtmp.code=9;wordtmp.pro=">";}else if(ch=='<') {wordtmp.code=10;wordtmp.pro="<";}else if(ch==',') {wordtmp.code=11;wordtmp.pro=",";}else if(ch=='\'') {wordtmp.code=12;wordtmp.pro="\'";}else if(ch=='-') {wordtmp.code=13;wordtmp.pro="-";}else if(ch=='/') {wordtmp.code=14;wordtmp.pro="/";}else if(ch=='#') {wordtmp.code=15;wordtmp.pro="#";}else if(ch=='|') {wordtmp.code=16;wordtmp.pro="|";}else{wordtmp.code=100;wordtmp.pro=ch;}return wordtmp;}void getch(){if(flag==0) //没有回退的字符ch=getchar();else//有回退字符,用回退字符,并设置标记flag=0;}void getBC(){while(ch==' '||ch=='\t'||ch=='\n')ch=getchar();}bool isLetter(){if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')return true;elsereturn false;}bool isDigit(){if(ch>='0'&&ch<='9')return true;elsereturn false;}string concat(string str){return str+ch;}void retract(){flag=1;}int Reserve(string str){int i;for(i=0;i<=8;i++){if(codestring[i]==str)//是某个重点字,返回对应的编码return codebook[i];}if(i==9) //不是重点字return -1;}【】#include<iostream>#include<string>#include<cstdlib>#include"cifa.h"#include"stack_num.h"#include"stack_str.h"#include"table_action.h"#include"table_go.h"using namespace std;void process(){int stepNum=1;int topStat;Stack_num statusSTK; Stack_str symbolSTK; //状态栈//符号栈Stack_num valueSTK; //值栈WordType word;Table_action actionTAB; Table_go goTAB; //行为表// 转向表cout<<"请输入源程序,以 #结束: ";word=get_w();//总控程序初始化操作symbolSTK.push("#");statusSTK.push(0);valueSTK.push(0);cout<<"步骤 \t 状态栈 \t 符号栈 \t 值栈 \t 目前词 \t 动作 \t 转向"<<endl; //剖析while(1){topStat=statusSTK.getTop(); // 目前状态栈顶string act=actionTAB.getCell(topStat,word.code);//依据状态栈顶和目前单词查到的动作//输出cout<<stepNum++<<"\t";statusSTK.outStack(); cout<<"\t";symbolSTK.outStack(); cout<<"\t";valueSTK.outStack(); cout<<"\t";cout<<word.pro<<"\t";//行为为“ acc”,且目前办理的单词为#,且状态栈里就两个状态//说明正常剖析结束if(act=="acc"&&word.pro=="#"&&statusSTK.topNumber()==1){cout<<act<<endl;cout<<"剖析成功! "<<endl;cout<<"结果为: "<<valueSTK.getTop()<<endl;return;}//读到 act 表里标记为错误的单元格else if(act==""){cout<<endl<<"不是文法的句子! "<<endl;cout<<"错误的地点为单词 "<<word.pro<<" 邻近。
实验报告编译原理
北京科技大学计算机与通信工程学院实验报告实验名称:_________编译原理实验报告_______学生姓名:_________ ________________专业:_________ _________________班级:_________ _________________学号:_________________________指导教师:_________ _________________实验成绩:________________________________实验地点:________________________________实验时间:____2015___年___07__月_______日一、实验目的与实验要求1、实验目的通过一个词法分析程序将一段给出的C语言代码的词法部分分析出来;通过一个语法分析程序将一段给出的C语言代码的语法分析出来。
2、实验要求二、实验设备(环境)及要求Win7家庭普通版;Visual Studio 2013;三、实验内容与步骤1、实验1(1)实验内容对于给定一段代码,通过词法分析程序将程序中的各个类型的字表分析,包括保留字、分隔符表、运算符表、标识符、整型数、浮点类型数、字符类型、字符串类型等表文件。
(2)主要步骤通过读入程序的文本文件,然后将分析的结果一次保存在本地文本文件。
然后通过指定的命令来将分析的结果读取出来。
附录:源码#include<stdio.h>#include<string.h>#include<stdlib.h>char*key0[] = { " ", "auto", "break", "case", "char", "const", "continue", "default", "do", "double", "else", "enum", "extern", "float", "for", "goto", "if", "int", "long", "register", "return", "short", "signed", "sizeof", "static", "struct", "switch", "typedef", "_Complex", "_Imaginary", "union", "unsigned", "void", "volatile", "while" };/*保留字表*/char *key1[] = { " ", "(", ")", "[", "]", "{", "}", ",", ";", "'" };/*分隔符表*/char *key2[] = { " ", "+", "-", "*", "/", "%", "<", ">", "==", ">=", "<=", "!=", "!", "&&", "||", "<<", ">>", "~", "|", "^", "&", "=", "?:", "->", "++", "--", ".", "+=", "-=", "*=", "/=" };/*运算符表*/int xx0[35], xx1[10], xx2[31];int temp_key3 = 0, temp_c40 = 0, temp_c41 = 0, temp_c42 = 0, temp_c43 = 0;/******* 初始化函数 *******/void load(){int mm;for (mm = 0; mm <= 34; mm++){xx0[mm] = 0;}for (mm = 0; mm <= 9; mm++){xx1[mm] = 0;}for (mm = 0; mm <= 30; mm++){xx2[mm] = 0;}FILE *floading;if ((floading = fopen("key0.txt", "w")) == NULL){printf("Error! Can't create file : key0.txt");return;}fclose(floading);/*建立保留字表文件:key0.txt*/if ((floading = fopen("key1.txt", "w")) == NULL){printf("Error! Can't create file : key1.txt");return;}/*建立分隔符表文件:key1.txt*/if ((floading = fopen("key2.txt", "w")) == NULL){printf("Error! Can't create file : key2.txt");return;}fclose(floading);/*建立运算符表文件:key2.txt*/if ((floading = fopen("key3.txt", "w")) == NULL){printf("Error! Can't create file : key3.txt");return;}fclose(floading);/*建立标识符表文件:key3.txt*/if ((floading = fopen("c40.txt", "w")) == NULL){printf("Error! Can't create file : c40.txt");return;}fclose(floading);/*建立整数类型常量表文件:c40.txt*/if ((floading = fopen("c41.txt", "w")) == NULL){printf("Error! Can't create file : c41.txt");return;}fclose(floading);/*建立浮点类型常量表文件:c41.txt*/if ((floading = fopen("c42.txt", "w")) == NULL){printf("Error! Can't create file : c42.txt");return;}fclose(floading);/*建立字符类型常量表文件:c42.txt*/if ((floading = fopen("c43.txt", "w")) == NULL){printf("Error! Can't create file : c43.txt");return;}fclose(floading);/*建立字符串类型常量表文件:c43.txt*/if ((floading = fopen("defination.txt", "w")) == NULL) {printf("Error! Can't create file : defination.txt");return;}fclose(floading);/*建立注释文件:defination.txt*/if ((floading = fopen("output.txt", "w")) == NULL){printf("Error! Can't create file : output.txt");return;}fclose(floading);/*建立内部码文件:output.txt*/if ((floading = fopen("temp_key1", "w")) == NULL){printf("Error! Can't create file : temp_key1");return;}fclose(floading);/*建立保留字临时表文件:temp_key1*/if ((floading = fopen("temp_key3", "w")) == NULL){printf("Error! Can't create file : temp_key3");return;}fclose(floading);/*建立标识符临时文件:temp_key3*/if ((floading = fopen("temp_c40", "w")) == NULL){printf("Error! Can't create file : temp_c40");return;}fclose(floading);/*建立整数类型常量临时文件:temp_c40*/if ((floading = fopen("temp_c41", "w")) == NULL){printf("Error! Can't create file : temp_c41");return;}fclose(floading);/*建立浮点类型常量临时文件:temp_c41*/if ((floading = fopen("temp_c42", "w")) == NULL){printf("Error! Can't create file : temp_c42");return;}fclose(floading);/*建立字符类型常量临时文件:temp_c42*/if ((floading = fopen("temp_c43", "w")) == NULL){printf("Error! Can't create file : temp_c43");return;}fclose(floading);/*建立字符串类型常量临时文件:temp_c43*/}/******* 保留字及标识符判断函数 *******/void char_search(char *word){int m, line = 0, csi = 0;int value = 0;int value2 = 0;char c, cs[100];FILE *foutput, *finput;for (m = 1; m <= 34; m++){if (strcmp(word, key0[m]) == 0){value = 1;break;}}if (value == 1){if (xx0[m] == 0){foutput = fopen("key0.txt", "a");fprintf(foutput, "0\t%d\t\t%s\n", m, word);fclose(foutput);xx0[m] = 1;}foutput = fopen("output.txt", "a");fprintf(foutput, "0\t%d\t\t%s\n", m, word);fclose(foutput);}else{if (temp_key3 == 0){foutput = fopen("temp_key3", "a");fprintf(foutput, "%s\n", word);fclose(foutput);temp_key3++;foutput = fopen("key3.txt", "a");fprintf(foutput, "3\t1\t\t%s\n", word);fclose(foutput);}finput = fopen("temp_key3", "r");c = fgetc(finput);while (c != EOF){while (c != '\n'){cs[csi++] = c;c = fgetc(finput);}cs[csi] = '\0';csi = 0;line++;if ((strcmp(cs, word)) == 0){value2 = 1;break;}else{value2 = 0;c = fgetc(finput);}}fclose(finput);if (value2 == 1){foutput = fopen("output.txt", "a");fprintf(foutput, "3\t%d\t\t%s\n", line, word);fclose(foutput);}else{foutput = fopen("temp_key3", "a");fprintf(foutput, "%s\n", word);fclose(foutput);temp_key3++;foutput = fopen("output.txt", "a");fprintf(foutput, "3\t%d\t\t%s\n", temp_key3, word);fclose(foutput);foutput = fopen("key3.txt", "a");fprintf(foutput, "3\t%d\t\t%s\n", temp_key3, word);fclose(foutput);}}}/******* 整数类型判断函数 *******/void inta_search(char *word){FILE *foutput, *finput;char c;char cs[100];int csi = 0;int line = 0;int value2 = 0;if (temp_c40 == 0){foutput = fopen("temp_c40", "a");fprintf(foutput, "%s\n", word);fclose(foutput);temp_c40++;foutput = fopen("c40.txt", "a");fprintf(foutput, "4\t0\t1\t%s\n", word);fclose(foutput);}finput = fopen("temp_c40", "r");c = fgetc(finput);while (c != EOF){while (c != '\n'){cs[csi++] = c;c = fgetc(finput);}cs[csi] = '\0';csi = 0;line++;if (strcmp(cs, word) == 0){value2 = 1;break;}c = fgetc(finput);}fclose(finput);if (value2 == 1){foutput = fopen("output.txt", "a");fprintf(foutput, "4\t0\t%d\t%s\n", line, word);fclose(foutput);}else{foutput = fopen("temp_c40", "a");fprintf(foutput, "%s\n", word);fclose(foutput);temp_c40++;foutput = fopen("output.txt", "a");fprintf(foutput, "4\t0\t%d\t%s\n", temp_c40, word);fclose(foutput);foutput = fopen("c40.txt", "a");fprintf(foutput, "4\t0\t%d\t%s\n", temp_c40, word);fclose(foutput);}}/******* 浮点类型判断函数 *******/void intb_search(char *word){FILE *foutput, *finput;char c;char cs[100];int csi = 0;int line = 0;int value2 = 0;if (temp_c41 == 0){foutput = fopen("temp_c41", "a");fprintf(foutput, "%s\n", word);fclose(foutput);temp_c41++;foutput = fopen("c41.txt", "a");fprintf(foutput, "4\t1\t1\t%s\n", word);fclose(foutput);}finput = fopen("temp_c41", "r");c = fgetc(finput);while (c != EOF){while (c != '\n'){cs[csi++] = c;c = fgetc(finput);}cs[csi] = '\0';csi = 0;line++;if (strcmp(cs, word) == 0){value2 = 1;break;}c = fgetc(finput);}fclose(finput);if (value2 == 1){foutput = fopen("output.txt", "a");fprintf(foutput, "4\t1\t%d\t%s\n", line, word);fclose(foutput);}else{foutput = fopen("temp_c41", "a");fprintf(foutput, "%s\n", word);fclose(foutput);temp_c41++;foutput = fopen("output.txt", "a");fprintf(foutput, "4\t1\t%d\t%s\n", temp_c41, word);fclose(foutput);foutput = fopen("c40.txt", "a");fprintf(foutput, "4\t1\t%d\t%s\n", temp_c41, word);fclose(foutput);}}/******* 字符串常量判断函数 *******/void cc_search(char *word){FILE *foutput, *finput;char c;char cs[100];int csi = 0;int line = 0;int value2 = 0;if (temp_c43 == 0){foutput = fopen("temp_c43", "a");fprintf(foutput, "%s\n", word);fclose(foutput);temp_c43++;foutput = fopen("c43.txt", "a");fprintf(foutput, "4\t3\t1\t%s\n", word);fclose(foutput);}finput = fopen("temp_c43", "r");c = fgetc(finput);while (c != EOF){while (c != '\n'){cs[csi++] = c;c = fgetc(finput);}cs[csi] = '\0';csi = 0;line++;if (strcmp(cs, word) == 0){value2 = 1;break;}c = fgetc(finput);}fclose(finput);if (value2 == 1){foutput = fopen("output.txt", "a");fprintf(foutput, "4\t3\t%d\t%s\n", line, word);fclose(foutput);}else{foutput = fopen("temp_c43", "a");fprintf(foutput, "%s\n", word);fclose(foutput);temp_c43++;foutput = fopen("output.txt", "a");fprintf(foutput, "4\t3\t%d\t%s\n", temp_c43, word);fclose(foutput);foutput = fopen("c43.txt", "a");fprintf(foutput, "4\t3\t%d\t%s\n", temp_c43, word);fclose(foutput);}}/******* 字符常量判断函数 *******/void c_search(char *word){FILE *foutput, *finput;char c;char cs[100];int csi = 0;int line = 0;int value2 = 0;if (temp_c42 == 0){foutput = fopen("temp_c42", "a");fprintf(foutput, "%s\n", word);fclose(foutput);temp_c42++;foutput = fopen("c42.txt", "a");fprintf(foutput, "4\t2\t1\t%s\n", word);fclose(foutput);}finput = fopen("temp_c42", "r");c = fgetc(finput);while (c != EOF){while (c != '\n'){cs[csi++] = c;c = fgetc(finput);}cs[csi] = '\0';csi = 0;line++;if (strcmp(cs, word) == 0){value2 = 1;break;}c = fgetc(finput);}fclose(finput);if (value2 == 1){foutput = fopen("output.txt", "a");fprintf(foutput, "4\t2\t%d\t%s\n", line, word);fclose(foutput);}else{foutput = fopen("temp_c42", "a");fprintf(foutput, "%s\n", word);fclose(foutput);temp_c42++;foutput = fopen("output.txt", "a");fprintf(foutput, "4\t2\t%d\t%s\n", temp_c42, word);fclose(foutput);foutput = fopen("c42.txt", "a");fprintf(foutput, "4\t2\t%d\t%s\n", temp_c42, word);fclose(foutput);}}/******* 主扫描函数 *******/void scan(){int count;char chin;FILE *fin;FILE *fout;char filename[50];char temp[100];char target[3] = "'";printf("请输入文件名:");scanf("%s", filename);if ((fin = fopen(filename, "r")) == NULL){printf("Error! Can't open file : %s\n", filename);return;}chin = fgetc(fin);while (chin != EOF){/*对文件包含、宏定义进行处理*/if (chin == '#'){while (chin != '>')chin = fgetc(fin);/*chin=fgetc(fin);*/}/*对空格符、水平制表符进行处理*/else if ((chin == ' ') || (chin == '\t')){;}/*对回车符进行处理*/else if (chin == '\n'){;}/*对单引号内的字符常量进行处理*/else if (chin == target[0]){if (xx1[9] == 0){fout = fopen("key1.txt", "a");fprintf(fout, "1\t9\t\t%c\n", target[0]);fclose(fout);xx1[9] = 1;}temp[0] = chin;chin = fgetc(fin);temp[1] = chin;chin = fgetc(fin);if (chin != target[0]){temp[2] = chin;chin = fgetc(fin);temp[3] = chin;temp[4] = '\0';}else{temp[2] = chin;temp[3] = '\0';}c_search(temp);}/*对双引号内的字符串常量进行处理*/else if (chin == '"'){int i = 0;temp[i++] = '"';chin = fgetc(fin);while (chin != '"'){temp[i++] = chin;chin = fgetc(fin);}temp[i] = '"';temp[i + 1] = '\0';cc_search(temp);}/*对保留字、标识符进行处理*/else if (((chin >= 'A') && (chin <= 'Z')) || ((chin >= 'a') && (chin <= 'z')) || (chin == '_')){int i = 0;while (((chin >= 'A') && (chin <= 'Z')) || ((chin >= 'a') && (chin <= 'z')) || (chin == '_') || ((chin >= '0') && (chin <= '9'))){temp[i++] = chin;chin = fgetc(fin);}temp[i] = '\0';char_search(temp);if (chin != EOF)fseek(fin, -1L, SEEK_CUR);}/*对整型、浮点型数据进行处理*/else if ((chin >= '0') && (chin <= '9')){int dotcount = 0;int i = 0;while (((chin >= '0') && (chin <= '9')) || (chin == '.')){if (chin == '.')dotcount++;if (dotcount == 2)break;temp[i++] = chin;chin = fgetc(fin);}temp[i] = '\0';if (dotcount == 1)intb_search(temp);elseinta_search(temp);if (chin != EOF)fseek(fin, -1L, SEEK_CUR);}/*对注释进行处理*/else if (chin == '/'){chin = fgetc(fin);if (chin == '='){fout = fopen("output.txt", "a");fprintf(fout, "2\t30\t\t/=\n");fclose(fout);}else if (chin != '*'){fout = fopen("output.txt", "a");fprintf(fout, "2\t4\t\t/\n");fclose(fout);fseek(fin, -1L, SEEK_CUR);}else if (chin == '*'){count = 0;chin = fgetc(fin);fout = fopen("defination.txt", "a");fprintf(fout, "/*");while (count != 2){count = 0;while (chin != '*'){fprintf(fout, "%c", chin);chin = fgetc(fin);}count++;fprintf(fout, "%c", chin);chin = fgetc(fin);if (chin == '/'){count++;fprintf(fout, "%c\n", chin);}else{fprintf(fout, "%c", chin);chin = fgetc(fin);}}}}/*对运算符、分隔符进行处理*/else{int time = 0;int firstblood = 0;temp[0] = chin;chin = fgetc(fin);if (chin != EOF){temp[1] = chin;temp[2] = '\0';for (time = 1; time <= 30; time++){if (strcmp(temp, key2[time]) == 0){firstblood = 1;if (xx2[time] == 0){fout = fopen("key2.txt", "a");fprintf(fout, "2\t%d\t\t%s\n", time, temp);fclose(fout);xx2[time] = 1;}fout = fopen("output.txt", "a");fprintf(fout, "2\t%d\t\t%s\n", time, temp);fclose(fout);break;}}if (firstblood != 1){fseek(fin, -1L, SEEK_CUR);temp[1] = '\0';for (time = 1; time <= 9; time++){if (strcmp(temp, key1[time]) == 0){if (xx1[time] == 0){fout = fopen("key1.txt", "a");fprintf(fout, "1\t%d\t\t%s\n", time, temp);fclose(fout);xx1[time] = 1;}fout = fopen("output.txt", "a");fprintf(fout, "1\t%d\t\t%s\n", time, temp);fclose(fout);break;}}for (time = 1; time <= 30; time++){if (strcmp(temp, key2[time]) == 0){if (xx2[time] == 0){fout = fopen("key2.txt", "a");fprintf(fout, "2\t%d\t\t%s\n", time, temp);fclose(fout);xx2[time] = 1;}fout = fopen("output.txt", "a");fprintf(fout, "2\t%d\t\t%s\n", time, temp);fclose(fout);break;}}}}}chin = fgetc(fin);}fout = fopen("output.txt", "a");fprintf(fout, "1\t6\t\t}\n");fclose(fout);}/******* Main函数 *******/void main(){FILE *fread;char charin;char command = 'Q';printf("\n");printf("******************** 词法分析 ********************\n");printf("* *\n");printf("* *\n");printf("* 0 --> 查看保留字表文件 *\n");printf("* 1 --> 查看分隔符表文件 *\n");printf("* 2 --> 查看运算符表文件 *\n");printf("* 3 --> 查看标识符表文件 *\n");printf("* 4 --> 查看整数类型常量表 *\n");printf("* 5 --> 查看浮点类型常量表 *\n");printf("* 6 --> 查看字符类型常量表 *\n");printf("* 7 --> 查看字符串类型常量表 *\n");//printf("* 8 --> 查看注释文件 *\n");printf("* 9 --> 查看内部码文件 *\n");printf("* -------------------------- *\n");printf("* Q --> 退出 *\n");printf("***************************************************************\n");printf("\n");load();scan();printf("\n");printf("分析完成!\n");getchar();printf("\n");printf("请输入命令:");command = getchar();while ((command != 'Q') && (command != 'q')){switch (command){case'0':{printf("*************************\n");printf("\n");fread = fopen("key0.txt", "r");charin = fgetc(fread);while (charin != EOF){putchar(charin);charin = fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case'1':{printf("*************************\n");printf("\n");fread = fopen("key1.txt", "r");charin = fgetc(fread);while (charin != EOF){putchar(charin);charin = fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case'2':{printf("*************************\n");printf("\n");fread = fopen("key2.txt", "r");charin = fgetc(fread);while (charin != EOF){putchar(charin);charin = fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case'3':{printf("*************************\n");printf("\n");fread = fopen("key3.txt", "r");charin = fgetc(fread);while (charin != EOF){putchar(charin);charin = fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case'4':{printf("*************************\n");printf("\n");fread = fopen("c40.txt", "r");charin = fgetc(fread);while (charin != EOF){putchar(charin);charin = fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case'5':{printf("*************************\n");printf("\n");fread = fopen("c41.txt", "r");charin = fgetc(fread);while (charin != EOF){putchar(charin);charin = fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case'6':{printf("*************************\n");printf("\n");fread = fopen("c42.txt", "r");charin = fgetc(fread);while (charin != EOF){putchar(charin);charin = fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case'7':{printf("*************************\n");printf("\n");fread = fopen("c43.txt", "r");charin = fgetc(fread);while (charin != EOF){putchar(charin);charin = fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case'8':{printf("*************************\n");printf("\n");fread = fopen("defination.txt", "r");charin = fgetc(fread);while (charin != EOF){putchar(charin);charin = fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}case'9':{printf("*************************\n");printf("\n");fread = fopen("output.txt", "r");charin = fgetc(fread);while (charin != EOF){putchar(charin);charin = fgetc(fread);}printf("\n");printf("*************************\n");printf("\n");printf("请输入命令:");break;}}command = getchar();}}2、实验2(1)实验内容输入单词串,以”#”结束,如果是文法正确的句子,则输出成功信息,打印“success”,否则输出”error”例如:输入: begin a:=9;b:=0 end #输出: success输入: begin a=9 end #输出: error(2)主要步骤附录:源码#include<stdio.h>#include<string.h>#include<ctype.h>#include<stdlib.h>char GetChar(char *input, int *index, int length);int ClearBlank(char *input, int(*index), int length);int reserve(char *s);void lrparser(char *input, int inputLength, int *index);void yucu(char *input, int inputLength, int *index);void factor(char *input, int inputLength, int *index);void statement(char *input, int inputLength, int *index);void expression(char *input, int inputLength, int *index);void term(char *input, int inputLength, int *index);char *retab[6] = { "begin", "if", "then", "while", "do", "end" };//关键字int syn = 0;int myIsAlpha(char ch){if (islower(ch) == 2 || isupper(ch) == 1){return 1;}else{return 0;}}void scaner(char *input, int inputLength, int *index){char s[256] = ""; //保存当前的字符char ch = GetChar(input, index, inputLength);int nowPosition = 0;int j = 0;if (myIsAlpha(ch) == 1) //如果是字母{while(((ch >= '0'&& ch <= '9') || (myIsAlpha(ch) == 1)) && *index<= inputLength) {s[nowPosition] = ch; //添加到当前字符串中nowPosition++;ch = GetChar(input, index, inputLength);}if ((ch <'0' || ch>'9') && (myIsAlpha(ch) == 0))//进行回退操作,并输出结果{s[nowPosition] = '\0';//添加结束标志j = reserve(s);if (j == 0){syn = 10;}else{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;}}elseif (ch >= '0' && ch <= '9') //如果是数字{while (ch >= '0' && ch <= '9'&& *index <= inputLength) {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'+':{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;}elseif (ch == '>'){syn = 21;return;}else{syn = 20;if (*index>inputLength){return;}else{(*index)--;return;}}case'>':{ch = GetChar(input, index, inputLength);if (ch == '='){syn = 24;return;}else{syn = 23;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;}}}case'=':{syn = 25;return;}case';':{syn = 26;return;}case'(':{syn = 27;return;}case')':{syn = 28;return;}case'#':{syn = 0;return;}case' ':{syn = -1;return;}default:{printf("(非法符号)");。
《编译原理(实验部分)》实验3_PL0语法分析
《编译原理(实验部分)》实验3_PL0语法分析《编译原理》(实验部分)实验3_PL0语法分析一、实验目的加深和巩固对于语法分析的了解和掌握;给出PL/0文法规范,要求编写PL/0语言的语法分析程序。
二、实验设备1、PC 兼容机一台;操作系统为WindowsWindowsXP。
2、Visual C++ 6.0 或以上版本, Windows 2000 或以上版本,汇编工具(在Software 子目录下)。
三、实验原理PL/O语言的编译程序,是用高级语言PASCAL语言书写的。
整个编译过程是由一些嵌套及并列的过程或函数完成。
语法分析是由过程BLOCK完成。
采用自顶向下的递归子程序法。
所产生的目标程序为假象栈式计算机的汇编语言。
对目标程序的执行是由PASCAL语言书写的解释程序进行的。
四、实验步骤实验代码int lp=0;int rp=0;#define getsymdo if(-1==getsym()) return -1#define expressiondo() if(-1==expression()) return -1#define termdo() if(-1==term()) return -1#define factordo() if(-1==factor()) return -1int expression();//语法分析int factor(){if(sym!=ident &&sym!=number&&sym!=lparen){err++;if(err==1) printf("语法错误: \n");printf("error----Factor Needs Ident or Number or Lparen\n");}if ((sym == ident) || (sym == number) || (sym == lparen)){if (sym == ident){WordAnalyse();if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=rparen){err++;if(err==1) printf("语法错误: \n");printf("变量后没有跟上+-*\\ \n");}if(lp==0 && sym==rparen){err++;if(err==1) printf("语法错误: \n");printf("没有左括号匹配\n");}}else if (sym == number){WordAnalyse();if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=rparen) {err++;if(err==1) printf("语法错误: \n");printf("数字后没有跟上+-*\\ \n");}if(lp==0 && sym==rparen){err++;if(err==1) printf("语法错误: \n");printf("没有左括号匹配\n");}}else if (sym == lparen){WordAnalyse();lp++;if(getsym()==-1){lp--;err++;if(err==1) printf("语法错误: \n");printf("error----Needs Rparen \n");return -1;}expressiondo();if (sym == rparen){WordAnalyse();lp--;if(getsym()==-1){return -1;}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus) {err++;if(err==1) printf("语法错误: \n");printf("括号后没有跟上+-*\\ \n");}}else{err++;if(err==1) printf("语法错误: \n");printf("error----Needs Rparen \n");}}}return 0;}int term(){factordo();if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus&&sym!=ident&&sym!=number&&sym!=lparen&&sym!=rparen) {err++;if(err==1) printf("语法错误: \n");printf("不能识别字符\n");}while ((sym == times) || (sym == slash)){WordAnalyse();if(getsym()==-1){err++;if(err==1) printf("语法错误: \n");printf("* \\ 后缺项\n");return -1;}factordo();}return 0;}int expression(){if ((sym == plus) || (sym == minus)){//cout<<strlen(id)<<endl;< p="">if (sym==minus&&2==strlen(ID)+1)flg=1;else{flg=0;WordAnalyse();}getsymdo;termdo();}else{//WordAnalyse();termdo();}if(sym!=times&&sym!=slash&&sym!=plus&&sym!=minus &&sym!=ident&&sym!=number&&sym!=lparen&&sym!=rparen){err++;if(err==1) printf("语法错误: \n");printf("不能识别字符\n");}while ((sym == plus) || (sym == minus)){WordAnalyse();if(getsym()==-1){err++;if(err==1) printf("语法错误: \n");printf("+ - 后缺项\n");return -1;}termdo();}return 0;}int main(int argc, char* argv[]){init();err=0;ifstream fin("in.txt");ofstream fout("out.txt");ch=' ';lp=0;getsymdo;expression();if(err==0) cout<<"语法正确"<<endl;< p="">elsecout<<"语法错误,错误个数: "<<err<<=""></err< </endl;<></strlen(id)<<endl;<>。
《编译原理》实验3_PL0语法分析
《编译原理》实验3_PL0语法分析编译原理是计算机科学中的重要课程,它涉及了程序语言的设计、编译器的构建以及编程语言的解释和执行等方面。
在编译原理的实验部分中,PL0语法分析是一个重要的实验项目。
PL0语法分析是基于PL0语言的语法规则来构建语法分析器,实现对PL0代码的分析和解释。
在这个实验中,我们将完成PL0语法分析器的设计和实现,并对其进行测试。
首先,我们需要了解PL0语言的语法规则。
PL0语言是一种过程型语言,类似于Pascal语言。
它有一套严格的语法规则,包括声明语句、赋值语句、条件语句、循环语句等。
我们需要先从PL0语言文法中提取出规则,然后将其转化为一个语法分析器。
接下来,我们需要设计和实现语法分析器。
语法分析器的主要任务是根据PL0语言的文法规则来分析和解释PL0代码。
我们可以选择使用自顶向下的语法分析方法,如递归下降分析法。
递归下降分析法是一种简单直观的语法分析方法,它通过递归调用子程序来分析和解释代码。
在设计语法分析器时,我们需要根据PL0语言的文法规则来设计相应的文法产生式和语法分析程序。
文法产生式描述了PL0语言的句子结构,它由非终结符和终结符组成,并用箭头“->”来表示产生关系。
语法分析程序则是根据产生式来解释和分析代码。
最后,我们需要编写测试代码来验证语法分析器的正确性。
测试代码应该包含PL0语言的各种语法结构和语法错误,从而验证语法分析器在不同情况下的正确性和鲁棒性。
通过完成这个实验项目,我们能够深入了解编译原理中的语法分析技术,并提升我们的编程能力和问题解决能力。
同时,我们也能够加深对PL0语言的理解,为以后的编程工作打下坚实的基础。
编译原理实验报告 (3)
#include <iostream>
#include <string>
using namespace std;
string keywords[8]={"do","end","for","if","printf","scanf","then","while"};
string optr[4]={"+","-","*","/"};
else if(instring[j]=='>') cout<<"<>"<<'\t'<<"("<<"<>"<<","<<4<<")"<<'\t'<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;
else{cout<<"<"<<"\t("<<"<"<<","<<4<<")"<<"\t"<<"\t关系运算符"<<'\t'<<"("<<line<<","<<row<<")"<<endl;j--;
编译原理实验报告实验三语法分析(LR分析程序)
编译原理实验报告实验三语法分析(LR分析程序)华北⽔利⽔电学院编译原理实验报告2012~2013学年第⼀学期2011 级计算机科学与技术专业班级:2011179 学号:2011179 姓名:⼀、实验题⽬:语法分析(LR分析程序)(1)选择最有代表性的语法分析⽅法LR分析法;(2)选择对各种常见程序语⾔都⽤的语法结构,如赋值语句(尤指表达式)作为分析对象,并且与所选语法分析⽅法要⽐较贴切。
⼆、实验内容(1)根据给定⽂法,先求出FirstVt和LastVt集合,构造算符优先关系表(要求算符优先关系表输出到屏幕或者输出到⽂件);(2)根据算法和优先关系表分析给定表达式是否是该⽂法识别的正确的算术表达式(要求输出归约过程)(3)给定表达式⽂法为:G(E’): E’→#E#E→E+T | TT→T*F |FF→(E)|i(4) 分析的句⼦为:(i+i)*i和i+i)*i三、根据以上⽂法构造出的LR(1)分析表为:四、程序源代using System;using System.Text;using System.IO;namespace Syntax_Analyzer{class Syntax{StreamReader myStreamReader;int t;int[] lengh;int l =0;string[] grammar;int s=0;string[] Word;int w=0;int[] wordNum ;int n =0;int[,] LR;public Syntax(){lengh = new int[7];grammar=new string[7];Word=new string[100];wordNum = new int[100];LR=new int[30,30];}public void analyzer(){//读⼊grammarSyntax myTextRead=new Syntax();Console.WriteLine("-----------------------------语法分析开始---------------------------------\n"); //***************************//循环读取⽂法//***************************string strStart;strStart="grammar.txt";myTextRead.myStreamReader=new StreamReader(strStart);string strBufferStart;int uu=0;do{strBufferStart =myTextRead.myStreamReader.ReadLine();if(strBufferStart==null)break;foreach (String subString in strBufferStart.Split()){grammar[uu]=subString; //每⾏⽂法存⼊grammar[]uu++;}}while (strBufferStart!=null);myTextRead.myStreamReader.Close();//***************************//循环读取lengh//***************************strStart="lengh.txt";myTextRead.myStreamReader=new StreamReader(strStart);uu=0;do{strBufferStart =myTextRead.myStreamReader.ReadLine();if(strBufferStart==null)break;foreach (String subString in strBufferStart.Split()){lengh[uu]=Convert.ToInt32(subString); //每⾏⽂法存⼊grammar[] uu++;}}while (strBufferStart!=null);myTextRead.myStreamReader.Close();//****************************// 读⼊⽂件,进⾏语法分析////****************************string strReadFile;strReadFile="input.txt";myTextRead.myStreamReader=new StreamReader(strReadFile); string strBufferText;int wid =0;Console.WriteLine("分析读⼊程序(记号ID):\n");do{strBufferText =myTextRead.myStreamReader.ReadLine();if(strBufferText==null)break;foreach (String subString in strBufferText.Split()){if(subString!=""){int ll;if(subString!=null){ll= subString.Length; //每⼀个长度}else{break;}int a=ll+1;char[] b = new char[a];StringReader sr = new StringReader(subString); sr.Read(b, 0, ll); //把substring 读到char[]数组⾥int sort=(int)b[0];// word[i] 和wordNum[i]对应//先识别出⼀整个串,再根据开头识别是数字还是字母Word[wid]=subString;if(subString.Equals("+")){wordNum[wid]=0;}else{if(subString.Equals("*")){wordNum[wid]=1;}else{if(subString.Equals("(")){wordNum[wid]=2;}else{if(subString.Equals(")")){wordNum[wid]=3;}else{if(subString.Equals("i")){wordNum[wid]=4;}}}}}Console.Write(subString+"("+wordNum[wid]+")"+" ");wid++;}}Console.WriteLine("\n");}while (strBufferText!=null);wordNum[wid]=5;myTextRead.myStreamReader.Close();//*********************************//读⼊LR分析表////***********************************string strLR;strLR="LR-table.txt";myTextRead.myStreamReader=new StreamReader(strLR); string strBufferLR;int pp=0;do{strBufferLR =myTextRead.myStreamReader.ReadLine(); if(strBufferLR==null)break;else{int j=0;foreach (String subString in strBufferLR.Split())if(subString!=null){int lllr=Convert.ToInt16(subString);LR[pp,j]=lllr; //把⾏与列读⼊数组j++;}}}pp++;}while (strBufferLR!=null);myTextRead.myStreamReader.Close();int[] state = new int[100];string[] symbol =new string[100];state[0]=0;symbol[0]="#";int p1=0;int p2=0;Console.WriteLine("\n按⽂法规则归约顺序如下:\n"); //***************//归约算法//***************while(true){int j,k;j=state[p2];k=wordNum[p1];t=LR[j,k]; //当出现t为的时候if(t==0){//错误类型string error = "" ;if (k == 0)error = "+";if (k == 1)error = "*";elseif (k == 2)error = "(";elseif (k == 3)error = ")";elseif (k == 4)error = "i";elseerror = " 其它错误!";Console.WriteLine("\n检测结果:");Console.WriteLine("代码中存在语法错误");Console.WriteLine("错误状况:错误状态编号为"+j+" 读头下符号为"+error); break;}else{if(t==-100) //-100为达到接受状态{Console.WriteLine("\n");Console.WriteLine("\n检测结果:");Console.WriteLine("代码通过语法检测");break;}if(t<0&&t!=-100) //归约{string m=grammar[-t];Console.Write(m+" "); //输出开始符int length=lengh[-t];p2=p2-(length-1);Search mySearch=new Search();int right=mySearch.search(m);if(right==0){Console.WriteLine("\n");Console.WriteLine("代码中有语法错误");break;}int a=state[p2-1];int LRresult= LR[a,right];state[p2]=LRresult;symbol[p2]=m;}if(t>0){p2=p2+1;state[p2]=t;symbol[p2]=Convert.ToString(wordNum[p1]);p1=p1+1;}}}myTextRead.myStreamReader.Close();Console.WriteLine("-----------------------------语法分析结束---------------------------------\n"); Console.Read();}}class Search{public int search(string x){string[] mysymbol=new string[3];mysymbol[0]="E";mysymbol[1]="T";mysymbol[2]="F";int r = 0;for(int s=0;s<=2;s++){if(mysymbol[s].Equals(x))r=s+6 ;}return r;}}}五、测试结果输⼊”( i + i ) * i”字符串,分析如下图所⽰输⼊”i + i ”字符串,分析如下图所⽰六、⼩结(包括收获、⼼得体会、存在的问题及解决问题的⽅法、建议等)本次实验是LR分析法,LR分析法是⼀种有效的⾃上⽽下分析技术,在⾃左向右扫描输⼊串时就能发现其中的任何错误。
编译原理实验3报告
班级:学号:姓名:实验7-8 预测分析表方法一、实验目的理解预测分析表方法的实现原理。
二、实验内容提示测试数据:1.算术表达式文法E→TAA → +TA|- TA|εT→FBB →*FB |/ FB |%FB|εF→(E) |id|num给定一符合该文法的句子,如id+id*id#,运行预测分析程序,给出分析过程和每一步的分析结果。
三.实验要求程序源代码及参考图:部分代码:void analysis ( nonterminator nont, terminator term , stack stac ){string wenjian;string rece;string ch;string top_stack;cout<<"请输入要测试的文件:";cin>>wenjian;ifstream infile ( wenjian.c_str (), ios::in );if ( !infile )cout<<"不存在"<<wenjian<<endl;else{print ();stac.push ( "E" );infile>>ch;while ( ch != "\0"){top_stack = stac.inn [stac.top];if ( term.is_term ( ch ) ){if ( top_stack == "#" && ch == "#" ){//结束stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t本次匹配结束!"<<endl;infile>>ch;if ( ch != "\0" ){cout<<"下一条语句开始执行匹配:"<<endl;stac.push ( "E" );continue;}else{cout<<"\t\t文件语法分析完毕!\n"<<endl;break;}}else if ( term.is_term ( top_stack ) ) //终结符{if ( top_stack == ch ) {stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t匹配终结符:"<<ch<<endl;stac.pop ( );}else{stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t出错跳过该符号"<<ch<<endl;}}else if ( ( rece = find ( top_stack, ch ) ) != "\0" )//非终结符{if ( rece == empty ){//指向空stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t展开非终结符:"<<top_stack<<"->ε"<<endl;stac.pop ();continue;}else if ( rece == "ERROR" )//出错{if ( nont.is_follow ( stac.inn [stac.top-1], ch ) )//属于follow集error ( 1 ){stac.display ();cout<<"\t\t"<<stac.inn [--stac.top] <<"\t\t"<<ch<<"\t\t出错,弹出该栈顶元素"<<endl;}else{//不属于follow集error ( 2 )stac.display ();cout<<"\t\t"<<stac.inn [stac.top] <<"\t\t"<<ch<<"\t\t 出错,不属于follow集故须跳过符号"<<ch <<endl;infile>>ch;}continue;}else//指向正常的非终结符{if ( rece == "id" || rece == "num" ){stac.pop ( );stac.push ( rece );}else{string str2;int i = 0;while ( rece[i] != '\0' )i ++;stac.pop ();for ( int j = i - 1; j >= 0; j -- ){str2 += rece[j];stac.push ( str2 );str2 = "\0";}}stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t展开非终结符:"<<top_stack<<"->"<<rece<<endl;continue;}}}else {stac.display ();cout<<"\t\t"<<top_stack<<"\t\t"<<ch<<"\t\t出错,跳过,无法识别该标识符"<<ch<<endl;}infile>>ch;}}infile.close ();}输出形式参考下图:四、实验总结通过实验,我对LL1()的算法有了初步的了解,基本能够编出代码,虽然有的地方处理的不是很好,我想通过后期的改正能够把程序改的完美。
编译原理语义分析实验报告
实验3 语义分析实验报告一、实验目的二、通过上机实习, 加深对语法制导翻译原理的理解, 掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
三、实验要求四、采用递归下降语法制导翻译法, 对算术表达式、赋值语句进行语义分析并生成四元式序列。
五、算法思想1.设置语义过程。
(1)emit(char *result,char *ag1,char *op,char *ag2)该函数的功能是生成一个三地址语句送到四元式表中。
四元式表的结构如下:struct{ char result[8];char ag1[8];char op[8];char ag2[8];}quad[20];(2) char *newtemp()该函数回送一个新的临时变量名, 临时变量名产生的顺序为T1, T2, …char *newtemp(void){ char *p;char m[8];p=(char *)malloc(8);k++;itoa(k,m,10);strcpy(p+1,m);p[0]=’t’;return(p);}六、 2.函数lrparser 在原来语法分析的基础上插入相应的语义动作: 将输入串翻译成四元式序列。
在实验中我们只对表达式、赋值语句进行翻译。
源程序代码:#include<stdio.h>#include<string.h>#include<iostream.h>#include<stdlib.h>struct{char result[12];char ag1[12];char op[12];char ag2[12];}quad;char prog[80],token[12];char ch;int syn,p,m=0,n,sum=0,kk; //p是缓冲区prog的指针, m是token的指针char *rwtab[6]={"begin","if","then","while","do","end"};void scaner();char *factor(void);char *term(void);char *expression(void);int yucu();void emit(char *result,char *ag1,char *op,char *ag2);char *newtemp();int statement();int k=0;void emit(char *result,char *ag1,char *op,char *ag2){strcpy(quad.result,result);strcpy(quad.ag1,ag1);strcpy(quad.op,op);strcpy(quad.ag2,ag2);cout<<quad.result<<"="<<quad.ag1<<quad.op<<quad.ag2<<endl;}char *newtemp(){char *p;char m[12];p=(char *)malloc(12);k++;itoa(k,m,10);strcpy(p+1,m);p[0]='t';return (p);}void scaner(){for(n=0;n<8;n++) token[n]=NULL;ch=prog[p++];while(ch==' '){ch=prog[p];p++;}if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){m=0;while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){token[m++]=ch;ch=prog[p++];}token[m++]='\0';p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){syn=n+1;break;}}else if((ch>='0'&&ch<='9')){{sum=0;while((ch>='0'&&ch<='9')){sum=sum*10+ch-'0';ch=prog[p++];}}p--;syn=11;if(sum>32767)syn=-1;}else switch(ch){case'<':m=0;token[m++]=ch;ch=prog[p++];if(ch=='>'){syn=21;token[m++]=ch;}else if(ch=='='){syn=22;token[m++]=ch;}else{syn=23;p--;}break;case'>':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=24;token[m++]=ch;}else{syn=20;p--;}break;case':':m=0;token[m++]=ch;ch=prog[p++];if(ch=='='){syn=18;token[m++]=ch;}else{syn=17;p--;}break;case'*':syn=13;token[0]=ch;break; case'/':syn=14;token[0]=ch;break; case'+':syn=15;token[0]=ch;break; case'-':syn=16;token[0]=ch;break; case'=':syn=25;token[0]=ch;break; case';':syn=26;token[0]=ch;break; case'(':syn=27;token[0]=ch;break; case')':syn=28;token[0]=ch;break; case'#':syn=0;token[0]=ch;break; default: syn=-1;break;}}int lrparser(){//cout<<"调用lrparser"<<endl;int schain=0;kk=0;if(syn==1){scaner();schain=yucu();if(syn==6){scaner();if(syn==0 && (kk==0))cout<<"success!"<<endl;}else{if(kk!=1)cout<<"缺end!"<<endl;kk=1;}}else{cout<<"缺begin!"<<endl;kk=1;}return(schain);}int yucu(){// cout<<"调用yucu"<<endl;int schain=0;schain=statement();while(syn==26){scaner();schain=statement();}return(schain);}int statement(){//cout<<"调用statement"<<endl;char *eplace,*tt;eplace=(char *)malloc(12);tt=(char *)malloc(12);int schain=0;switch(syn){case 10:strcpy(tt,token);scaner();if(syn==18){scaner();strcpy(eplace,expression());emit(tt,eplace,"","");schain=0;}else{cout<<"缺少赋值符!"<<endl;kk=1;}return(schain);break;}return(schain);}char *expression(void){char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12);ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt =(char *)malloc(12);strcpy(eplace,term ()); //调用term分析产生表达式计算的第一项eplacewhile((syn==15)||(syn==16)){if(syn==15)strcpy(tt,"+");else strcpy(tt,"-");scaner();strcpy(ep2,term()); //调用term分析产生表达式计算的第二项ep2strcpy(tp,newtemp()); //调用newtemp产生临时变量tp存储计算结果emit(tp,eplace,tt,ep2); //生成四元式送入四元式表strcpy(eplace,tp);}return(eplace);}char *term(void){// cout<<"调用term"<<endl;char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12);ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt=(char *)malloc(12);strcpy(eplace,factor());while((syn==13)||(syn==14)){if(syn==13)strcpy(tt,"*");else strcpy(tt,"/");scaner();strcpy(ep2,factor()); //调用factor分析产生表达式计算的第二项ep2strcpy(tp,newtemp()); //调用newtemp产生临时变量tp存储计算结果emit(tp,eplace,tt,ep2); //生成四元式送入四元式表strcpy(eplace,tp);}return(eplace);}char *factor(void){char *fplace;fplace=(char *)malloc(12);strcpy(fplace,"");if(syn==10){strcpy(fplace,token); //将标识符token的值赋给fplacescaner();}else if(syn==11){itoa(sum,fplace,10);scaner();}else if(syn==27){scaner();fplace=expression(); //调用expression分析返回表达式的值if(syn==28)scaner();else{cout<<"缺)错误!"<<endl;kk=1;}}else{cout<<"缺(错误!"<<endl;kk=1;}return(fplace);}void main(){p=0;cout<<"**********语义分析程序**********"<<endl;cout<<"Please input string:"<<endl;do{cin.get(ch);prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();}七、结果验证1、给定源程序begin a:=2+3*4; x:=(a+b)/c end#输出结果2、源程序begin a:=9; x:=2*3-1; b:=(a+x)/2 end#输出结果八、收获(体会)与建议通过此次实验, 让我了解到如何设计、编制并调试语义分析程序, 加深了对语法制导翻译原理的理解, 掌握了将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
实验三编译原理综合实验报告——(LR(0)语法分析的实现)
m_pTree->SetControlInfo(IDC_TREE1, RESIZE_BOTH);
m_pTree->SetControlInfo(IDOK, ANCHORE_BOTTOM | ANCHORE_RIGHT);
void CAnalyzeDlg::OnOK()
{
// TODO: Add extra validation here
//CDialog::OnOK();
}
void CAnalyzeDlg::OnCancel()
{
// TODO: Add extra cleanup here
六、实验原理、数据(程序)记录
(一)实验原理:
利用LR(k)类分析算法的四个步骤,分别实现"移进"、"归约"、"成功"、"报错"的分析能力。同时采用相应的数据结构实现分析表的描述。
(二)程序框架:
#include "stdafx.h"
#include "GoData.h"
GoData::GoData()
assert(j != -1);
out.WriteString(GetStepInfo(iStep, Status, Symbol, m_input.Right(m_input.GetLength() - iPos), ToDo, j));
for(i = 0; i < m_g.GetPrecept(ToDo.two).GetRight().length(); i++)
编译原理实验报告3-LL(1)文法构造
实验3 LL(1)文法构造一、实验目的熟悉LL(1)文法的分析条件,了解LL(1)文法的构造方法。
二、实验内容1、编制一个能够将一个非LL(1)文法转换为LL(1)文法;2、消除左递归;3、消除回溯。
三、实验要求1、将一个可转换非LL(1)文法转换为LL(1)文法,要经过两个阶段,1)消除文法左递归,2)提取左因子,消除回溯。
2、提取文法左因子算法:1)对文法G的所有非终结符进行排序2)按上述顺序对每一个非终结符Pi依次执行:for( j=1; j< i-1;j++)将Pj代入Pi的产生式(若可代入的话);消除关于Pi的直接左递归:Pi -> Piα|β ,其中β不以Pi开头,则修改产生式为:Pi —> βPi′Pi′—>αPi′|ε3)化简上述所得文法。
3、提取左因子的算法:A—>δβ1|δβ2|…|δβn|γ1|γ2|…|γm(其中,每个γ不以δ开头) 那么,可以把这些产生式改写成A —>δA′|γ1| γ2…|γmA′—>β1|β2|…|βn4、利用上述算法,实现构造一个LL(1)文法:1)从文本文件g.txt中读入文法,利用实验1的结果,存入实验1设计的数据结构;2)设计函数remove_left_recursion()和remove_left_gene()实现消除左递归和提取左因子算法,分别对文法进行操作,消除文法中的左递归和提出左因子;3)整理得到的新文法;4)在一个新的文本文件newg.txt输出文法,文法输出按照一个非终结符号一行,开始符号引出的产生式写在第一行,同一个非终结符号的候选式用“|”分隔的方式输出。
四、实验环境PC微机DOS操作系统或Windows操作系统Turbo C程序集成环境或VisualC++ 程序集成环境五、实验步骤1、学习LL(1)文法的分析条件;2、学习构造LL(1)文法的算法;3、结合实验1给出的数据结构,编程实现构造LL(1)文法的算法;4、结合实验1编程和调试实现对一个具体文法运用上述算法,构造它的LL(1)文法形式;5、把实验结果写入一个新建立的文本文件。
编译原理 实验三 实验报告
实验报告第 1 页专业____软件工程________ 班级____2_____ 姓名_71李飞强77欧艺欣81吴文浩89张泰鑫__ 组别:第四组实验日期:2014年 3 月26 日报告退发(订正、重做)课程编译原理实验名称递归下降的预测分析一、实验目的1. 学会用语法图来形式化地描述一门简单的语言;2. 掌握递归下降的预测分析;3. 掌握词法分析。
二、实验环境Visual Studio 或 GCC 或Eclipse三、实验内容、步骤和结果分析实验内容:请基于递归下降的分析方法(教材P55页),编写一个“语法图.doc”所对应语言的语法分析器。
该语法分析器能读入一个源代码文件(如“test.c”文件所示),并判断其中的源代码是否符合“语法图.doc”的规定。
如果符合,打印出Yes;如果不符合,打印出No。
(所用编程语言不限)C语言版:#include<stdio.h>#include<string.h>#include<stdlib.h>#define MaxIdLen 20 //标志符的最大长度#define KeyWordsCount 5 //该语言拥有的关键字个数#define BoolValueCount 2 //bool类型可能取值的个数#define SymTypeCount 17 //symType个数enum SymType//枚举{OR , //或AND, //与LP, //左括号RP, //右括号ID, //标志符ASSIGN, //赋值LB, //左大括号RB, //右大括号COMMA, //逗号SEMICOLON, //分号UNDEFINED, //未定义BOOLVALUE, //bool类型的值IF, //ifELSE, //elseWHILE, //whilePRINTF, //printfBOOL, //bool};enum boolValue{TRUE,FALSE,};//关键字static char * keywords[KeyWordsCount] = { "if","else","while","printf","bool",};//关键字对应类别static int keyType[KeyWordsCount] = { IF,ELSE,WHILE,PRINTF,BOOL,};static char * boolvalue[BoolValueCount]={"true","false",};static int boolValueType[BoolValueCount]={TRUE,FALSE,};char ch=' '; //当前字符char id[MaxIdLen+1]; //当前符号串int token; //当前记号(的类型)int value; //当前记号的值FILE * fp; //用来打开要识别的源代码文件int lineNum=1; //要识别的代码行数bool isPass = false ; //判断识别的代码是否全部合法void getToken();void program();void program();void statement();void definition();void term();void factor();void expression();void match(int t);void main(){fopen_s(&fp,"D:\\test.c","r");getToken();program();if(isPass)printf("Y\n");else printf("N\n");fclose(fp);}/****************************************lexical*****************************************/int getKeyWord(char * str){for(int i=0;i<KeyWordsCount;i++)if(strcmp(str,keywords[i])==0)return keyType[i];return UNDEFINED;}int getBoolValue(char* str){for(int i=0;i<BoolValueCount;i++)if(strcmp(str,boolvalue[i])==0){value = boolValueType[i];return BOOLVALUE;}return UNDEFINED;}bool isLetter(char ch){return (ch>='A'&&ch<='Z')||(ch>='a'&&ch<='z'); }bool isDigit(char ch){return ch>='0'&&ch<='9';}void nextChar(){ch = fgetc(fp);}void getToken(){while(ch==' '||ch=='\t'||ch=='\r'||ch=='\n'){if(ch == '\n')lineNum++;nextChar();}if(isLetter(ch)){int index=0;id[index++] = ch;nextChar();while(isLetter(ch) || isDigit(ch)){if(index<MaxIdLen){id[index++] = ch;nextChar();}else{//cout<<"identifier is too long."<<endl;//exit(1);}}id[index]='\0';token = getKeyWord(id);if(token == UNDEFINED)token = getBoolValue(id);if(token == UNDEFINED){token = ID;}}else if(ch == '='){token = ASSIGN;nextChar();}else if(ch=='|'){nextChar();if(ch=='|'){token=OR;nextChar();}elseexit(1);}else if(ch=='&'){nextChar();if(ch=='&'){token=AND;nextChar();}elseexit(1);}else if(ch == ';'){token = SEMICOLON;nextChar();}else if(ch == '('){token = LP;nextChar();}else if(ch == ')'){token = RP;nextChar();}else if(ch == ','){token = COMMA;nextChar();}else if(ch == '{'){token = LB;nextChar();}else if(ch == '}'){token = RB;nextChar();}else if(ch == EOF){printf(" EOF!\n");isPass = true;}else{printf("第%d行不能识别的符号!\n",lineNum );exit(1);}}/****************************************grammar*****************************************/void match(int t){if(t == token){getToken();}else{printf("大概在第%d行错误\n",lineNum);exit(1);}}void expression(){term();while(token == OR){match(OR);term();}}void factor(){if(token == BOOLVALUE && value == TRUE)match(BOOLVALUE);else if(token == BOOLVALUE && value == FALSE) match(BOOLVALUE);else if(token == LP){match(LP);expression();match(RP);}else if(token == ID)match(ID);}void term(){factor();while(token == AND){match(AND);factor();}}void definition(){do{match(BOOL);match(ID);match(ASSIGN);expression();match(SEMICOLON);}while(token == BOOL);}void statement(){if(token == IF){match(IF);match(LP);expression();match(RP);statement();if(token == ELSE){match(ELSE);statement();}}else if(token == PRINTF){match(PRINTF);match(LP);expression();while(token == COMMA){match(COMMA);expression();}match(RP);match(SEMICOLON);}else if(token == WHILE){match(WHILE);match(LP);expression();match(RP);statement();}else if(token == LB){match(LB);do{statement();}while(token != RB);match(RB);}else if(token == ID){match(ID);match(ASSIGN);expression();match(SEMICOLON);}else if(token == SEMICOLON){match(SEMICOLON);}}void program(){definition();statement();}Java版:(吴文浩)Java版的关键代码:// 由语法分析带动翻译public void parse(String src) {this.lexer = new GrammarLexer(src);lookahead = lexer.getToken();program();}private void match(TokenType type) {// 如果记号lookahead的类型是type,则取下一个记号System.out.println("------------>" + type);if (lookahead.tokenType.equals(type)) {lookahead = lexer.getToken();} else {error("NO");// 否则报错}}private void error(String str) {// out.println(str);System.out.println(str);System.exit(-1);}/*** program:程序 definition----->statement-------->*/public void program() {definition();//定义statement();// 声明}// definition:定义/*** bool-->id-->=-->expression-->;*/public void definition() {do {match(TokenType.BOOLEAN);match(TokenType.ID);match(TokenType.EQUAL);expression();match(TokenType.SEMICOLON);// 匹配分号} while (lookahead.isBoolean());}// statement:声明public void statement() {if(lookahead.isIf()) {// -->if-->(-->expression-->)-->statement--->match(TokenType.IF);match(TokenType.LeftP);expression();match(TokenType.RightP);statement();if(lookahead.isElse()) {//缺陷:如果用全部代码测试时,程序走到这里停止了,while循环后的语句将不能执行!match(TokenType.ELSE);statement();} else {}} else if (lookahead.isWhile()) {match(TokenType.WHILE);match(TokenType.LeftP);expression();match(TokenType.RightP);statement();} else if (lookahead.isPrint()) {match(TokenType.PRINT);match(TokenType.LeftP);expression();while (lookahead.isComma()) {match(MA);expression();}match(TokenType.RightP);match(TokenType.SEMICOLON);} else if (lookahead.isSemicolon()) {// ;match(TokenType.SEMICOLON);} else if (lookahead.isLeftBrace()) {match(TokenType.LeftBrace);statement();while(!lookahead.isRightBrace() || lookahead.isId() ){//必须加入lookahead.isId()否则a = false;运行不出来(语法图缺陷吧!)statement();}match(TokenType.RightBrace);} else if (lookahead.isId()) {// id = expression;// System.out.println("++++++++++++++++++++");match(TokenType.ID);match(TokenType.EQUAL);expression();match(TokenType.SEMICOLON);} else {}}/***expression:式子-------->term()----(---->||------->term()---->);*/private void expression() {term();while (lookahead.isOr()) {// 如果是||就继续循环处理match(TokenType.OR);term();}}/***term:项 Factor(); While(match(‘&&’)){ Factor(); }*/private void term() {factor();while (lookahead.isAnd()) {// 判断是&&就继续进行match(TokenType.AND);factor();}}/*** --->(------>expression--------->)--------->* ---->true---->* ---->false---->* ---->id------>*/private void factor() {if (lookahead.isTrue()) {match(TokenType.TRUE);} else if (lookahead.isLeftP()) {match(TokenType.LeftP);expression();match(TokenType.RightP);} else if (lookahead.isFalse()) {match(TokenType.FALSE);} else if (lookahead.isId()) {match(TokenType.ID);} else{}}/*** 获取下一个Token*/public Token getToken() {int value = 0;char cur;while (true) {if (index >= src.length())return Token.EOF;else {// 取下一字符cur = next();// 如果下一个字符是空白,继续读取字符if (this.isBlank(cur))continue;else if (this.isAlpha(cur)) {// 字符缓冲区StringBuilder buffer = new StringBuilder();buffer.append(cur);while (isAlpha((char) peek())) {buffer.append(next());}if(buffer.toString().equals(KeyWord.BOOLEAN)) {return new Token(TokenType.BOOLEAN, buffer.toString());} else if (buffer.toString().equals(KeyWord.FALSE)) {return new Token(TokenType.FALSE, buffer.toString());} else if (buffer.toString().equals(KeyWord.TRUE)) {return new Token(TokenType.TRUE, buffer.toString());} else if(buffer.toString().equals(KeyWord.IF)) {return new Token(TokenType.IF, buffer.toString());} else if (buffer.toString().equals(KeyWord.WHILE)) {return new Token(TokenType.WHILE, buffer.toString());} else if (buffer.toString().equals(KeyWord.PRINT)) {return new Token(TokenType.PRINT, buffer.toString());} else {return new Token(TokenType.ID, buffer.toString());}} else if (cur == ',') {return MA;} else if (cur == '(') {return Token.LeftP;} else if (cur == ')') {return Token.RightP;} else if (cur == '|' && next() == '|') {return Token.OR;// 或者} else if (cur == '&' && next() == '&') {return Token.AND;// 且} else if (cur == '=') {return Token.EQUAL;} else if (cur == ';') {return Token.SEMICOLON;// 分号} else if (cur == '{') {// 左大括号return Token.LeftBrace;} else if (cur == '}') {return Token.RightBrace;} else if (cur == '\n') {line++;} else {this.error();}}}}运行这个测试代码的截图:String src = "boolean a = true;boolean b = false;boolean c = (a && b);if( a || b) print(a,b);else print(c);";运行这个测试代码的截图:String src = "boolean a = true; while(a && (b||c)){print(a,b,c);a = false;}";四、讨论(说明实验过程中遇到的问题及解决办法;未解决/需进一步研讨的问题或建议新实验方法等)在text.c中先是声明bool类型,然后是if语句,最后是while语句。
编译原理实验教程课程设计
编译原理实验教程课程设计背景编译原理是计算机科学专业的一门重要课程,它研究如何将高级语言翻译成低级语言,以便计算机执行。
编译器是实现这一过程的关键工具。
然而,对于很多学生来说,编译原理的理论知识学习起来比较抽象,难以掌握。
因此,本文旨在为编译原理的学习提供一些实验教程的设计思路。
实验一:词法分析器词法分析器是编译器的第一个模块,它的作用是将输入的字符流转化为一个个单词符号。
本实验的目的是设计并实现一个简单的词法分析器,实现以下功能:1.识别输入的程序中所包含的各个单词符号。
2.输出所有单词符号及其对应的单词类型。
3.当遇到不合法单词符号时,给出相应的错误提示。
具体实现可以采用有限自动机的思想,使用正则表达式或者手写代码,实现对于不同的单词类型的识别,并对于不合法单词进行识别和报错处理。
实验二:语法分析器语法分析器是编译器的第二个模块,它的作用是将词法分析器输出的单词序列转换成语法树或者语法分析表,以便后续进行语义分析和目标代码生成。
本实验的目的是设计并实现一个简单的语法分析器,实现以下功能:1.识别输入的程序是否符合所设计的文法规则。
2.输出语法树或语法分析表。
具体实现可以采用自上而下的递归下降分析法或自下而上的移进-规约分析法,实现对于不同的句型的识别,并生成语法树或语法分析表。
实验三:语义分析器语义分析器是编译器的第三个模块,它的作用是对语法分析器输出的语法树或语法分析表进行语义分析,并生成中间代码。
本实验的目的是设计并实现一个简单的语义分析器,实现以下功能:1.对语法树或语法分析表进行遍历,识别语法错误和语义错误,给出相应的错误提示。
2.生成中间代码。
具体实现可以采用语义规则和符号表的检查方式,识别语法错误和语义错误,并在生成中间代码时,根据中间代码语言的规则进行实现。
实验四:目标代码生成器目标代码生成器是编译器的第四个模块,它的作用是将中间代码转换成机器语言,以便计算机执行。
本实验的目的是设计并实现一个简单的目标代码生成器,实现以下功能:1.将中间代码转换成机器语言。
编译原理实验教案
一、实验目的与要求1. 实验目的(1) 理解编译原理的基本概念和流程。
(2) 掌握常用的编译方法和技术。
(3) 熟练使用编译器开发工具。
2. 实验要求(1) 熟悉计算机专业基础知识。
(2) 掌握C/C++编程语言。
(3) 了解基本的编译原理。
二、实验环境1. 硬件环境(1) 计算机一台。
(2) 编译器开发工具(如GCC、Clang等)。
2. 软件环境(1) 操作系统(如Windows、Linux等)。
(2) 文本编辑器或集成开发环境(如Visual Studio、Eclipse等)。
三、实验内容1. 实验一:词法分析(1) 实现一个简单的词法分析器,识别出关键字、标识符、常量等。
(2) 分析输入的程序,输出词法分析结果。
2. 实验二:语法分析(1) 实现一个简单的语法分析器,根据给定的语法规则分析输入的程序。
(2) 分析输入的程序,输出语法分析树。
3. 实验三:语义分析(1) 实现一个简单的语义分析器,检查程序中的语义错误。
(2) 分析输入的程序,输出语义分析结果。
4. 实验四:中间代码(1) 实现一个简单的中间代码器,将转换为中间代码表示。
(2) 对输入的程序进行转换,输出中间代码。
5. 实验五:目标代码(1) 实现一个简单的目标代码器,将中间代码转换为目标代码。
(2) 对输入的中间代码进行转换,输出目标代码。
四、实验步骤与方法1. 实验一:词法分析(1) 编写词法分析器的代码。
(2) 测试并调试词法分析器。
2. 实验二:语法分析(1) 编写语法分析器的代码。
(2) 测试并调试语法分析器。
3. 实验三:语义分析(1) 编写语义分析器的代码。
(2) 测试并调试语义分析器。
4. 实验四:中间代码(1) 编写中间代码器的代码。
(2) 测试并调试中间代码器。
5. 实验五:目标代码(1) 编写目标代码器的代码。
(2) 测试并调试目标代码器。
五、实验注意事项1. 按照实验要求编写代码,注意代码规范和可读性。
编译原理实验三-自下而上语法分析报告及语义分析报告.docx
上海电力学院编译原理课程实验报告实验名称:实验三自下而上语法分析及语义分析院系:计算机科学与技术学院专业年级:学生姓名:学号:指导老师:实验日期:实验三自上而下的语法分析一、实验目的:通过本实验掌握LR分析器的构造过程,并根据语法制导翻译,掌握属性文法的自下而上计算的过程。
二、实验学时:4学时。
三、实验内容根据给出的简单表达式的语法构成规则(见五),编制LR分析程序,要求能对用给定的语法规则书写的源程序进行语法分析和语义分析。
对于正确的表达式,给出表达式的值。
对于错误的表达式,给出出错位置。
四、实验方法采用LR分析法。
首先给出S-属性文法的定义(为简便起见,每个文法符号只设置一个综合属性,即该文法符号所代表的表达式的值。
属性文法的定义可参照书137页表6.1),并将其改造成用LR分析实现时的语义分析动作(可参照书145页表6.5)。
接下来给出LR分析表。
然后程序的具体实现:●LR分析表可用二维数组(或其他)实现。
●添加一个val栈作为语义分析实现的工具。
●编写总控程序,实现语法分析和语义分析的过程。
注:对于整数的识别可以借助实验1。
五、文法定义简单的表达式文法如下:(1)E->E+T(2)E->E-T(3)E->T(4)T->T*F(5)T->T/F(6)T->F(7)F->(E)(8)F->i五、处理程序例和处理结果例示例1:20133191*(20133191+3191)+ 3191#六、源代码【cifa.h】//cifa.h#include<string> using namespace std;//单词结构定义struct WordType{int code;string pro;};//函数声明WordType get_w();void getch();void getBC();bool isLetter();bool isDigit();void retract();int Reserve(string str); string concat(string str); 【Table.action.h】//table_action.hclass Table_action{int row_num,line_num;int lineName[8];string tableData[16][8]; public:Table_action(){row_num=16;line_num=8;lineName[0]=30;lineName[1]=7;lineName[2]=13;lineName[3]=8;lineName[4]=14;lineName[5]=1;lineName[6]=2;lineName[7]=15;lineName[8]=0;for(int m=0;m<row_num;m++) for(int n=0;n<line_num;n++) tableData[m][n]="";tableData[0][0]="S5";tableData[0][5]="S4";tableData[1][1]="S6";tableData[1][2]="S12";tableData[1][7]="acc";tableData[2][1]="R3";tableData[2][2]="R3";tableData[2][3]="S7";tableData[2][6]="R3"; tableData[2][7]="R3"; tableData[3][1]="R6"; tableData[3][2]="R6"; tableData[3][3]="R6"; tableData[3][4]="R6"; tableData[3][6]="R6"; tableData[3][7]="R6"; tableData[4][0]="S5"; tableData[4][5]="S4"; tableData[5][1]="R8"; tableData[5][2]="R8"; tableData[5][3]="R8"; tableData[5][4]="R8"; tableData[5][6]="R8"; tableData[5][7]="R8"; tableData[6][0]="S5"; tableData[6][5]="S4"; tableData[7][0]="S5"; tableData[7][5]="S4"; tableData[8][1]="S6";tableData[8][6]="S11"; tableData[9][1]="R1"; tableData[9][2]="R1"; tableData[9][3]="S7"; tableData[9][4]="S13"; tableData[9][6]="R1"; tableData[9][7]="R1"; tableData[10][1]="R4"; tableData[10][2]="R4"; tableData[10][3]="R4"; tableData[10][4]="R4"; tableData[10][6]="R4"; tableData[10][7]="R4"; tableData[11][1]="R7"; tableData[11][2]="R7"; tableData[11][3]="R7"; tableData[11][4]="R7"; tableData[11][6]="R7"; tableData[11][7]="R7"; tableData[12][0]="S5"; tableData[12][5]="S4";tableData[13][5]="S4";tableData[14][1]="R2";tableData[14][2]="R2";tableData[14][3]="S7";tableData[14][4]="S13";tableData[14][6]="R2";tableData[14][7]="R2";tableData[15][1]="R5";tableData[15][2]="R5";tableData[15][3]="R5";tableData[15][4]="R5";tableData[15][5]="R5";tableData[15][6]="R5";tableData[15][7]="R5";}string getCell(int rowN,int lineN){int row=rowN;int line=getLineNumber(lineN);if(row>=0&&row<row_num&&line>=0&&line<=line_num) return tableData[row][line];elsereturn"";}int getLineNumber(int lineN){for(int i=0;i<line_num;i++)if(lineName[i]==lineN)return i;return -1;}};【Table_go.h】//table_go.hclass Table_go{int row_num,line_num;//行数、列数string lineName[3];int tableData[16][3];public:Table_go(){row_num=16;line_num=3;lineName[0]="E";lineName[1]="T";lineName[2]="F";for(int m=0;m<row_num;m++) for(int n=0;n<line_num;n++)tableData[m][n]=0;tableData[0][0]=1;tableData[0][1]=2;tableData[0][2]=3;tableData[4][0]=8;tableData[4][1]=2;tableData[4][2]=3;tableData[6][1]=9;tableData[6][2]=3;tableData[7][2]=10;tableData[12][1]=14;tableData[12][2]=3;tableData[13][2]=15;}int getCell(int rowN,string lineNa){int row=rowN;int line=getLineNumber(lineNa);if(row>=0&&row<row_num&&line<=line_num) return tableData[row][line];elsereturn -1;}int getLineNumber(string lineNa){for(int i=0;i<line_num;i++)if(lineName[i]==lineNa)return i;return -1;}};【Stack_num.h】class Stack_num{int i; //栈顶标记int *data; //栈结构public:Stack_num() //构造函数{data=new int[100];i=-1;}int push(int m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{i--;return data[i+1];}int getTop() //返回栈顶{return data[i];}~Stack_num() //析构函数{delete []data;}int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【Stack_str.h】class Stack_str{int i; //栈顶标记string *data; //栈结构public:Stack_str() //构造函数{data=new string[50];i=-1;}int push(string m) //进栈操作{i++;data[i]=m;return i;}int pop() //出栈操作{data[i]="";i--;return i;}string getTop() //返回栈顶{return data[i];}~Stack_str() //析构函数{delete []data;int topNumber(){return i;}void outStack(){for(int m=0;m<=i;m++)cout<<data[m];}};【cifa.cpp】//cifa.cpp#include<iostream>#include<string>#include"cifa.h"using namespace std;//关键字表和对应的编码stringcodestring[10]={"main","int","if","then","else","return","void","cout","endlint codebook[10]={26,21,22,23,24,25,27,28,29};//全局变量char ch;int flag=0;/*//主函数int main(){WordType word;cout<<"请输入源程序序列:";word=get_w();while(word.pro!="#")//#为自己设置的结束标志{cout<<"("<<word.code<<","<<"“"<<word.pro<<"”"<<")"<<endl;word=get_w();};return 0;}*/WordType get_w(){string str="";int code;WordType wordtmp;getch();//读一个字符getBC();//去掉空白符if(isLetter()){ //以字母开头while(isLetter()||isDigit()){str=concat(str);getch();}retract();code=Reserve(str);if(code==-1){wordtmp.code=0;wordtmp.pro=str;}//不是关键字else{wordtmp.code=code;wordtmp.pro=str;}//是关键字}else if(isDigit()){ //以数字开头while(isDigit()){str=concat(str);getch();}retract();wordtmp.code=30;wordtmp.pro=str;}else if(ch=='(') {wordtmp.code=1;wordtmp.pro="(";} else if(ch==')') {wordtmp.code=2;wordtmp.pro=")";} else if(ch=='{') {wordtmp.code=3;wordtmp.pro="{";} else if(ch=='}') {wordtmp.code=4;wordtmp.pro="}";} else if(ch==';') {wordtmp.code=5;wordtmp.pro=";";} else if(ch=='=') {wordtmp.code=6;wordtmp.pro="=";} else if(ch=='+') {wordtmp.code=7;wordtmp.pro="+";} else if(ch=='*') {wordtmp.code=8;wordtmp.pro="*";} else if(ch=='>') {wordtmp.code=9;wordtmp.pro=">";} else if(ch=='<') {wordtmp.code=10;wordtmp.pro="<";} else if(ch==',') {wordtmp.code=11;wordtmp.pro=",";} else if(ch=='\'') {wordtmp.code=12;wordtmp.pro="\'";} else if(ch=='-') {wordtmp.code=13;wordtmp.pro="-";} else if(ch=='/') {wordtmp.code=14;wordtmp.pro="/";} else if(ch=='#') {wordtmp.code=15;wordtmp.pro="#";} else if(ch=='|') {wordtmp.code=16;wordtmp.pro="|";}else {wordtmp.code=100;wordtmp.pro=ch;}return wordtmp;}void getch(){if(flag==0) //没有回退的字符ch=getchar();else //有回退字符,用回退字符,并设置标志flag=0;}void getBC(){while(ch==' '||ch=='\t'||ch=='\n')ch=getchar();}bool isLetter(){if(ch>='a'&&ch<='z'||ch>='A'&&ch<='Z')return true;elsereturn false;}bool isDigit(){if(ch>='0'&&ch<='9')return true;elsereturn false;}string concat(string str){return str+ch;}void retract(){flag=1;}int Reserve(string str){int i;for(i=0;i<=8;i++){if(codestring[i]==str) //是某个关键字,返回对应的编码return codebook[i];}if(i==9) //不是关键字return -1;}【LR.cpp】#include<iostream>#include<string>#include<cstdlib>#include"cifa.h"#include"stack_num.h"#include"stack_str.h"#include"table_action.h"#include"table_go.h"using namespace std;void process(){int stepNum=1;int topStat;Stack_num statusSTK; //状态栈Stack_str symbolSTK; //符号栈Stack_num valueSTK; //值栈WordType word;Table_action actionTAB; //行为表Table_go goTAB; //转向表cout<<"请输入源程序,以#结束:";word=get_w();//总控程序初始化操作symbolSTK.push("#");statusSTK.push(0);valueSTK.push(0);cout<<"步骤\t状态栈\t符号栈\t值栈\t当前词\t动作\t转向"<<endl;//分析while(1){topStat=statusSTK.getTop(); //当前状态栈顶string act=actionTAB.getCell(topStat,word.code);//根据状态栈顶和当前单词查到的动作//输出cout<<stepNum++<<"\t";statusSTK.outStack(); cout<<"\t";symbolSTK.outStack(); cout<<"\t";valueSTK.outStack(); cout<<"\t";cout<<word.pro<<"\t";//行为为“acc”,且当前处理的单词为#,且状态栈里就两个状态//说明正常分析结束if(act=="acc"&&word.pro=="#"&&statusSTK.topNumber()==1){cout<<act<<endl;cout<<"分析成功!"<<endl;cout<<"结果为:"<<valueSTK.getTop()<<endl;return;}//读到act表里标记为错误的单元格else if(act==""){cout<<endl<<"不是文法的句子!"<<endl;cout<<"错误的位置为单词"<<word.pro<<"附近。
编译原理实验报告3
编译原理实验报告3编译原理实验报告——表达式语法分析——表达式语法分析表达式语法分析实验报告一、实验题目设计一个简单的表达式语法分析器(采用递归下降方法设计实现)二、实验目的1、了解形式语言基础及其文法运算;2、熟悉语法分析原理及 4 种常用的语法分析方法;其中:四种算法为(1)设计算术表达式的递归下降子程序分析算法(2)设计算术表达式的 LL(1) 分析算法(3)设计算术表达式的简单优先分析算法(4)设计算术表达式的SLR(1) 分析算法3、选择上述一种方法并设计一个表达式的语法分析器。
(本实验设计的是递归下降的表达式语法分析器)三、实验内容1.设计递归下降语法分析器算法;2.编写代码并上机调试运行通过; 3、写出试验体会及心得。
四、实验要求1、给出算术表达式文法2、进行适当的文法变换3、选择一种语法分析的方法,并说明其原理4、根据原理给出相应的算法设计,说明主要的数据结构并画出算法流程图5、编写代码并上机调试运行通过6、写出程序运行结果7、写出相应的文档以及代码注释8、输入——表达式;输出——表达式语法是否正确。
五、递归下降的表达式语法分析器设计概要1.算术表达式文法.G(E):E T F 2.文法变换:文法变换:G’(E): E->TE' E'->+TE'|ε T->FT' T'->*FT'|ε F->(E)|I E +T | T T* F | F i | (E)3. 递归下降子程序框图:递归下降子程序框图:六、实验设计源程序#includechar inputstream[50]; int temp=0; int right; void e(); void e1(); void t(); void t1(); void f(); void main() { right=1;//存储输入句子//数组下标 //判断输出信息cout<<"请输入您要分析的字符串以#结束(^为空字符):"<>inputstream; e(); if((inputstream[temp]=='#')&&right) cout<<"分析成功"<<<"e-="" cout<<"分析失败"<TE'"<<<"e'-="" e1()="" e1();="" if(inputstream[temp]="='+')" t();="" void="" {="" }="">+TE'"<e1(); } else if (inputstream[temp]!='#'||inputstream[temp]!=')') { cout<<"T'->^"<<<"t-="" else="" return="" right="0;" t()="" void="" {="" }="">FT'"<<<"t'-="" f();="" if(inputstream[temp]="='*')" t1()="" t1();="" void="" {="" }="">*FT'"<<<"t'-="" else="" f();="" if="" t1();="" temp++;="" {="" }="">^"<} } void f() { if(inputstream[temp]=='i') { cout<<"F->i"<if(inputstream[temp]=='(') { cout<<"F->(E)"<<<"f-="" e();="" if(inputstream[temp]="=')')" temp++;="" {="">(E)"<七、运行结果八、实验思考题语法分析的任务是什么?语法分析的任务是什么?答:语法分析器的任务是识别和处理比单词更大的语法单位,如:程序设计语言中的表达式、各种说明和语句乃至全部源程序,指出其中的语法错误;必要时,可生成内部形式,便于下一阶段处理。
编译原理-实验报告3-LL1
计算机硬件实验室实验报告根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。
本次实验的目的主要是加深对预测分析LL(1)分析法的理解。
二、实验要求:对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG|—TG(3)G->ε(4)T->FS(5)S->*FS|/FS(6)S->ε(7)F->(E)(8)F->i输出的格式如下:(1)LL(1)分析程序,编制人:姓名,学号,班级(2)输入一以#结束的符号串(包括+—*/()i#):在此位置输入符号串(3)输出过程如下:步骤分析栈剩余输入串所用产生式1 E i+i*i# E->TG(4)输入符号串为非法符号串(或者为合法符号串)备注:(1)在“所用产生式”一列中如果对应有推导则写出所用产生式;如果为匹配终结符则写明匹配的终结符;如分析异常出错则写为“分析出错”;若成功结束则写为“分析成功”。
(2) 在此位置输入符号串为用户自行输入的符号串。
(3)上述描述的输出过程只是其中一部分的。
注意:1.表达式中允许使用运算符(+-*/)、分割符(括号)、字符i,结束符#;2.如果遇到错误的表达式,应输出错误提示信息(该信息越详细越好);三、实验过程:1.模块设计:将程序分成合理的多个模块(函数),每个模块做具体的同一事情。
2.写出(画出)设计方案:模块关系简图、流程图、全局变量、函数接口等。
3.程序编写(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);(3)控制部分:从键盘输入一个表达式符号串;(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
四、实验结果:(1)写出程序流程图(2)给出运行结果示例程序:注意:本示例只要修改分析的句子即可,不要改写文法/*LL(1)分析法源程序,只能在VC++中运行*/#include<stdio.h>#include<stdlib.h>#include<string.h>#include<dos.h>char A[20];/*分析栈*/char B[20];/*剩余串*/char v1[20]={'i','+','-','*','/','(',')','#'};/*终结符*/char v2[20]={'E','G','T','S','F'};/*非终结符*/int j=0,b=0,top=0,l;/*L为输入串长度*/typedef struct type/*产生式类型定义*/{char origin;/*大写字符*/char array[5];/*产生式右边字符*/int length;/*字符个数*/}type;type e,t,g,g1,g2,s,s2,s1,f,f1;/*结构体变量*/type C[10][10];/*预测分析表*/void print()/*输出分析栈*/{int a;/*指针*/for(a=0;a<=top+1;a++)printf("%c",A[a]);printf("\t\t");}/*print*/void print1()/*输出剩余串*/{int j;for(j=0;j<b;j++)/*输出对齐符*/printf(" ");for(j=b;j<=l;j++)printf("%c",B[j]);printf("\t\t\t");}/*print1*/void main(){int m,n,k=0,flag=0,finish=0;char ch,x;type cha;/*用来接受C[m][n]*//*把文法产生式赋值结构体*/e.origin='E';strcpy(e.array,"TG");e.length=2;t.origin='T';strcpy(t.array,"FS");t.length=2;g.origin='G';strcpy(g.array,"+TG");g.length=3;g1.origin='G';strcpy(g1.array,"-TG");g1.length=3;g2.origin='G';g2.array[0]='^';g2.length=1;/////////////////////////////////////////////s.origin='S';strcpy(s.array,"*FS");s.length=3;s1.origin='S';strcpy(s1.array,"/FS");s1.length=3;s2.origin='S';s2.array[0]='^';s2.length=1;////////////////////////////////f.origin='F';strcpy(f.array,"(E)");f.length=3;f1.origin='F';f1.array[0]='i';f1.length=1;for(m=0;m<=4;m++)/*初始化分析表*/for(n=0;n<=5;n++)C[m][n].origin='N';/*全部赋为空*//*填充分析表*///char v1[20]={'i','+','-','*','/','(',')','#'};/*终结符*///char v2[20]={'E','G','T','S','F'};/*非终结符*/C[0][0]=e;C[0][5]=e;C[1][1]=g;C[1][2]=g1;C[1][3]=C[1][4]=C[1][7]=g2;C[2][0]=t;C[2][3]=t;C[2][5]=t;C[3][1]=C[3][2]=s2;C[3][3]=s;C[3][4]=s1;C[3][6]=C[3][7]=s2;C[4][0]=f1; C[4][5]=f;printf("LL(1)分析程序,编制人:武普泉,20号,1020562班\n");printf("输入一以#结束的符号串(包括+ - * / () i #):");do/*读入分析串*/{scanf("%c",&ch);if ((ch!='i') &&(ch!='+') &&(ch!='-')&&(ch!='*')&&(ch!='/')&&(ch!='(')&&(ch!=')')&&(ch!='#')) {printf("输入串中有非法字符\n");exit(1);}B[j]=ch;j++;}while(ch!='#');l=j;/*分析串长度*/ch=B[0];/*当前分析字符*/A[top]='#'; A[++top]='E';/*'#','E'进栈*/printf("步骤\t\t分析栈\t\t剩余字符\t\t所用产生式\n");do{x=A[top--];/*x为当前栈顶字符*/printf("%d",k++);printf("\t\t");for(j=0;j<=7;j++)/*判断是否为终结符*/if(x==v1[j]){flag=1;break;}if(flag==1)/*如果是终结符*/{if(x=='#'){finish=1;/*结束标记*/printf("acc!\n");/*接受*/getchar();getchar();exit(1);}/*if*/if(x==ch){print();print1();printf("%c匹配\n",ch);ch=B[++b];/*下一个输入字符*/flag=0;/*恢复标记*/}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",ch);/*输出出错终结符*/exit(1);}/*else*/}/*if*/else/*非终结符处理*/{for(j=0;j<=4;j++)if(x==v2[j]){m=j;/*行号*/break;}for(j=0;j<=7;j++)if(ch==v1[j]){n=j;/*列号*/break;}cha=C[m][n];if(cha.origin!='N')/*判断是否为空*/{print();print1();printf("%c->",cha.origin);/*输出产生式*/for(j=0;j<cha.length;j++)printf("%c",cha.array[j]);printf("\n");for(j=(cha.length-1);j>=0;j--)/*产生式逆序入栈*/A[++top]=cha.array[j];if(A[top]=='^')/*为空则不进栈*/top--;}/*if*/else/*出错处理*/{print();print1();printf("%c出错\n",x);/*输出出错非终结符*/exit(1);}/*else*/}/*else*/}while(finish==0);}/*main*。
编译原理_LL(1)文法源代码(实验三)
一、实验目的及要求1.掌握LL(1)分析法的基本原理;2.掌握LL(1)分析表的构造方法;3.用LL(1)分析法分析高级语言表达式。
4、了解LL(1)分析器的工作过程。
文法:无二义性的算术表达式的文法(1)把词法分析作为语法分析的子程序实现(5分)(2)独立的语法分析程序(4分)(3)对表达式文法消除左递归、构造LL(1)分析表(4)LL(1)分析表可以直接输入(4分),也可以用程序实现(5分)(5)给一个表达式,给出分析过程(分析栈、输入串、所用规则)(4分)(6)生成一个棵语法树(5分)用二叉树的形式表示出来二、实验内容及原理1、实验原理(1)、LL(1)文法的定义LL(1)分析法属于确定的自顶向下分析方法。
LL(1)的含义是:第一个L表明自顶向下分析是从左向右扫描输入串,第2个L表明分析过程中将使用最左推导,1表明只需向右看一个符号便可决定如何推导,即选择哪个产生式(规则)进行推导。
LL(1)文法的判别需要依次计算FIRST集、FOLLOW集和SELLECT集,然后判断是否为LL(1)文法,最后再进行句子分析。
需要预测分析器对所给句型进行识别。
即在LL(1)分析法中,每当在符号栈的栈顶出现非终极符时,要预测用哪个产生式的右部去替换该非终极符;当出现终结符时,判断其与剩余输入串的第一个字符是否匹配,如果匹配,则继续分析,否则报错。
LL(1)分析方法要求文法满足如下条件:对于任一非终极符A的两个不同产生式A→α,A→β,都要满足下面条件:SELECT(A→α)∩SELECT(A→β)=∅(2)、预测分析表构造LL(1)分析表的作用是对当前非终极符和输入符号确定应该选择用哪个产生式进行推导。
它的行对应文法的非终极符,列对应终极符,表中的值有两种:一是产生式的右部的字符串,一是null。
若用M表示LL(1)分析表,则M可表示如下:M: VN×VT→P∪{Error}M(A, t) = A→α,当t∈select(A→α) ,否则M(A, t) = Error其中P表示所有产生式的集合。
(完整word版)编译原理实验报告逆波兰式分析
河南工业大学实验报告课程编译原理实验名称实验三逆波兰式分析一.实验目的1.掌握自底向上分析中算符优先分析法的基本原理;2.掌握优先关系表的构造方法。
二.实验内容及要求根据介绍的算术表达式文法编制调试算符优先分析程序,以便对任意输入的简单算术表达式进行分析。
将用中缀式表示的算术表达式转换为用逆波兰式(后缀式)表示的算术表达式,并计算用逆波兰式表示的算术表达式的值。
程序输入一以#结束的符号串,如:2*(3+4)#。
输出过程如下:(1)逆波兰式(后缀式)为:2&3&4&+*;(2)计算结果:14。
三.实验过程及结果(说明:实验结果可以是运行画面的抓屏,抓屏图片要尽可能的小。
)代码如下:#include<stdio.h>#include<math.h>#define max 100char ex[max]; /*存储后缀表达式*/void trans(){ /*将算术表达式转化为后缀表达式*/char str[max]; /*存储原算术表达式*/char stack[max]; /*作为栈使用*/char ch;int sum,i,j,t,top=0;printf("*****************************************\n"); printf("*输入一个求值的表达式,以#结束。
*\n"); printf("******************************************\n"); printf("算数表达式:");i=0; /*获取用户输入的表达式*/ do{i++;scanf("%c",&str[i]);}while(str[i]!='#' && i!=max);sum=i;t=1;i=1;ch=str[i];i++;while(ch!='#'){switch(ch){case '(': /*判定为左括号*/top++;stack[top]=ch;break;case ')': /*判定为右括号*/while(stack[top]!='('){ex[t]=stack[top];top--;t++;}top--;(完整word版)编译原理实验报告逆波兰式分析break;case '+': /*判定为加减号*/case '-':while(top!=0&&stack[top]!='('){ex[t]=stack[top];top--;t++;}top++;stack[top]=ch;break;case '*': /*判定为乘除号*/case '/':while(stack[top]=='*'||stack[top]=='/'){ex[t]=stack[top];top--;t++;}top++;stack[top]=ch;break;case ' ':break;default:while(ch>='0'&&ch<='9'){ /*判定为数字*/ex[t]=ch;t++;ch=str[i];i++;}i--;ex[t]='&';t++;}ch=str[i];i++;}while(top!=0){ex[t]=stack[top];t++;top--;}ex[t]='#';printf("\n\t原来表达式:");for(j=1;j<sum;j++)printf("%c",str[j]);printf("\n\t后缀表达式:",ex);for(j=1;j<t;j++)printf("%c",ex[j]);}void compvalue(){ /*计算后缀表达式的值*/ float stack[max],d; /*作为栈使用*/char ch;int t=1,top=0; /*t为ex下标,top为stack下标*/ch=ex[t];t++;while(ch!='#'){switch(ch){case '+':stack[top-1]=stack[top-1]+stack[top];top--;break;case '-':stack[top-1]=stack[top-1]-stack[top];top--;break;case '*':stack[top-1]=stack[top-1]*stack[top];top--;break;case '/':if(stack[top]!=0)stack[top-1]=stack[top-1]/stack[top];else{printf("\n\t除零错误!\n");exit(0); /*异常退出*/}top--;break;default:d=0;while(ch>='0'&&ch<='9'){d=10*d+ch-'0'; /*将数字字符转化为对应的数值*/ch=ex[t];t++;}top++;stack[top]=d;}ch=ex[t];t++;}printf("\n\t计算结果:%g\n",stack[top]);}void main(){trans();compvalue();}截屏如下:四.实验中的问题及心得这次试验让我更一步了解到自底向上分析中算符优先分析法的基本原理。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
编译原理实验报告实验三语义分析班级:学号:姓名:任课教师:计算机科学与工程系2016年 6 月20 日一、实验目的通过上机实习,加深对语法制导翻译原理的理解,掌握将语法分析所识别的语法成分变换为中间代码的语义翻译方法。
二、实验要求实验的输入和输出:输入是语法分析后提供的正确的单词串,输出为三地址指令形式的四元式序列。
例如:对于语句串begin a:=2+3*4;x:=(a+b)/c end#输出的三地址指令如下:(1) t1=3* 4 (4) t3=a+b(2) t2=2+t1 (5) t4=t3/c(3) a=t2 (6) x=t4三、实验内容采用递归下降语法制导翻译法,对算术表达式、赋值语句进行语义分析并生成四元式序列。
四、算法设计和源程序#include "stdio.h"#include "string.h"#include "stdlib.h"char prog[100],token[8],ch;char *rwtab[6]={"begin","if","then","while","do","end"};int syn,p,m,n,sum,q;int kk;struct { char result1[8];char ag11[8];char op1[8];char ag21[8];} quad[20];char *factor();char *expression();int yucu();char *term();int statement();int lrparser();char *newtemp();scaner();emit(char *result,char *ag1,char *op,char *ag2);main()q=p=kk=0;printf("\nplease input a string (end with '#'): ");do{ scanf("%c",&ch);prog[p++]=ch;}while(ch!='#');p=0;scaner();lrparser();if(q>19)printf(" to long sentense!\n");else for(j=0;j<q;j++)printf("%s=%s%s%s\n\n",quad[j].result1,quad[j].ag11,quad[j].op1,quad[j].ag21); //getch();}int lrparser(){ int schain=0;kk=0;if (syn==1){ scaner(); //读下一个单词符号schain=yucu(); //调用语句串分析函数进行分析if(syn==6){ scaner(); //读下一个单词符号if((syn==0)&&(kk==0)) printf("Success!\n"); //输出(“success”)}else { if(kk!=1)printf("short of 'end' !\n"); //输出‘缺end’ 错误kk=1;// getch();exit(0);}}else { printf("short of 'begin' !\n"); //输出’begin’错误kk=1;// getch();exit(0);}return (schain);}int yucu(){ int schain=0;schain=statement(); //调用语句分析函数进行分析{ scaner(); //读下一个单词符号schain=statement(); //调用语句分析函数进行分析}return (schain);}int statement(){ char tt[8],eplace[8];int schain=0;if (syn==10){ strcpy(tt,token);scaner();if(syn==18){ scaner(); //读下一个单词符号strcpy(eplace,expression());emit(tt,eplace,"","");schain=0;}else { printf("short of sign ':=' !\n"); //输出’缺少赋值号’的错误kk=1;// getch();exit(0);}return (schain);}}char *expression(){ char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12); //分配空间ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt=(char *)malloc(12);strcpy(eplace,term()); //调用term分析产生表达式计算的第一项eplace while((syn==13)||(syn==14)){ if (syn==13)strcpy(tt,"+"); //操作符tt= ‘+’或者‘—’else strcpy(tt,"-");scaner(); //读下一个单词符号strcpy(ep2,term()); //调用term分析产生表达式计算的第二项ep2strcpy(tp,newtemp()); //调用newtemp产生临时变量tp存储计算结果strcpy(eplace,tp);}return (eplace);}char *term() //仿照函数expression编写{ char *tp,*ep2,*eplace,*tt;tp=(char *)malloc(12);ep2=(char *)malloc(12);eplace=(char *)malloc(12);tt=(char *)malloc(12);strcpy(eplace,factor());while((syn==15)||(syn==16)){ if (syn==15)strcpy(tt,"*");else strcpy(tt,"/");scaner(); //读下一个单词符号strcpy(ep2,factor());strcpy(tp,newtemp());emit(tp,eplace,tt,ep2);strcpy(eplace,tp);}return (eplace);}char *factor(){ char *fplace;fplace=(char *)malloc(12);strcpy(fplace,"");if(syn==10){ strcpy(fplace,token);scaner(); //读下一个单词符号}else if(syn==11){ itoa(sum,fplace,10);scaner(); //读下一个单词符号}else if(syn==27){ scaner(); //读下一个单词符号fplace=expression(); //调用expression分析返回表达式的值if(syn==28) scaner(); //读下一个单词符号else { printf("error on ')' !\n");// getch();exit(0);}}else { printf("error on '(' !\n");kk=1;// getch();exit(0);}return (fplace);}char *newtemp(){ char *p;char m[8];p=(char *)malloc(8);kk++;itoa(kk,m,10);strcpy(p+1,m);p[0]='t';return(p);}scaner(){ sum=0;for(m=0;m<8;m++)token[m++]=NULL;m=0;ch=prog[p++];while(ch==' ')ch=prog[p++];if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))){ while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9'))) {token[m++]=ch;ch=prog[p++];}p--;syn=10;token[m++]='\0';for(n=0;n<6;n++)if(strcmp(token,rwtab[n])==0){ syn=n+1;}}else if((ch>='0')&&(ch<='9')){ while((ch>='0')&&(ch<='9')) { sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11;}else switch(ch){ case '<':m=0;ch=prog[p++];if(ch=='>'){ syn=21;}else if(ch=='='){ syn=22;}else{ syn=20;p--;}break;case '>':m=0;ch=prog[p++];if(ch=='='){ syn=24;}else{ syn=23;p--;}break;case ':':m=0;ch=prog[p++];if(ch=='='){ syn=18;}{ syn=17;p--;}break;case '+': syn=13; break;case '-': syn=14; break;case '*': syn=15;break;case '/': syn=16;break;case '(': syn=27;break;case ')': syn=28;break;case '=': syn=25;break;case ';': syn=26;break;case '#': syn=0;break;default: syn=-1;break;}}emit(char *result,char *ag1,char *op,char *ag2){strcpy(quad[q].result1,result);strcpy(quad[q].ag11,ag1);strcpy(quad[q].op1,op);strcpy(quad[q].ag21,ag2);q++;}五、实验结果分析输入:begin a:=2+3*4; x:=(a+b)/c end #输入:begin x:=2+d; end #(错误案例,结果显示---缺少赋值号错误)输入:x:=4+2;d:=2+4/3 end #(错误案例,结果显示---缺少begin错误)六、实验心得体会及问题反馈说明:打印时正文采用5号宋体,英文为Times New Roman,A4纸,页边距均为20mm,行间距采用18磅。