编译原理实验二

合集下载

编译原理-实验二-FLEX词法分析器

编译原理-实验二-FLEX词法分析器

编译原理-实验⼆-FLEX词法分析器FLEX词法分析器⼀、Lex和Yacc介绍Lex 是⼀种⽣成扫描器的⼯具。

扫描器是⼀种识别⽂本中的词汇模式的程序。

⼀种匹配的常规表达式可能会包含相关的动作。

这⼀动作可能还包括返回⼀个标记。

当 Lex 接收到⽂件或⽂本形式的输⼊时,它试图将⽂本与常规表达式进⾏匹配。

它⼀次读⼊⼀个输⼊字符,直到找到⼀个匹配的模式。

如果能够找到⼀个匹配的模式,Lex 就执⾏相关的动作(可能包括返回⼀个标记)。

另⼀⽅⾯,如果没有可以匹配的常规表达式,将会停⽌进⼀步的处理,Lex 将显⽰⼀个错误消息。

Yacc代表 Yet Another Compiler Compiler 。

Yacc 的 GNU 版叫做 Bison。

它是⼀种⼯具,将任何⼀种编程语⾔的所有语法翻译成针对此种语⾔的 Yacc 语法解析器。

(下载下载flex和bison。

⽹址分别是/packages/flex.htm和/packages/bison.htm。

)⼆、配置环境(win7)①下载flex和bison并安装到D:\GnuWin32(尽量是根⽬录)②由于我们使⽤的flex和bison都是GNU的⼯具,所以为了⽅便,采⽤的C/C++编译器也采⽤GNU的编译器GCC,当然我们需要的也是Windows版本的GCC了。

所以提前准备好VC 6.0③检验是否可以进⾏lex⽂件编译1.新建⽂本⽂件,更改名称为lex.l,敲⼊下⾯代码%{int yywrap(void);%}%%%%int yywrap(void){return 1;}2.新建⽂本⽂件,更改名称为yacc.y,敲⼊下⾯代码%{void yyerror(const char *s);%}%%program:;%%void yyerror(const char *s){}int main(){yyparse();}我们暂且不讨论上⾯代码的意思。

打开控制台,进⼊到刚才所建⽴⽂件(lex.l,yacc.y)所在的⽂件夹。

《编译原理(实验部分)》实验2_PL0词法分析

《编译原理(实验部分)》实验2_PL0词法分析

《编译原理》(实验部分)实验2_PL0 词法分析一、实验目的加深和巩固对于词法分析的了解和掌握;初步认识PL/0 语言的基础和简单的程序编写;通过本实验能够初步的了解和掌握程序词法分析的整个过程;提高自己上机和编程过程中处理具体问题的能力。

二、实验设备1、P C兼容机一台;操作系统为WindowsWindowsX P2、Visual C++ 6.0 或以上版本,Windows 2000 或以上版本,汇编工具 (在Software 子目录下)。

三、实验原理PL/O语言的编译程序,是用高级语言PASCAL语言书写的。

整个编译过程是由一些嵌套及并列的过程或函数完成。

词法分析程序是独立的过程GETSY完成,供语法分析读单词时使用。

四、实验步骤阅读所给出的词法分析程序( pl0_lexical.c ),搞懂程序中每一个变量的含义,以及每一个过程的作用,并在该过程中进行中文注释;阅读完程序后,画出各过程的流程图;给出的程序包含两处输入错误,利用所给的pl/0 源程序(test.pl0) 对程序进行调试,使其能正确对所给文件进行分析并能够解释运行;在阅读懂所给出的词法分析程序后,将你对词法分析的理解写在实验报告上。

实验代码#include<stdio.h>main(){ printf ("my name is 08061118 yuchaofeng ");}主程序:#include <stdio.h>#include <ctype.h>#include <alloc.h>#include <stdlib.h>#include <string.h>#define NULL 0FILE *fp;char cbuffer;char *key[8]={"DO","BEGIN","ELSE","END","IF","THEN","VAR","WHILE"}; char *border[6]={",",";",":=",".","(",")"};char *arithmetic[4]={"+","-","*","/"};char *relation[6]={"<","<=","=",">",">=","<>"};char *consts[20];char *label[20];int constnum=0,labelnum=0;int search(char searchchar[],int wordtype){int i=0;switch (wordtype) {case 1:for (i=0;i<=7;i++){if (strcmp(key[i],searchchar)==0)return(i+1);};case 2:{for (i=0;i<=5;i++){if (strcmp(border[i],searchchar)==0)return(i+1);};return(0);}case 3:{for (i=0;i<=3;i++){ if (strcmp(arithmetic[i],searchchar)==0){};};return(0);};case 4:{for (i=0;i<=5;i++){ if (strcmp(relation[i],searchchar)==0){return(i+1);};};return(0);};case 5:{for (i=0;i<=constnum;i++){ if (strcmp(consts[i],searchchar)==0){return(i+1);};}consts[i-1]=(char *)malloc(sizeof(searchchar));strcpy(consts[i-1],searchchar);constnum++;return(i);};case 6:{for (i=0;i<=labelnum;i++){ if (strcmp(label[i],searchchar)==0){ return(i+1);};}label[i-1]=(char *)malloc(sizeof(searchchar)); strcpy(label[i-1],searchchar);return(i);};}}char alphaprocess(char buffer){int atype;int i=-1;char alphatp[20];while ((isalpha(buffer))||(isdigit(buffer))){ alphatp[++i]=buffer; buffer=fgetc(fp);}; alphatp[i+1]='\0';if (atype=search(alphatp,1)) printf("%s (1,%d)\n",alphatp,atype-1); else { atype=search(alphatp,6);printf("%s (6,%d)\n",alphatp,atype-1); };return(buffer);char digitprocess(char buffer){int i=-1;char digittp[20];int dtype;while ((isdigit(buffer))){ digittp[++i]=buffer;buffer=fgetc(fp);}digittp[i+1]='\0';dtype=search(digittp,5);printf("%s (5,%d)\n",digittp,dtype-1); return(buffer);}char otherprocess(char buffer){int i=-1;char othertp[20];int otype,otypetp;othertp[0]=buffer;othertp[1]='\0';if (otype=search(othertp,3)){printf("%s (3,%d)\n",othertp,otype-1);buffer=fgetc(fp);goto out;};if (otype=search(othertp,4)){buffer=fgetc(fp);othertp[1]=buffer;othertp[2]='\0';if (otypetp=search(othertp,4)){printf("%s (4,%d)\n",othertp,otypetp-1); goto out;}elseothertp[1]='\0';printf("%s (4,%d)\n",othertp,otype-1);goto out;};if (buffer==':'){ buffer=fgetc(fp);if (buffer=='=')printf(":= (2,2)\n");buffer=fgetc(fp);goto out;}else{if (otype=search(othertp,2)){ printf("%s (2,%d)\n",othertp,otype-1); buffer=fgetc(fp); goto out;}};if ((buffer!='\n')&&(buffer!=' '))printf("%c error,not a word\n",buffer); buffer=fgetc(fp);out: return(buffer);} void main(){ int i;for (i=0;i<=20;i++){label[i]=NULL; consts[i]=NULL;};if ((fp=fopen("skh.c","r"))==NULL) printf("error");else{ cbuffer = fgetc(fp);while (cbuffer!=EOF){if (isalpha(cbuffer)) cbuffer=alphaprocess(cbuffer);else if (isdigit(cbuffer))cbuffer=digitprocess(cbuffer); else cbuffer=otherprocess(cbuffer); };printf("over\n");};}。

编译原理实验二LL文法分析

编译原理实验二LL文法分析

实验2 LL(1)分析法一、实验目的通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。

使学生了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练学生掌握开发应用程序的基本方法。

有利于提高学生的专业素质,为培养适应社会多方面需要的能力。

二、实验要求1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。

2、如果遇到错误的表达式,应输出错误提示信息。

3、对下列文法,用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三、实验内容根据某一文法编制调试LL ( 1 )分析程序,以便对任意输入的符号串进行分析。

构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。

分析法的功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。

四、实验步骤1、根据流程图编写出各个模块的源程序代码上机调试。

2、编制好源程序后,设计若干用例对系统进行全面的上机测试,并通过所设计的LL(1)分析程序;直至能够得到完全满意的结果。

3、书写实验报告;实验报告正文的内容:写出LL(1)分析法的思想及写出符合LL(1)分析法的文法。

程序结构描述:函数调用格式、参数含义、返回值描述、函数功能;函数之间的调用关系图。

详细的算法描述(程序执行流程图)。

给出软件的测试方法和测试结果。

实验总结(设计的特点、不足、收获与体会)。

五、实验截图六、核心代码#include<iostream>#include<stdio.h>#include<stdlib.h>#include<string.h>#define MAX 20using namespace std;char A[MAX];char B[MAX];char v1[MAX] = { 'i','+','-','*','/','(',')','#'}; char v2[MAX] = {'E','G','T','S','F'};int j = 0, b = 0, top = 0;int l; //l是字符串长度class type{public:char origin;char array[7];int length;};type e, t, g,g0, g1, s, s0,s1, f, f1;type C[10][10];void print(){int a;for ( a = 0; a <= top + 1; a++)cout<<A[a];cout << "\t\t";}void print1(){int j;for (j = 0; j<b; j++)cout << " ";for (j = b; j <= l; j++)cout << B[j];cout << "\t\t\t";}int main(){int m, n, k = 0;int flag = 0,finish = 0;char ch, x;type cha;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;g0.origin = 'G';strcpy(g0.array, "-TG");g0.length = 3;g1.origin = 'G';g1.array[0] = '^';g1.length = 1;s.origin = 'S';strcpy(s.array, "*FS");s.length = 3;s0.origin = 'S';strcpy(s0.array, "/FS");s0.length = 3;s1.origin = 'S';s1.array[0] = '^';s1.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 <= 7; n++)C[m][n].origin = 'N';/*C[0][0] = e; C[0][3] = e; C[1][2] = g0;C[1][1] = g; C[1][4] = g1; C[1][5] = g1;C[2][0] = t; C[2][3] = t;C[3][1] = s1; C[3][2] = s;C[3][4] = C[3][5] = s1;C[4][0] = f1; C[4][3] = f;*/C[0][0] = e; C[0][5] = e;C[1][1] = g; C[1][2] = g0;C[1][6] = g1; C[1][7] = g1;C[2][0] = t; C[2][5] = t;C[3][1] = s1; C[3][2] = s1;C[3][3] = s;C[3][4] = s0; C[3][6] = s1; C[3][7] = s1;C[4][0] = f1; C[4][5] = f;cout << "input,please~:";do{cin >> ch;if ((ch!='i') &&(ch!='+') &&(ch!='-') &&(ch!='*') &&(ch!='/') &&(ch!='(') &&(ch!=')') &&(ch!='#')){cout << "Error!\n";exit(1);}B[j] = ch;j++;} while (ch != '#');l = j; //l是字符串长度/* for(j=0;j<l;j++)cout<<B[j]<<endl;*/ch = B[0]; //当前分析字符A[top] = '#';A[++top] = 'E';/*'#','E'进栈*/cout << "步骤\t\t分析栈\t\t剩余字符\t\t所用字符\n"; do{x = A[top--];cout << k++;cout << "\t\t";for (j = 0; j<=7 ; j++)if (x == v1[j]){flag = 1;break;}if (flag==1){if (x == '#'){finish = 1;cout << "acc!\n";getchar();getchar();exit(1);}if (x == ch){print();print1();cout <<ch << "匹配\n";ch = B[++b];flag = 0;}else{cout<<"x:"<<x<<endl;cout<<"ch:"<<ch<<endl;print();print1();cout <<ch<< "出错\n" ;exit(1);}}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();cout << cha.origin << "->";for (j = 0; j<cha.length; j++)cout << cha.array[j];cout << "\n";for (j = (cha.length - 1); j >= 0; j--)A[++top] = cha.array[j];if (A[top] == '^')/*为空则不进栈*/top--;}else{print();print1();cout<<"x:"<<x<<endl;cout<<"ch:"<<ch<<endl;cout<<"sign1"<<endl;cout << "Error!" << x;exit(1);}}} while (finish == 0);}。

编译原理_实验报告实验二__语法分析(算符优先) 2

编译原理_实验报告实验二__语法分析(算符优先) 2

华北水利水电学院编译原理实验报告一、实验题目:语法分析(算符优先分析程序)(1)选择最有代表性的语法分析方法算符优先法;(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三、程序源代#include<stdlib.h>#include<stdio.h>#include<string.h>#include<iostream.h>#define SIZE 128char priority[6][6]; //算符优先关系表数组char input[SIZE]; //存放输入的要进行分析的句子char remain[SIZE]; //存放剩余串char AnalyseStack[SIZE]; //分析栈void analyse();int testchar(char x); //判断字符X在算符优先关系表中的位置void remainString(); //移进时处理剩余字符串,即去掉剩余字符串第一个字符int k;void init()//构造算符优先关系表,并将其存入数组中{priority[0][2]='<';priority[0][3]='<';priority[0][4]='>';priority[0][5]='>';priority[1][0]='>';priority[1][1]='>';priority[1][2]='<';priority[1][3]='<';priority[1][4]='>';priority[1][5]='>';priority[2][0]='>';priority[2][1]='>';priority[2][2]='$';//无优先关系的用$表示priority[2][3]='$';priority[2][4]='>';priority[2][5]='>';priority[3][0]='<';priority[3][1]='<';priority[3][2]='<';priority[3][3]='<';priority[3][4]='=';priority[3][5]='$';priority[4][0]='>';priority[4][1]='>';priority[4][2]='$';priority[4][3]='$';priority[4][4]='>';priority[4][5]='>';priority[5][0]='<';priority[5][3]='<';priority[5][4]='$';priority[5][5]='=';}void analyse()//对所输入的句子进行算符优先分析过程的函数{FILE *fp;fp=fopen("li","a");int i,j,f,z,z1,n,n1,z2,n2;int count=0;//操作的步骤数char a; //用于存放正在分析的字符char p,Q,p1,p2;f=strlen(input); //测出数组的长度for(i=0;i<=f;i++){a=input[i];if(i==0)remainString();if(AnalyseStack[k]=='+'||AnalyseStack[k]=='*'||AnalyseStack[k]=='i'||Analy seStack[k]=='('||AnalyseStack[k]==')'||AnalyseStack[k]=='#')j=k;elsej=k-1;z=testchar(AnalyseStack[j]);//从优先关系表中查出s[j]和a的优先关系if(a=='+'||a=='*'||a=='i'||a=='('||a==')'||a=='#')n=testchar(a);else //如果句子含有不是终结符集合里的其它字符,不合法{printf("错误!该句子不是该文法的合法句子!\n");break;}if(p=='$'){printf("错误!该句子不是该文法的合法句子!\n");return;}if(p=='>'){ for( ; ; ){Q=AnalyseStack[j];if(AnalyseStack[j-1]=='+'||AnalyseStack[j-1]=='*'||AnalyseStack[j-1]=='i'||AnalyseStack[j-1]=='('||AnalyseStack[j-1]==')'||AnalyseStack[j-1]=='#')j=j-1;elsej=j-2;z1=testchar(AnalyseStack[j]);n1=testchar(Q);p1=priority[z1][n1];if(p1=='<') //把AnalyseStack[j+1]~AnalyseStack[k]归约为N{count++;printf("(%d) %s\t%10c\t%5c%17s\t 归约\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"归约");k=j+1;i--;AnalyseStack[k]='N';int r,r1;r=strlen(AnalyseStack);for(r1=k+1;r1<r;r1++)AnalyseStack[r1]='\0';break;}else}}else{if(p=='<') //表示移进{count++;printf("(%d) %s\t%10c\t%5c%17s\t 移进\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"移进");k=k+1;AnalyseStack[k]=a;remainString();}else{if(p=='='){z2=testchar(AnalyseStack[j]);n2=testchar('#');p2=priority[z2][n2];if(p2=='='){count++;printf("(%d) %s\t%10c\t%5c%17s\t 接受\n",count,AnalyseStack,p,a,remain);fprintf(fp,"(%d) %s\t%17s\t %s\n",count,AnalyseStack,remain,"接受");printf("该句子是该文法的合法句子。

编译原理实验二:压缩文法的等价变换

编译原理实验二:压缩文法的等价变换

实验二:压缩文法的等价变换一:要求输入:任意的上下文无关文法输出:等价的压缩了的文法要求:除了可查看压缩了的文法,还可查看删除了哪些规则二:实验目的了解文法的简化三:实验原理删除文法中的有害规则和多余规则有害规则:若文法中有如U::=U的规则,则这就是有害规则,它会引起二义性,而无任何用处。

多余规则:(1)某条规则U::=u的左部非终结符U(U不是识别符号),不在任何其他规则右部出现,即所有的推导始终不会用到此规则。

【不可到达】(2)在推导句子的过程中,一旦使用了该规则,将推不出任何终结符号串。

即该规则中含有推不出任何终结符号串的非终结符。

【不可终止】四:数据结构与算法struct Chomsky{string left;string right;};void apart(Chomsky *p,int i) //分开产生式左右部void VNVT(Chomsky *p)//求VN和VTint zero(Chomsky *p)//0型文法int one(Chomsky *p)//1型文法int two(Chomsky *p)//2型文法void shanchu(Chomsky *p)//删除多余规则与有害规则五:出错分析1:变量重复定义导致了一些小错误2:程序太长{}缺少也导致了错误3:后面删除规则的程序出错了,没有调试成功。

六:实验结果与分析不是上下文无关文法的:2型文法的压缩:七:源代码#include<iostream>#include<string>using namespace std;#define max 50int NONE=1;int RELEFT=1;string strings,noend,end;//非终结符与终结符存储int n;//产生式总数int flag;struct Chomsky{string left;string right;};void apart(Chomsky *p,int i) //分开产生式左右部{int j;for(j=0;j<strings.length();j++)if(strings[j]=='-'){p[i].left=strings.substr(0,j);p[i].right=strings.substr(j+1,strings.length()-j);}}void VNVT(Chomsky *p)//求VN和VT{int i,j;for(i=0;i<n;i++){for(j=0;j<(int)p[i].left.length();j++){if((p[i].left[j]>='A'&&p[i].left[j]<='Z'))//非终结符判断{if(noend.find(p[i].left[j])>100)noend+=p[i].left[j];}else{if(end.find(p[i].left[j])>100)end+=p[i].left[j];}}{if(!(p[i].right[j]>='A'&&p[i].right[j]<='Z'))//终结符判断{if(end.find(p[i].right[j])>100)end+=p[i].right[j];}else{if(noend.find(p[i].right[j])>100)noend+=p[i].right[j];}}}}int zero(Chomsky *p)//0型文法{int flag(0),count(0);int i,j;for(i=0;i<n;i++){{if(p[i].left[j]>='A'&&p[i].left[j]<='Z') //有否非终结符flag++;}if(flag>0){flag=0;count++;}elsebreak; //左部没有非终结符,结束}if(count==n)return 1; //属于0型文法else{cout<<endl<<"所输产生式不属于任何文法。

编译原理实验报告LL(2)分析法

编译原理实验报告LL(2)分析法

课程编译原理实验名称实验二 LL(1)分析法实验目的1.掌握LL(1)分析法的基本原理;2.掌握LL(1)分析表的构造方法;3.掌握LL(1)驱动程序的构造方法。

一.实验内容及要求根据某一文法编制调试LL(1)分析程序,以便对任意输入的符号串进行分析。

本次实验的目的主要是加深对预测分析LL(1)分析法的理解。

对下列文法,用LL(1)分析法对任意输入的符号串进行分析:(1)E->TG(2)G->+TG(3)G->ε(4)T->FS(5)S->*FS(6)S->ε(7)F->(E)(8)F->i程序输入一以#结束的符号串(包括+*()i#),如:i+i*i#。

输出过程如下:步骤分析栈剩余输入串所用产生式1 E i+i*i# E->TG... ... ... ...二.实验过程及结果代码如下:#include<iostream>#include "edge.h"using namespace std;edge::edge(){cin>>left>>right;rlen=right.length();if(NODE.find(left)>NODE.length())NODE+=left;}string edge::getlf(){return left;}string edge::getrg(){return right;}string edge::getfirst(){return first;}string edge::getfollow(){return follow;}string edge::getselect(){return select;}string edge::getro(){string str;str+=right[0];return str;}int edge::getrlen(){return right.length();}void edge::newfirst(string w){int i;for(i=0;i<w.length();i++)if(first.find(w[i])>first.length())first+=w[i];}void edge::newfollow(string w){int i;for(i=0;i<w.length();i++)if(follow.find(w[i])>follow.length()&&w[i]!='@')follow+=w[i];}void edge::newselect(string w){int i;for(i=0;i<w.length();i++)if(select.find(w[i])>select.length()&&w[i]!='@')select+=w[i];}void edge::delfirst(){int i=first.find('@');first.erase(i,1);}int SUM;string NODE,ENODE;//计算firstvoid first(edge ni,edge *n,int x){int i,j;for(j=0;j<SUM;j++){if(ni.getlf()==n[j].getlf()){if(NODE.find(n[j].getro())<NODE.length()){for(i=0;i<SUM;i++)if(n[i].getlf()==n[j].getro())first(n[i],n,x);}elsen[x].newfirst(n[j].getro());}}}//计算followvoid follow(edge ni,edge *n,int x){int i,j,k,s;string str;for(i=0;i<ni.getrlen();i++){s=NODE.find(ni.getrg()[i]);if(s<NODE.length()&&s>-1) //是非终结符if(i<ni.getrlen()-1) //不在最右for(j=0;j<SUM;j++)if(n[j].getlf().find(ni.getrg()[i])==0){if(NODE.find(ni.getrg()[i+1])<NODE.length()){for(k=0;k<SUM;k++)if(n[k].getlf().find(ni.getrg()[i+1])==0){n[j].newfollow(n[k].getfirst());if(n[k].getfirst().find("@")<n[k].getfirst().length())n[j].newfollow(ni.getfollow());}}else{str.erase();str+=ni.getrg()[i+1];n[j].newfollow(str);}}}}//计算selectvoid select(edge &ni,edge *n){int i,j;if(ENODE.find(ni.getro())<ENODE.length()){ni.newselect(ni.getro());if(ni.getro()=="@")ni.newselect(ni.getfollow());}elsefor(i=0;i<ni.getrlen();i++){for(j=0;j<SUM;j++)if(ni.getrg()[i]==n[j].getlf()[0]){ni.newselect(n[j].getfirst());if(n[j].getfirst().find('@')>n[j].getfirst().length())return;}}}//输出集合void out(string p){int i;if(p.length()==0)return;cout<<"{";for(i=0;i<p.length()-1;i++){cout<<p[i]<<",";}cout<<p[i]<<"}";}//连续输出符号void outfu(int a,string c){int i;for(i=0;i<a;i++)cout<<c;}//输出预测分析表void outgraph(edge *n,string (*yc)[50]){int i,j,k;bool flag;for(i=0;i<ENODE.length();i++){if(ENODE[i]!='@'){outfu(10," ");cout<<ENODE[i];}}outfu(10," ");cout<<"#"<<endl;int x;for(i=0;i<NODE.length();i++){outfu(4," ");cout<<NODE[i];outfu(5," ");for(k=0;k<ENODE.length();k++){flag=1;for(j=0;j<SUM;j++){if(NODE[i]==n[j].getlf()[0]){x=n[j].getselect().find(ENODE[k]);if(x<n[j].getselect().length()&&x>-1){cout<<"->"<<n[j].getrg();yc[i][k]=n[j].getrg();outfu(9-n[j].getrlen()," ");flag=0;}x=n[j].getselect().find('#');if(k==ENODE.length()-1&&x<n[j].getselect().length()&&x>-1){cout<<"->"<<n[j].getrg();yc[i][j]=n[j].getrg();}}}if(flag&&ENODE[k]!='@')outfu(11," ");}cout<<endl;}}//分析符号串int pipei(string &chuan,string &fenxi,string (*yc)[50],int &b){char ch,a;int x,i,j,k;b++;cout<<endl<<" "<<b;if(b>9)outfu(8," ");elseoutfu(9," ");cout<<fenxi;outfu(26-chuan.length()-fenxi.length()," "); cout<<chuan;outfu(10," ");a=chuan[0];ch=fenxi[fenxi.length()-1];x=ENODE.find(ch);if(x<ENODE.length()&&x>-1){if(ch==a){fenxi.erase(fenxi.length()-1,1);chuan.erase(0,1);cout<<"'"<<a<<"'匹配";if(pipei(chuan,fenxi,yc,b))return 1;elsereturn 0;}elsereturn 0;}else{if(ch=='#'){if(ch==a){cout<<"分析成功"<<endl;return 1;}elsereturn 0;}elseif(ch=='@'){fenxi.erase(fenxi.length()-1,1);if(pipei(chuan,fenxi,yc,b))return 1;elsereturn 0;}else{i=NODE.find(ch);if(a=='#'){x=ENODE.find('@');if(x<ENODE.length()&&x>-1)j=ENODE.length()-1;elsej=ENODE.length();}elsej=ENODE.find(a);if(yc[i][j].length()){cout<<NODE[i]<<"->"<<yc[i][j];fenxi.erase(fenxi.length()-1,1);for(k=yc[i][j].length()-1;k>-1;k--)if(yc[i][j][k]!='@')fenxi+=yc[i][j][k];if(pipei(chuan,fenxi,yc,b))return 1;elsereturn 0;}elsereturn 0;}}}void main(){edge *n;string str,(*yc)[50];int i,j,k;bool flag=0;cout<<"请输入上下文无关文法的总规则数:"<<endl;cin>>SUM;cout<<"请输入具体规则(格式:左部右部,@为空):"<<endl;n=new edge[SUM];for(i=0;i<SUM;i++)for(j=0;j<n[i].getrlen();j++){str=n[i].getrg();if(NODE.find(str[j])>NODE.length()&&ENODE.find(str[j])>ENODE.length()) ENODE+=str[j];}//计算first集合for(i=0;i<SUM;i++){first(n[i],n,i);}//outfu(10,"~*~");cout<<endl;for(i=0;i<SUM;i++)if(n[i].getfirst().find("@")<n[i].getfirst().length()){if(NODE.find(n[i].getro())<NODE.length()){for(k=1;k<n[i].getrlen();k++){if(NODE.find(n[i].getrg()[k])<NODE.length()){for(j=0;j<SUM;j++){if(n[i].getrg()[k]==n[j].getlf()[0]){n[i].newfirst(n[j].getfirst());break;}}if(n[j].getfirst().find("@")>n[j].getfirst().length()){n[i].delfirst();break;}}}}}//计算follow集合for(k=0;k<SUM;k++){for(i=0;i<SUM;i++){if(n[i].getlf()==n[0].getlf())n[i].newfollow("#");follow(n[i],n,i);}for(i=0;i<SUM;i++){for(j=0;j<SUM;j++)if(n[j].getrg().find(n[i].getlf())==n[j].getrlen()-1)n[i].newfollow(n[j].getfollow());}}//计算select集合for(i=0;i<SUM;i++){select(n[i],n);}for(i=0;i<NODE.length();i++){str.erase();for(j=0;j<SUM;j++)if(n[j].getlf()[0]==NODE[i]){if(!str.length())str=n[j].getselect();else{for(k=0;k<n[j].getselect().length();k++)if(str.find(n[j].getselect()[k])<str.length()){flag=1;break;}}}}//输出cout<<endl<<"非终结符";outfu(SUM," ");outfu(SUM," ");cout<<"Follow"<<endl;outfu(5+SUM,"-*-");cout<<endl;for(i=0;i<NODE.length();i++){for(j=0;j<SUM;j++)if(NODE[i]==n[j].getlf()[0]){outfu(3," ");cout<<NODE[i];outfu(SUM+4," ");out(n[j].getfirst());outfu(SUM+4-2*n[j].getfirst().length()," ");out(n[j].getfollow());cout<<endl;break;}}outfu(5+SUM,"-*-");cout<<endl<<"判定结论:";if(flag){cout<<"该文法不是LL(1)文法!"<<endl;return;}else{cout<<"该文法是LL(1)文法!"<<endl;}//输出预测分析表cout<<endl<<"预测分析表如下:"<<endl;yc=new string[NODE.length()][50];outgraph(n,yc);string chuan,fenxi,fchuan;cout<<endl<<"请输入符号串:";cin>>chuan;fchuan=chuan;fenxi="#";fenxi+=NODE[0];i=0;cout<<endl<<"预测分析过程如下:"<<endl;outfu(7," ");cout<<"分析栈";outfu(10," ");cout<<"剩余输入串";outfu(8," ");cout<<"推导所用产生式或匹配";if(pipei(chuan,fenxi,yc,i))cout<<endl<<"输入串"<<fchuan<<"是该文法的句子!"<<endl;elsecout<<endl<<"输入串"<<fchuan<<"不是该文法的句子!"<<endl;}截屏如下:三.实验中的问题及心得这次实验让我更加熟悉了LL(1)的工作流程以及LL(1)分析表的构造方法。

昆明理工编译原理实验报告2

昆明理工编译原理实验报告2

昆明理工大学信息工程与自动化学院学生实验报告( 2014 — 2015 学年 第1学期 )课程名称:编译原理 开课实验室:信自楼445 时间:2014年12月15日 一、实验目的及要求目的:编制一个语法分析程序,实现对词法分析程序所提供的单词序列进行语法检查和结构分析。

要求:在实验一词法分析的基础上,采用递归子程序法或其他适合的语法分析方法,实现其语法分析程序。

要求编译后能检查出语法错误。

已知待分析的C 语言子集的语法,用EBNF 表示如下: <程序>→main()<语句块> <语句块> →‘{’<语句串>‘}’ <语句串> → <语句> {; <语句> };<语句> → <赋值语句> |<条件语句>|<循环语句> <赋值语句>→ID=<表达式><条件语句>→if ‘(‘条件’)’<语句块> <循环语句>→while ’(‘<条件>’)‘<语句块> <条件> → <表达式><关系运算符> <表达式> <表达式> →<项>{+<项>|-<项>}年级、专业、班学号姓名成绩实验项目名称 实验二 语法分析器指导教师李亚教师评语该同学是否了解实验原理: A.了解□ B.基本了解□ C.不了解□ 该同学的实验能力: A.强 □ B.中等 □ C.差 □ 该同学的实验是否达到要求: A.达到□B.基本达到□C.未达到□ 实验报告是否规范: A.规范□ B.基本规范□ C.不规范□是否有运行结果与分析: A.详细□ B.一般 □ C.没有 □ 是否有总结与体会: A.详细□B.一般 □C.没有 □教师签名: 年 月 日<项> → <因子> {* <因子> |/ <因子>}<因子> →ID|NUM| ‘(’<表达式>‘)’<关系运算符> →<|<=|>|>=|==|!=二、实验原理及基本技术路线图(方框原理图或程序流程图)开始调用打开对话框输入文法优化输入的文法并判断文法合法性获取文法的终结符和非终结符对文法求SELECT集并判断合法性构造文法分析法输入并分析句子结束三、所用仪器、材料(设备名称、型号、规格等或使用软件)1台PC及visual c++ 6.0软件四、实验方法、步骤(或:程序代码或操作过程)#include <iostream>#include <string>using namespace std;char prog[80],token[8];char ch;int syn,p,m,n,sum,k=0;char *key[6]={"main","int","char","if","else","while"};void scaner();void lrparser();void yucu();void statement();void expression();void term();void factor();void main(){p=0;cout<<"语法分析"<<endl;cout<<"请输入字符串,以@结尾:"<<endl;do {ch = getchar(); prog[p++]=ch;}while(ch!='@');p=0;scaner();lrparser();}void scaner(){sum=m=0;for(n=0;n<8;n++) token[n]=NULL;ch=prog[p++];while(ch==' ') ch=prog[p++];if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')){while((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')||(ch>='0'&&ch<='9')){token[m++]=ch; ch=prog[p++];}token[m++]='\0';p--;syn=10;for(n=0;n<6;n++)if(strcmp(token,key[n])==0){syn=n+1; break;}}else if(ch>='0'&&ch<='9'){while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=20;}elseswitch(ch){case '<': m=0;token[m++]=ch;ch=prog[p++];if(ch=='<') {syn=33; token[m++]=ch;}else if(ch=='=') {syn=35; token[m++]=ch;}break;case '>': m=0;token[m++]=ch;ch=prog[p++];if(ch=='=') {syn=34; token[m++]=ch;}else {syn=32; p--;}break;case '=':token[m++]=ch;ch=prog[p++];if(ch=='='){ syn=36;token[m++]=ch;}else{ syn=21;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=22; token[0]=ch; break;case '-': syn=23; token[0]=ch; break;case '*': syn=24; token[0]=ch; break;case '/': syn=25; token[0]=ch; break;case ';': syn=31; token[0]=ch; break;case '(': syn=26; token[0]=ch; break;case ')': syn=27; token[0]=ch; break;case '@': syn=0; token[0]=ch; break;default : syn=-1;}}void lrparser(){if(syn==1){scaner();yucu();if(syn=6){scaner();if(syn==0 && (k==0))cout<<"\nsuccess\n"<<endl;}else{if(k!=1)cout<<"\nwhile error\n"<<endl;k=1;}}else{cout<<"\nmain error\n"<<endl;k=1;}return;}void yucu(){statement();while(syn==31){scaner();statement();}return;}void statement(){if(syn==10){scaner();if(syn==18){scaner();expression();}else{cout<<"\nscentence error\n"<<endl;k=1;}}return;}void expression(){term();while(syn==22||syn==23){scaner();term();}return;}void term(){factor();while(syn==24||syn==25){scaner();factor();}return;}void factor(){if(syn==10||syn==20)scaner();else if(syn==26){scaner();expression();if(syn==27)scaner();else{cout<<"( error"<<endl;k=1;}}else{cout<<"expression error"<<endl;k=1;}return;}五、实验过程原始记录( 测试数据、图表、计算等)六、实验结果、分析和结论(程序运行结果、改进、收获)本实验在词法分析的基础上,对提取出的标识符进行语法判断。

编译原理实验(二)

编译原理实验(二)

实验编号:语法分析(2)一、实验目的及要求编制一个递归下降分析程序,实现对词法分析程序所提供的单词序列的语法检查和结构分析。

利用C语言编制递归下降分析程序,并对简单语言进行语法分析。

1待分析的简单语言的语法用扩充的BNF表示如下:⑴ <程序>::=begin<语句串>end⑵ <语句串>::=<语句>{;<语句>}⑶ <语句>::=<赋值语句>⑷ <赋值语句>::=ID :=<表达式>⑸ <表达式>::=<项>{+<项>卜<项>}⑹<项>::=<因子>{*<因子> | /<因子>⑺ <因子>::=ID | NUM | (<表达式>)2实验要求说明输入单词串,以“ #”结束,如果是文法正确的句子,则输出成功信息,打印“succesS', 否则输出"error”。

例如:输入begin a:=9; x:=2*3; b:=a+x end # 输出success!输入x:=a+b*c end # 输出error二、实验环境Microsoft Visual Studio VC6.0三、算法描述(1)主程序示意图如图2-1所示。

”-1 •: 结束图2-1语法分析主程序示意图(2) 递归下降分析程序示意图如图 2-2所示。

(3)语句串分析过程示意图如图 2-3所示。

调用expression 函数否是 否 是否是否调用语句串分析程序是 否出错处理否syn=O&&kk=O ?是打印分析成功出错处理否否否是2调用term 函数调用statement 函数调用statement 函数调用scaner调用scaner调用scaner 调用scaner图2-2 (4)statement 语 图2-3语句串分析示意图是否:=?是否+ , -?递归下降分析程序示意图J 分析程序流程如图 2-4、2-5、2-6、2-7所示。

1是调用scaner是否end?调用s caner是否标识符?#i nclude"stdio.h"#in elude "stri ng.h" char prog[100],toke n[ 8],ch; char *rwtab [6]={"begi n","if',"the n" ,"while","do","e nd"};int syn ,p,m, n,sum;调用term函数出错处理图2-4 statement语句分析函数示意图出错处理图2-5 expression表达式分析函数示意图四、源程序清单-3 •-4 •int kk;factor();〃 因子 expressio n();〃 表达式judgue();〃 判断语句、下一条语句 term();〃 项stateme nt();〃 赋值语句 lrparser();〃 判断、输出函数 scan er();〃 读下一个字符 yucu();void mai n(){ p=0;printf(- 请输入源程序:\n"); do {scan f("%c",&ch); prog[p++]=ch; }while(ch!='#'); p=0; sca ner(); lrparser(); prin tf(" 语法分析结束! \n");lrparser() {printf(" *********************语法分析程序 ************* **\n");if (syn==1) //begi n{sca ner();yucu();if (syn==6) //end{sca ner();if (sy n==O && kk==O)prin tf("success \n");}else{if(kk!=1)prin tf("error,lose 'end' !\n"); kk=1;}}else{prin tf("error,lose 'beg in' ! \n");kk=1;return 0;}yucu()• 5 •{stateme nt();while(sy n==26) //;{sca ner();stateme nt();}return 0;}stateme nt(){if (sy n==10){sca ner();if (syn==18){sca ner();expressi on();}else{prin tf("error!"); -6 •kk=1;}}else{prin tf("error!");kk=1;}return 0;}expressi on(){term();while(s yn==13 || syn==14){sca ner();term();}return 0;}term(){factor();while(s yn==15 || syn==16)sea ner();factor();-7 •}return 0;}factor(){if(syn==10 || syn==11)scan er(); // 为标识符或整常数时,读下一个单词符号else if(syn==27){sca ner();expressi on();if(sy n==28)sca ner();else{printf("')' 错误\n"); kk=1;}}else{printf(" 表达式错误\n"); kk=1;}return 0;sea ner(){ sum=O;• 8 •for(m=0;m<8;m++)toke n[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'))){toke n[ m++]=ch;ch=prog[p++];}p--;sy n=10;toke n[m++]='\0';for(n=0;n<6;n++)if(strcmp(toke n,rwtab[ n])==0)〃判断是否为关键字{syn=n+1;break;}}else if((ch>='0')&&(ch<='9')){ while((ch>='0')&&(ch<=9)){ sum=sum*10+ch-'0';ch=prog[p++];}p--;syn=11;-9 •}else switch(ch){ case 'v':m=O; ch=prog[p++]; if(ch=='>'){ syn=21;}else if(ch=='='){ sy n=22;}else{ sy n=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;-10 •}else{ 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;}return 0;-11 •五、运行结果及分析输入begin a:=9;x:=2*3;b:二a+x end # 输出successerror输入x:=a+b*c end # 输出-12 •。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

编译原理二-------词法分析器一.问题描述词法分析程序的功能:输入源程序,输出单词符号,如图所示:单词符号处理过程:在扫描源程序字符串时,一旦识别出关键字、分隔符、标识符、无符号常数中之一,即以单词形式(各类单词均采用相同的结构,即二元式编码形式)输出。

每次调用词法分析程序,它均能自动继续扫描下去,形成下一个单词,直至整个源程序全部扫描完毕,并形成相应的单词串形式的源程序。

二.需求分析1.对给定的程序通过词法分析器能够识别一个个单词符号,并以二元式(单词类型,单词符号)显示;2.可以将要分析的程序保存到文件中进行读取;3.删除无用的空白字符、回车符、及其它非实质性符号。

三.程序设计本程序规定:(1)关键字"begin","end","if","then","else","while","write","read","do", "call","const","char","until","procedure","repeat"(2)运算符:"+","-","*","/","="(3)界符:"{","}","[","]",";",",",".","(",")",":"(4)其他标记如字符串,表示以字母开头的标识符。

(5)空格、回车、换行符跳过。

对于一段可能的输入代码,其结果在屏幕上显示如下:( 1 , 无符号整数)( begin , 关键字)( if , 关键字)( +, 运算符)( ;, 界符)( a , 普通标识符)关键字或标识符的判断:读入一串字符,将ASCII码在字母范围的字符存入数组中,将该数组与设置好的关键字比较,如果相等则输出是关键字,否则继续读入直至下一字符既非数字也非字母,输出为标识符;数字的判断:若跟在字母后面则一起输出为标识符,否则输出为数字;界符、运算符的判断:直接判断其ASCII码运行过程为:1.预处理:把源文件一个字符一个字符的读入词法分析程序设置的输入字符结构体数组中(输入缓冲区),读入过程要删除多余的空格;2.源程序字符数组中获得单词, 编码为二元式.:二元式采用结构体数组存储, 把单词类型和词元记录下来。

为了方便和适用起见,首先建立一个文本,进而在文本中进行pascal语言输入。

输入完毕之后,就可以进行从文本中取字符,进而把它放在一个数组中。

之后再数组中进行取字符,之前要定义一个数组,定义一个指针指向数组,为first。

之后就用一个循环依次从数组中取字符,假如是字符就放在buf中,first++;一次进行下去,期间要时刻与关键字指针数组进行比较如果相等就立马输出,并显示是关键字此时将buf置为初值,first重新指向首地址。

四.流程图Y是界符NERROR五.调试分析刚开始的时候,我的程序没有采用文件形式,结果只能输入一行代码分析一行,很不实用,后来我想到可以将分析结果保存到数组中,并将结果和结果之间用空格分隔开,这样在输出时就可以连续输出了,我将这一思想运用到了文件系统中,经过改进,现在的程序可以分析保存在文件中的比较长的代码了。

六.用户手册现将要处理的代码段保存于文件中,在本程序中,我保存的位置是D:\ hello.txt,文件内容如下图所示:点击运行程序需要先输入待分析代码的文件位置,在本程序中是D:\ hello.txt,输入后程序自动分析并输出结果。

七.运行结果点击运行程序,其分析结果如下:八.程序代码:#include <iostream>#include<string>using namespace std;#define MAX 22char ch =' ';string key[15]={"begin","end","if","then","else","while","write","read", "do", "call","const","char","until","procedure","repeat"};int Iskey(string c){ //关键字判断int i;for(i=0;i<MAX;i++) {if(key[i].compare(c)==0) return 1;}return 0;}int IsLetter(char c) { //判断是否为字母if(((c<='z')&&(c>='a'))||((c<='Z')&&(c>='A'))) return 1; else return 0;}int IsDigit(char c){ //判断是否为数字if(c>='0'&&c<='9') return 1;else return 0;}void fenxi(FILE *fpin){string arr="";while((ch=fgetc(fpin))!=EOF) {arr="";if(ch==' '||ch=='\t'||ch=='\n'){}else if(IsLetter(ch)){while(IsLetter(ch)||IsDigit(ch)) {if((ch<='Z')&&(ch>='A')) ch=ch+32; arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);if (Iskey(arr)){cout<<arr<<"\t$关键字"<<endl;} else cout<<arr<<"\t$普通标识符"<<endl; }else if(IsDigit(ch)){while(IsDigit(ch)||ch=='.'&&IsDigit(fgetc(fpin))){ arr=arr+ch;ch=fgetc(fpin);}fseek(fpin,-1L,SEEK_CUR);cout<<arr<<"\t$无符号实数"<<endl;}else switch(ch){case'+':case'-' :case'*' :case'=' :case'/' :cout<<ch<<"\t$运算符"<<endl;break;case'(' :case')' :case'[' :case']' :case';' :case'.' :case',' :case'{' :case'}' :cout<<ch<<"\t$界符"<<endl;break;case':' :{ch=fgetc(fpin);if(ch=='=') cout<<":="<<"\t$运算符"<<endl; else {cout<<"="<<"\t$运算符"<<endl;;fseek(fpin,-1L,SEEK_CUR);}}break;case'>' :{ch=fgetc(fpin);if(ch=='=') cout<<">="<<"\t$运算符"<<endl;if(ch=='>')cout<<">>"<<"\t$输入控制符"<<endl;else {cout<<">"<<"\t$运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;case'<' :{ch=fgetc(fpin);if(ch=='=')cout<<"<="<<"\t$运算符"<<endl;else if(ch=='<')cout<<"<<"<<"\t$输出控制符"<<endl; else if(ch=='>') cout<<"<>"<<"\t$运算符"<<endl;else{cout<<"<"<<"\t$运算符"<<endl;fseek(fpin,-1L,SEEK_CUR);}}break;default : cout<<ch<<"\t$无法识别字符"<<endl;}}}void main(){char in_fn[30];FILE * fpin;cout<<"请输入源文件名(包括路径和后缀名):";for(;;){cin>>in_fn;if((fpin=fopen(in_fn,"r"))!=NULL) break;else cout<<"文件路径错误!请输入源文件名(包括路径和后缀名):"; }cout<<"\n********************分析如下*********************"<<endl; fenxi(fpin);fclose(fpin);}九.实验总结分析通过这次实验,我对词法分析器有了一定的了解,进一步的巩固了这部分的知识。

相关文档
最新文档