实验一_文法分析方法及其应用 (1)

合集下载

LR(0)文法分析

LR(0)文法分析

实验名称:LR(0)文法分析一、实验目的:输入:任意的压缩了的上下文无关文法。

输出:相应的LR(0)分析表。

二、实验原理:对于LR文法,我们可以自动构造相应的LR分析表。

为了构造LR分析表,我们需要定义一个重要概念——文法的规范句型“活前缀”。

这种句柄之后不含任何符号的前缀称为活前缀。

在LR分析工作过程中的任何时候,栈里的文法符号(自栈底而上)X1X2…X m应该构成活前缀,把输入串的剩余部分配上之后即应成为规范句型(如果整个输入串确实构成一个句子)。

因此,只要输入串的已扫描部分保持可归约成一个活前缀,那就意味着所扫描过的部分没有错误。

对于一个文法G,我们可以构造一个有限自动机,它能识别G的所有活前缀,然后把这个自动机转变成LR分析表,按照该LR分析表进行LR分析,就能保证在分析的过程中,如果分析的句子是正确的,栈里的文法符号(自栈底而上)始终构成活前缀。

假若一个文法G的拓广文法G'的活前缀识别自动机中的每个状态(项目集)不存在下述情况:(1)既含移进项目又含归约项目;(2)含有多个归约项目,则称G是一个LR(0)文法。

该自动机的状态集合即为该文法的LR(0)项目集规范族。

构造识别文法活前缀DFA有3种方法:(1)根据形式定义求出活前缀的正则表达式,然后由此正则表达式构造NFA 再确定为DFA;(2)求出文法的所有项目,按一定规则构造识别活前缀的NFA再确定化为DFA;(3)使用闭包函数(CLOSURE)和转向函数(GO(I,X))构造文法G’的LR(0)的项目集规范族,再由转换函数建立状态之间的连接关系来得到识别活前缀的DFA。

符号串的前缀是指该符号串的任意首部,包括空串ε。

例如,对于符号串abc,其前缀有ε,a,ab,abc。

如果输入串没有错误的话,一个规范句型的活前缀是该句型的一个前缀,但它不含句柄之后的任何符号。

之所以称为活前缀,是因为在该前缀后联接尚未输入的符号串可以构成一个规范句型。

编译原理LL(1)文法分析器实验(java)

编译原理LL(1)文法分析器实验(java)

编译原理LL(1)文法分析器实验本程序是基于已构建好的某一个语法的预测分析表来对用户的输入字符串进行分析,判断输入的字符串是否属于该文法的句子。

基本实现思想:接收用户输入的字符串(字符串以“#”表示结束)后,对用做分析栈的一维数组和存放分析表的二维数组进行初始化。

然后取出分析栈的栈顶字符,判断是否为终结符,若为终结符则判断是否为“#”且与当前输入符号一样,若是则语法分析结束,输入的字符串为文法的一个句子,否则出错若不为“#”且与当前输入符号一样则将栈顶符号出栈,当前输入符号从输入字符串中除去,进入下一个字符的分析。

若不为“#”且不与当前输入符号一样,则出错。

若栈顶符号为非终结符时,查看预测分析表,看栈顶符号和当前输入符号是否构成产生式,若产生式的右部为ε,则将栈顶符号出栈,取出栈顶符号进入下一个字符的分析。

若不为ε,将产生式的右部逆序的入栈,取出栈顶符号进入下一步分析。

程序流程图:本程序中使用以下文法作对用户输入的字符串进行分析:E→TE’E’→+TE’|εT→FT’T’→*FT’|εF→i|(E)该文法的预测分析表为:1、显示预测分析表,提示用户输入字符串2、输入的字符串为正确的句子:3、输入的字符串中包含了不属于终结符集的字符4、输入的字符串不是该文法能推导出来的句子程序代码:package ;import java.io.*;public class LL {String Vn[] = { "E", "E'", "T", "T'", "F" }; // 非终结符集String Vt[] = { "i", "+", "*", "(", ")", "#" }; // 终结符集String P[][] = new String[5][6]; // 预测分析表String fenxi[] ; // 分析栈int count = 1; // 步骤int count1 = 1;//’分析栈指针int count2 = 0, count3 = 0;//预测分析表指针String inputString = ""; // 输入的字符串boolean flag;public void setCount(int count, int count1, int count2, int count3){this.count = count;this.count1 = count1;this.count2 = count2;this.count3 = count3;flag = false;}public void setFenxi() { // 初始化分析栈fenxi = new String[20];fenxi[0] = "#";fenxi[1] = "E";}public void setP() { // 初始化预测分析表for (int i = 0; i < 5; i++) {for (int j = 0; j < 6; j++) {P[i][j] = "error";}}P[0][0] = "->TE'";P[0][3] = "->TE'";P[1][1] = "->+TE'";P[1][4] = "->ε";P[1][5] = "->ε";P[2][0] = "->FT'";P[2][3] = "->FT'";P[3][1] = "->ε";P[3][2] = "->*FT'";P[3][4] = "->ε";P[3][5] = "->ε";P[4][0] = "->i";P[4][3] = "->(E)";// 打印出预测分析表System.out.println(" 已构建好的预测分析表");System.out.println("----------------------------------------------------------------------");for (int i=0; i<6; i++) {System.out.print(" "+Vt[i]);}System.out.println();System.out.println("----------------------------------------------------------------------");for (int i=0; i<5; i++) {System.out.print(" "+Vn[i]+" ");for (int j=0; j<6; j++) {int l = 0;if (j>0) {l = 10-P[i][j-1].length();}for (int k=0; k<l; k++) {System.out.print(" ");}System.out.print(P[i][j]+" ");}System.out.println();}System.out.println("----------------------------------------------------------------------"); }public void setInputString(String input) {inputString = input;}public boolean judge() {String inputChar = inputString.substring(0, 1); // 当前输入字符boolean flage = false;if (count1 >= 0) {for (int i=0; i<6; i++) {if (fenxi[count1].equals(Vt[i])) { // 判断分析栈栈顶的字符是否为终结符flage = true;break;}}}if (flage) {// 为终结符时if (fenxi[count1].equals(inputChar)) {if (fenxi[count1].equals("#")&&inputString.length()==1) { // 栈顶符号为结束标志时// System.out.println("最后一个");String fenxizhan = "";for (int i=0; i<=P.length; i++) { // 拿到分析栈里的全部内容(滤去null)if (fenxi[i] == null) {break;} else {fenxizhan = fenxizhan + fenxi[i];}}// 输出当前分析栈情况,输入字符串,所用产生式或匹配System.out.print(" " + count);String countToString = Integer.toString(count);int farWay = 14 - countToString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(fenxizhan);farWay = 20 - fenxizhan.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(inputString);farWay = 25 - inputString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.println("接受");flag = true;return true;} else {// 分析栈栈顶符号不为结束标志符号时String fenxizhan = "";for (int i=0; i<=P.length; i++) { // 拿到分析栈里的全部内容(滤去null)if (fenxi[i] == null) {break;} else {fenxizhan = fenxizhan + fenxi[i];}}// 输出当前分析栈情况,输入字符串,所用产生式或匹配System.out.print(" "+count);String countToString = Integer.toString(count);int farWay = 14 - countToString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(fenxizhan);farWay = 20 - fenxizhan.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(inputString);farWay = 25 - inputString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.println("\"" + inputChar + "\"" + "匹配");// 将栈顶符号出栈,栈顶指针减一fenxi[count1] = null;count1 -= 1;if (inputString.length() > 1) { // 当当前输入字符串的长度大于1时,将当前输入字符从输入字符串中除去inputString = inputString.substring(1, inputString.length());} else { // 当前输入串长度为1时inputChar = inputString;}// System.out.println(" "+count+" "+fenxizhan+"// "+inputString +" "+P[count3][count2]);// System.out.println(count + inputChar + "匹配");count++;judge();}}else { // 判断与与输入符号是否一样为结束标志System.out.println(" 分析到第" + count + "步时出错!");flag = false;return false;}} else {// 非终结符时boolean fla = false;for (int i=0; i<6; i++) { // 查询当前输入符号位于终结符集的位置if (inputChar.equals(Vt[i])) {fla = true;count2 = i;break;}}if(!fla){System.out.println(" 分析到第" + count + "步时出错!");flag = false;return false;}for (int i=0; i<5; i++) { // 查询栈顶的符号位于非终结符集的位置if (fenxi[count1].equals(Vn[i])) {count3 = i;break;}}if (P[count3][count2] != "error") { // 栈顶的非终结符与输入的终结符存在产生式时String p = P[count3][count2];String s1 = p.substring(2, p.length()); // 获取对应的产生式if (s1.equals("ε")) { // 产生式推出“ε”时String fenxizhan = "";for (int i=0; i<=P.length; i++) {if (fenxi[i] == null) {break;} else {fenxizhan = fenxizhan + fenxi[i];}}// 输出当前分析栈情况,输入字符串,所用产生式或匹配System.out.print(" " + count);String countToString = Integer.toString(count);int farWay = 14 - countToString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(fenxizhan);farWay = 20 - fenxizhan.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.print(inputString);farWay = 25 - inputString.length();for (int k=0; k<farWay; k++) {System.out.print(" ");}System.out.println(fenxi[count1] + P[count3][count2]);// 将栈顶符号出栈,栈顶指针指向下一个元素fenxi[count1] = null;count1 -= 1;count++;judge();} else { // 产生式不推出“ε”时int k = s1.length();String fenxizhan = "";for (int i=0; i<=P.length; i++) {if (fenxi[i] == null) {break;} else {fenxizhan = fenxizhan + fenxi[i];}}// 输出当前分析栈情况,输入字符串,所用产生式或匹配System.out.print(" "+count);String countToString = Integer.toString(count);int farWay = 14 - countToString.length();for (int o=0; o<farWay; o++) {System.out.print(" ");}System.out.print(fenxizhan);farWay = 20 - fenxizhan.length();for (int o=0; o<farWay; o++) {System.out.print(" ");}System.out.print(inputString);farWay = 25 - inputString.length();for (int o=0; o<farWay; o++) {System.out.print(" ");}System.out.println(fenxi[count1] + P[count3][count2]);for (int i=1; i<=k; i++) { // 将产生式右部的各个符号入栈String s2 = s1.substring(s1.length() - 1, s1.length());s1 = s1.substring(0, s1.length() - 1);if (s2.equals("'")) {s2 = s1.substring(s1.length() - 1, s1.length())+ s2;i++;s1 = s1.substring(0, s1.length() - 1);}fenxi[count1] = s2;if (i < k)count1++;// System.out.println("count1=" + count1);}// System.out.println(" "+count+" "+fenxizhan+"// "+inputString +" "+P[count3][count2]);count++;// System.out.println(count);judge();}} else {System.out.println(" 分析到第" + count + "步时出错!");flag = false;return false;}}return flag;}public static void main(String args[]) {LL l = new LL();l.setP();String input = "";boolean flag = true;while (flag) {try {InputStreamReader isr = new InputStreamReader(System.in);BufferedReader br = new BufferedReader(isr);System.out.println();System.out.print("请输入字符串(输入exit退出):");input = br.readLine();} catch (Exception e) {e.printStackTrace();}if(input.equals("exit")){flag = false;}else{l.setInputString(input);l.setCount(1, 1, 0, 0);l.setFenxi();System.out.println();System.out.println("分析过程");System.out.println("----------------------------------------------------------------------");System.out.println(" 步骤| 分析栈| 剩余输入串| 所用产生式");System.out.println("----------------------------------------------------------------------");boolean b = l.judge();System.out.println("----------------------------------------------------------------------");if(b){System.out.println("您输入的字符串"+input+"是该文发的一个句子");}else{System.out.println("您输入的字符串"+input+"有词法错误!");}}}}}。

编译原理词法分析,语法分析实验报告

编译原理词法分析,语法分析实验报告

编译原理实验报告一.LL(1)文法分析1.设计要求(1)对输入文法,它能判断是否为LL(1)文法,若是,则转(2);否则报错并终止;(2)输入已知文法,由程序自动生成它的LL(1)分析表;(3)对于给定的输入串,应能判断识别该串是否为给定文法的句型。

2.分析该程序可分为如下几步:(1)读入文法(2)判断正误(3)若无误,判断是否为LL(1)文法(4)若是,构造分析表;(5)由总控算法判断输入符号串是否为该文法的句型。

3.流程图开始读入文法有效?是是LL(1)文法?是判断句型报错结束4.源程序/*******************************************语法分析程序作者:xxx学号:xxx********************************************/#include<stdlib.h>#include<stdio.h>#include<string.h>/*******************************************/int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/ char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*//*******************************************判断一个字符是否在指定字符串中********************************************/int in(char c,char *p){int i;if(strlen(p)==0)return(0);for(i=0;;i++){if(p[i]==c)return(1); /*若在,返回1*/if(i==strlen(p))return(0); /*若不在,返回0*/}}/*******************************************得到一个不是非终结符的符号********************************************/char c(){char c='A';while(in(c,non_ter)==1)c++;return(c);}/*******************************************分解含有左递归的产生式********************************************/void recur(char *point){ /*完整的产生式在point[]中*/int j,m=0,n=3,k;char temp[20],ch;ch=c(); /*得到一个非终结符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++){if(point[n]==point[0]){ /*如果‘|’后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++){while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|'){n=j+1;break;}}}else{ /*如果‘|’后的首符号和左部不同*/ left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;}}}/*******************************************分解不含有左递归的产生式********************************************/void non_re(char *point){int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++){if(point[j]!='|')temp[m++]=point[j];else{left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;}}left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;}/*******************************************读入一个文法********************************************/ char grammer(char *t,char *n,char *left,char right[50][50]) {char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("\n请输入文法的非终结符号串:");scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++){printf("请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();}for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){ printf("\ninput error!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);}return(s);}/*******************************************将单个符号或符号串并入另一符号串********************************************/void merge(char *d,char *s,int type){ /*d是目标符号串,s是源串,type=1,源串中的‘^ ’一并并入目串;type=2,源串中的‘^ ’不并入目串*/int i,j;for(i=0;i<=strlen(s)-1;i++){if(type==2&&s[i]=='^');else{for(j=0;;j++){if(j<strlen(d)&&s[i]==d[j])break;if(j==strlen(d)){d[j]=s[i];d[j+1]='\0';}}}}}/*******************************************求所有能直接推出^的符号********************************************/void emp(char c){ /*即求所有由‘^ ’推出的符号*/ char temp[10];int i;for(i=0;i<=count-1;i++){if(right[i][0]==c&&strlen(right[i])==1){temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);}}}/*******************************************求某一符号能否推出‘^ ’********************************************/int _emp(char c){ /*若能推出,返回1;否则,返回0*/ int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)return(1);for(i=0;;i++){if(i==count)return(0);if(left[i]==c) /*找一个左部为c的产生式*/{j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1)else if(j==1&&in(right[i][0],termin)==1)return(0);else{for(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;else{for(k=0;k<=j-1;k++){result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);}}}if(result==0&&i<count)continue;else if(result==1&&i<count)return(1);}}}/*******************************************判断读入的文法是否正确********************************************/int judge(){int i,j;for(i=0;i<=count-1;i++){if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/ printf("\nerror1!");validity=0;return(0);}for(j=0;j<=strlen(right[i])-1;j++){if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^'){ /*若右部某一符号不在非终结符、终结符中且不为‘^ ’,报错*/ printf("\nerror2!");validity=0;return(0);}}}return(1);}/*******************************************求单个符号的FIRST********************************************/void first2(int i){ /*i为符号在所有输入符号中的序号*/char c,temp[20];int j,k,m;c=v[i];char ch='^';emp(ch);if(in(c,termin)==1) /*若为终结符*/{first1[i][0]=c;first1[i][1]='\0';}else if(in(c,non_ter)==1) /*若为非终结符*/{for(j=0;j<=count-1;j++){if(left[j]==c){if(in(right[j][0],termin)==1||right[j][0]=='^'){temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);}else if(in(right[j][0],non_ter)==1){if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])break;if(f[k]=='0'){first2(k);f[k]='1';}merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++){empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1){for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0'){first2(m);f[m]='1';}merge(first1[i],first1[m],2);}else if(_emp(right[j][k])==1&&k==strlen(right[j])-1){temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);}elsebreak;}}}}}f[i]='1';}/*******************************************求各产生式右部的FIRST********************************************/void FIRST(int i,char *p){int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/ {if(p[0]=='^'){if(i>=0){first[i][0]='^';first[i][1]='\0';}else{TEMP[0]='^';TEMP[1]='\0';}}else{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0){memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';}else{memcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';}}}else /*如果右部为符号串*/{for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++){empt[0]='\0';if(_emp(p[k])==1&&k<length-1){for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)merge(first[i],first1[m],2);elsemerge(TEMP,first1[m],2);}else if(_emp(p[k])==1&&k==length-1){temp[0]='^';temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);}else if(_emp(p[k])==0)break;}}}/*******************************************求各产生式左部的FOLLOW********************************************/ void FOLLOW(int i){int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/ temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);}for(j=0;j<=count-1;j++){if(in(c,right[j])==1) /*找一个右部含有c的产生式*/{for(k=0;;k++)if(right[j][k]==c)break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j])break; /*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1){merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}else{ /*如果c不在产生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++){empt[0]='\0';result*=_emp(right[j][n]);}if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;}if(F[m]=='0'){FOLLOW(m);F[m]='1';}merge(follow[i],follow[m],1);}for(n=k+1;n<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);}}}F[i]='1';}/*******************************************判断读入文法是否为一个LL(1)文法********************************************/int ll1(){int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';}for(j=0;j<=strlen(v)-1;j++)first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n:::\n_emp:");for(j=0;j<=strlen(v)-1;j++)printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++)FIRST(i,right[i]); /*求FIRST*/printf("\n");for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW*/if(fo[j]==0){fo[0]='\0';FOLLOW(j);}}printf("\nfirst:");for(i=0;i<=count-1;i++)printf("%s ",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++)printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1){for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],1);}}printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/ length=strlen(temp);if(left[i]==left[i-1]){merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);}else{temp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';}}return(1);}/*******************************************构造分析表M********************************************/void MM(){int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++){for(m=0;;m++)if(non_ter[m]==left[i])break; /*m为产生式左部非终结符的序号*/for(j=0;j<=strlen(select[i])-1;j++){if(in(select[i][j],termin)==1){for(k=0;;k++)if(termin[k]==select[i][j])break; /*k为产生式右部终结符的序号*/ M[m][k]=i;}}}}/*******************************************总控算法********************************************/void syntax(){int i,j,k,m,n,p,q;char ch;char S[50],str[50];printf("请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1){if(in(S[strlen(S)-1],termin)==1){if(S[strlen(S)-1]!=ch){printf("\n该符号串不是文法的句型!");return;}else if(S[strlen(S)-1]=='#'){printf("\n该符号串是文法的句型.");return;}else{S[strlen(S)-1]='\0';j++;ch=str[j];}}else{for(i=0;;i++)if(non_ter[i]==S[strlen(S)-1])break;for(k=0;;k++){if(termin[k]==ch)break;if(k==strlen(termin)){printf("\n词法错误!");return;}}if(M[i][k]==-1){printf("\n语法错误!");return;}else{m=M[i][k];if(right[m][0]=='^')S[strlen(S)-1]='\0';else{p=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--)S[p++]=right[m][n];S[q+strlen(right[m])]='\0';}}}printf("\nS:%s str:",S);for(p=j;p<=strlen(str)-1;p++)printf("%c",str[p]);printf(" ");}}/*******************************************一个用户调用函数********************************************/void menu(){syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y'){menu();}}/*******************************************主函数********************************************/void main(){int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/ printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++)printf("%c ",left[i]);if(validity==1)validity=judge();printf("\nvalidity=%d",validity);if(validity==1){printf("\n文法有效");ll=ll1();printf("\nll=%d",ll);if(ll==0)printf("\n该文法不是一个LL1文法!");else{MM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);printf("\n");menu();}}}5.执行结果(1)输入一个文法(2)输入一个符号串(3)再次输入一个符号串,然后退出程序二.词法分析一、问题描述识别简单语言的单词符号识别简单语言的基本字、标识符、无符号整数、运算符和界符。

实验 LL(1)文法 计算器

实验 LL(1)文法 计算器

主程序的代码结构是一致的
递归子程序法中主程序的结构是一样的,它们都是读入第一个符 号,然后调用开始符对应的子程序。
主程序: 开始
读第一个单词
开始符子程序
# OK 结束
n
error
例如:G(S): S→aS|b
S子程序: 开始
主程序: 开始 读第一个符号
a
n
b
y next
n
S
error #
S
结束
y next
# OK 结束
y next E
结束
扩展


可进行多行表达式计算 让计算器支持括号 让计算器支持负数
实验检查

2015年10月9日(第四周)做ppt汇报实验

按y=f(x)的思路进行汇报

先随机选三位同学汇报 鼓励做得更好的同学进行汇报
G(S): S→ABC
主程序:
A→ad
B→be
S子程序:
C→cf
A子程序:
开始
next
开始
开始 a
next n error
A B n
error
S

OK 结束
读第一个单词
……
n error
C
结束
d
next 结束
递归子程序法的思想
例如:设文法G(S)的一个产生式如下
S→A1A2…An
Ai∈(VN∪VT)
error
n
error

开始
y
OK 结束
y next S
结束
a
n b
n
error 返回
y next #
例:设文法G(S) 如下

自动机实验报告(3篇)

自动机实验报告(3篇)

第1篇一、实验目的1. 理解自动机的概念和分类。

2. 掌握有限自动机(FA)和正规文法(CFG)的基本原理。

3. 学习自动机的应用,如词法分析、语法分析等。

4. 通过实验加深对自动机理论的理解。

二、实验内容1. 有限自动机(FA)- 实验一:设计并实现一个识别特定字符串的有限自动机实验步骤:(1)根据题目要求,确定输入字母表和输出字母表。

(2)设计有限自动机的状态转移图。

(3)编写代码实现有限自动机的状态转移功能。

(4)测试有限自动机对特定字符串的识别能力。

- 实验二:分析并验证有限自动机的正确性实验步骤:(1)根据实验一的结果,分析有限自动机的状态转移图。

(2)验证有限自动机是否满足题目要求。

(3)如果有限自动机不满足要求,修改状态转移图,重新进行实验。

2. 正规文法(CFG)- 实验一:设计并实现一个正规文法实验步骤:(1)根据题目要求,确定正规文法中的非终结符、终结符和产生式。

(2)编写代码实现正规文法的生成功能。

(3)测试正规文法生成的句子是否满足题目要求。

- 实验二:将正规文法转换为有限自动机实验步骤:(1)根据实验一的结果,分析正规文法。

(2)将正规文法转换为有限自动机。

(3)测试有限自动机对句子进行词法分析的能力。

三、实验结果与分析1. 实验一:有限自动机- 在实验一中,我们成功设计并实现了识别特定字符串的有限自动机。

通过测试,我们发现有限自动机能够正确识别给定的字符串。

- 在实验二中,我们分析了有限自动机的状态转移图,并验证了其正确性。

我们发现有限自动机满足题目要求,能够正确识别给定的字符串。

2. 实验二:正规文法- 在实验一中,我们成功设计并实现了正规文法。

通过测试,我们发现正规文法能够生成满足题目要求的句子。

- 在实验二中,我们将正规文法转换为有限自动机,并测试了其对句子进行词法分析的能力。

我们发现有限自动机能够正确对句子进行词法分析。

四、实验总结通过本次实验,我们掌握了有限自动机和正规文法的基本原理,并学会了如何将它们应用于实际问题。

LL(1)分析法

LL(1)分析法

LL(1)分析法编译原理实验报告日期:班级:题目:LL(1)分析法组员:LL(1)语法分析程序1. 实验目的:1.根据某一文法编制调试LL (1)分析程序,以便对任意输入的符号串进行分析。

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

2. 实验平台Windows + VC + Win32 Console范例程序: “3-LL1.c ”3. 实验内容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程序输入/输出示例:程序现有功能:输入: 一个以 # 结束的符号串(包括 + * ( )i # )输出: 只能输出步骤1, 格式如下:程序目前还不能对所有输入串进行正确的分析. 需要完善的功能:(1) 请输出完整的分析过程。

即详细输出每一步骤分析栈和剩余串的变化情况, 及每一步所用的产生式.(2) 请输出最终的分析结果, 即输入串 “合法”或 “非法”.(3)示例程序只能完成 + 、* 、(、)的语法分析, 请加入 - 和 / 的语法分析(4)可将测试用的表达式事先放在文本文件中,一行存放一个表达式,以分号分割。

同时将预期的输出结果写在另一个文本文件中,以便和输出进行对照;备注:1. 在“所用产生式”一列中,如果对应有推导,则写出所用产生式;如果为匹配终结符,则写明匹配的终结符; 如分析异常出错则,写为“分析出错”;如成功结束则写为“分析成功”。

步骤 分析栈 剩余输入串 所用产生式 1 #E i+i*i# E →TG2. 对一个新的文法实现LL(1)分析。

4.程序代码第一种文法#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[7];/*产生式右边字符*/int length;/*字符个数*/}type;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++)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;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][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;printf("提示:本程序只能对由'i','+','-','*','/','(',')'构成的以'#'结束的字符串进行分析,\n");printf("请输入要分析的字符串:\n");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"); dox=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("合法\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*/测试一(1)测试i+i#(2)测试i-i(3)测试i*i#(4)测试i/i#(5)测试i+i*i#(6)测试输入非法字符i+i*#第二中文发#include<stdlib.h>#include<stdio.h>#include<string.h>int count=0; /*分解的产生式的个数*/int number; /*所有终结符和非终结符的总数*/char start; /*开始符号*/char termin[50]; /*终结符号*/char non_ter[50]; /*非终结符号*/char v[50]; /*所有符号*/char left[50]; /*左部*/char right[50][50]; /*右部*/char first[50][50],follow[50][50]; /*各产生式右部的FIRST和左部的FOLLOW集合*/char first1[50][50]; /*所有单个符号的FIRST集合*/char select[50][50]; /*各单个产生式的SELECT集合*/char f[50],F[50]; /*记录各符号的FIRST和FOLLOW是否已求过*/ char empty[20]; /*记录可直接推出^的符号*/char TEMP[50]; /*求FOLLOW时存放某一符号串的FIRST集合*/ int validity=1; /*表示输入文法是否有效*/int ll=1; /*表示输入文法是否为LL(1)文法*/int M[20][20]; /*分析表*/char choose; /*用户输入时使用*/char empt[20]; /*求_emp()时使用*/char fo[20]; /*求FOLLOW集合时使用*/判断一个字符是否在指定字符串中int in(char c,char *p)int i;if(strlen(p)==0)return(0);for(i=0;;i++)if(p[i]==c)return(1); /*若在,返回1*/if(i==strlen(p))return(0); /*若不在,返回0*/得到一个不是非终结符的符号char c()char c='A';while(in(c,non_ter)==1)c++;return(c);分解含有左递归的产生式void recur(char *point){ /*完整的产生式在point[]中*/int j,m=0,n=3,k;char temp[20],ch;ch=c(); /*得到一个非终结符*/k=strlen(non_ter);non_ter[k]=ch;non_ter[k+1]='\0';for(j=0;j<=strlen(point)-1;j++)if(point[n]==point[0]){ /*如果'|'后的首符号和左部相同*/ for(j=n+1;j<=strlen(point)-1;j++)while(point[j]!='|'&&point[j]!='\0')temp[m++]=point[j++];left[count]=ch;memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';m=0;count++;if(point[j]=='|')n=j+1;break;else{ /*如果'|'后的首符号和左部不同*/ left[count]=ch;right[count][0]='^';right[count][1]='\0';count++;for(j=n;j<=strlen(point)-1;j++)if(point[j]!='|')temp[m++]=point[j];elseleft[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';printf(" count=%d ",count);m=0;count++;left[count]=point[0];memcpy(right[count],temp,m);right[count][m]=ch;right[count][m+1]='\0';count++;m=0;分解不含有左递归的产生式void non_re(char *point)int m=0,j;char temp[20];for(j=3;j<=strlen(point)-1;j++)if(point[j]!='|')temp[m++]=point[j];elseleft[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';m=0;count++;left[count]=point[0];memcpy(right[count],temp,m);right[count][m]='\0';count++;m=0;读入一个文法char grammer(char *t,char *n,char *left,char right[50][50]) char vn[50],vt[50];char s;char p[50][50];int i,j,k;printf("\n请输入文法的非终结符号串:");scanf("%s",vn);getchar();i=strlen(vn);memcpy(n,vn,i);n[i]='\0';printf("请输入文法的终结符号串:");scanf("%s",vt);getchar();i=strlen(vt);memcpy(t,vt,i);t[i]='\0';printf("请输入文法的开始符号:");scanf("%c",&s);getchar();printf("请输入文法产生式的条数:");scanf("%d",&i);getchar();for(j=1;j<=i;j++)printf("请输入文法的第%d条(共%d条)产生式:",j,i);scanf("%s",p[j-1]);getchar();for(j=0;j<=i-1;j++)if(p[j][1]!='-'||p[j][2]!='>'){ printf("\ninput error!");validity=0;return('\0');} /*检测输入错误*/for(k=0;k<=i-1;k++){ /*分解输入的各产生式*/if(p[k][3]==p[k][0])recur(p[k]);elsenon_re(p[k]);return(s);将单个符号或符号串并入另一符号串void merge(char *d,char *s,int type){ /*d是目标符号串,s是源串,type=1,源串中的' ^ '一并并入目串;type=2,源串中的' ^ '不并入目串*/int i,j;for(i=0;i<=strlen(s)-1;i++)if(type==2&&s[i]=='^')elsefor(j=0;;j++)if(j<strlen(d)&&s[i]==d[j])break;if(j==strlen(d))d[j]=s[i];d[j+1]='\0';break;求所有能直接推出^的符号void emp(char c){ /*即求所有由' ^ '推出的符号*/char temp[10];int i;for(i=0;i<=count-1;i++)if(right[i][0]==c&&strlen(right[i])==1)temp[0]=left[i];temp[1]='\0';merge(empty,temp,1);emp(left[i]);求某一符号能否推出' ^ 'int _emp(char c){ /*若能推出,返回1;否则,返回0*/int i,j,k,result=1,mark=0;char temp[20];temp[0]=c;temp[1]='\0';merge(empt,temp,1);if(in(c,empty)==1)return(1);for(i=0;;i++)if(i==count)return(0);if(left[i]==c) /*找一个左部为c的产生式*/j=strlen(right[i]); /*j为右部的长度*/if(j==1&&in(right[i][0],empty)==1)return(1);else if(j==1&&in(right[i][0],termin)==1)return(0);elsefor(k=0;k<=j-1;k++)if(in(right[i][k],empt)==1)mark=1;if(mark==1)continue;elsefor(k=0;k<=j-1;k++)result*=_emp(right[i][k]);temp[0]=right[i][k];temp[1]='\0';merge(empt,temp,1);if(result==0&&i<count)continue;else if(result==1&&i<count)return(1);判断读入的文法是否正确int judge()int i,j;for(i=0;i<=count-1;i++)if(in(left[i],non_ter)==0){ /*若左部不在非终结符中,报错*/printf("\nerror1!");validity=0;return(0);for(j=0;j<=strlen(right[i])-1;j++)if(in(right[i][j],non_ter)==0&&in(right[i][j],termin)==0&&right[i][j]!='^'){ /*若右部某一符号不在非终结符、终结符中且不为' ^ ',报错*/ printf("\nerror2!");validity=0;return(0);return(1);求单个符号的FIRSTvoid first2(int i){ /*i为符号在所有输入符号中的序号*/char c,temp[20];int j,k,m;c=v[i];char ch='^';emp(ch);if(in(c,termin)==1) /*若为终结符*/first1[i][0]=c;first1[i][1]='\0';else if(in(c,non_ter)==1) /*若为非终结符*/for(j=0;j<=count-1;j++)if(left[j]==c)if(in(right[j][0],termin)==1||right[j][0]=='^')temp[0]=right[j][0];temp[1]='\0';merge(first1[i],temp,1);else if(in(right[j][0],non_ter)==1)if(right[j][0]==c)continue;for(k=0;;k++)if(v[k]==right[j][0])break;if(f[k]=='0')first2(k);f[k]='1';merge(first1[i],first1[k],2);for(k=0;k<=strlen(right[j])-1;k++)empt[0]='\0';if(_emp(right[j][k])==1&&k<strlen(right[j])-1)for(m=0;;m++)if(v[m]==right[j][k+1])break;if(f[m]=='0')first2(m);f[m]='1';merge(first1[i],first1[m],2);else if(_emp(right[j][k])==1&&k==strlen(right[j])-1)temp[0]='^';temp[1]='\0';merge(first1[i],temp,1);elsebreak;f[i]='1';求各产生式右部的FIRSTvoid FIRST(int i,char *p)int length;int j,k,m;char temp[20];length=strlen(p);if(length==1) /*如果右部为单个符号*/if(p[0]=='^')if(i>=0)first[i][0]='^';first[i][1]='\0';elseTEMP[0]='^';TEMP[1]='\0';elsefor(j=0;;j++)if(v[j]==p[0])break;if(i>=0)memcpy(first[i],first1[j],strlen(first1[j]));first[i][strlen(first1[j])]='\0';elsememcpy(TEMP,first1[j],strlen(first1[j]));TEMP[strlen(first1[j])]='\0';else /*如果右部为符号串*/ for(j=0;;j++)if(v[j]==p[0])break;if(i>=0)merge(first[i],first1[j],2);elsemerge(TEMP,first1[j],2);for(k=0;k<=length-1;k++)empt[0]='\0';if(_emp(p[k])==1&&k<length-1)for(m=0;;m++)if(v[m]==right[i][k+1])break;if(i>=0)merge(first[i],first1[m],2);elsemerge(TEMP,first1[m],2);else if(_emp(p[k])==1&&k==length-1)temp[0]='^';temp[1]='\0';if(i>=0)merge(first[i],temp,1);elsemerge(TEMP,temp,1);else if(_emp(p[k])==0)break;求各产生式左部的FOLLOWvoid FOLLOW(int i)int j,k,m,n,result=1;char c,temp[20];c=non_ter[i]; /*c为待求的非终结符*/ temp[0]=c;temp[1]='\0';merge(fo,temp,1);if(c==start){ /*若为开始符号*/temp[0]='#';temp[1]='\0';merge(follow[i],temp,1);for(j=0;j<=count-1;j++)if(in(c,right[j])==1) /*找一个右部含有c的产生式*/for(k=0;;k++)if(right[j][k]==c)break; /*k为c在该产生式右部的序号*/for(m=0;;m++)if(v[m]==left[j])break; /*m为产生式左部非终结符在所有符号中的序号*/ if(k==strlen(right[j])-1){ /*如果c在产生式右部的最后*/if(in(v[m],fo)==1)merge(follow[i],follow[m],1);continue;if(F[m]=='0')FOLLOW(m);F[m]='1';merge(follow[i],follow[m],1);else{ /*如果c不在产生式右部的最后*/for(n=k+1;n<=strlen(right[j])-1;n++)empt[0]='\0';result*=_emp(right[j][n]);if(result==1){ /*如果右部c后面的符号串能推出^*/if(in(v[m],fo)==1){ /*避免循环递归*/merge(follow[i],follow[m],1);continue;if(F[m]=='0')FOLLOW(m);F[m]='1';merge(follow[i],follow[m],1);for(n=k+1;n<=strlen(right[j])-1;n++)temp[n-k-1]=right[j][n];temp[strlen(right[j])-k-1]='\0';FIRST(-1,temp);merge(follow[i],TEMP,2);F[i]='1';判断读入文法是否为一个LL(1)文法int ll1()int i,j,length,result=1;char temp[50];for(j=0;j<=49;j++){ /*初始化*/first[j][0]='\0';follow[j][0]='\0';first1[j][0]='\0';select[j][0]='\0';TEMP[j]='\0';temp[j]='\0';f[j]='0';F[j]='0';for(j=0;j<=strlen(v)-1;j++)first2(j); /*求单个符号的FIRST集合*/ printf("\nfirst1:");for(j=0;j<=strlen(v)-1;j++)printf("%c:%s ",v[j],first1[j]);printf("\nempty:%s",empty);printf("\n:::\n_emp:");for(j=0;j<=strlen(v)-1;j++)printf("%d ",_emp(v[j]));for(i=0;i<=count-1;i++)FIRST(i,right[i]); /*求FIRST*/printf("\n");for(j=0;j<=strlen(non_ter)-1;j++){ /*求FOLLOW*/if(fo[j]==0)fo[0]='\0';FOLLOW(j);printf("\nfirst:");for(i=0;i<=count-1;i++)printf("%s ",first[i]);printf("\nfollow:");for(i=0;i<=strlen(non_ter)-1;i++)printf("%s ",follow[i]);for(i=0;i<=count-1;i++){ /*求每一产生式的SELECT集合*/ memcpy(select[i],first[i],strlen(first[i]));select[i][strlen(first[i])]='\0';for(j=0;j<=strlen(right[i])-1;j++)result*=_emp(right[i][j]);if(strlen(right[i])==1&&right[i][0]=='^')result=1;if(result==1)for(j=0;;j++)if(v[j]==left[i])break;merge(select[i],follow[j],1);printf("\nselect:");for(i=0;i<=count-1;i++)printf("%s ",select[i]);memcpy(temp,select[0],strlen(select[0]));temp[strlen(select[0])]='\0';for(i=1;i<=count-1;i++){ /*判断输入文法是否为LL(1)文法*/length=strlen(temp);if(left[i]==left[i-1])merge(temp,select[i],1);if(strlen(temp)<length+strlen(select[i]))return(0);elsetemp[0]='\0';memcpy(temp,select[i],strlen(select[i]));temp[strlen(select[i])]='\0';return(1);构造分析表Mvoid MM()int i,j,k,m;for(i=0;i<=19;i++)for(j=0;j<=19;j++)M[i][j]=-1;i=strlen(termin);termin[i]='#'; /*将#加入终结符数组*/termin[i+1]='\0';for(i=0;i<=count-1;i++)for(m=0;;m++)if(non_ter[m]==left[i])break; /*m为产生式左部非终结符的序号*/ for(j=0;j<=strlen(select[i])-1;j++)if(in(select[i][j],termin)==1)for(k=0;;k++)if(termin[k]==select[i][j])break; /*k为产生式右部终结符的序号*/ M[m][k]=i;总控算法void syntax()int i,j,k,m,n,p,q;char ch;char S[50],str[50];printf("请输入该文法的句型:");scanf("%s",str);getchar();i=strlen(str);str[i]='#';str[i+1]='\0';S[0]='#';S[1]=start;S[2]='\0';j=0;ch=str[j];while(1)if(in(S[strlen(S)-1],termin)==1)if(S[strlen(S)-1]!=ch)printf("\n该符号串不是文法的句型!");return;else if(S[strlen(S)-1]=='#')printf("\n该符号串是文法的句型.");return;elseS[strlen(S)-1]='\0';j++;ch=str[j];elsefor(i=0;;i++)if(non_ter[i]==S[strlen(S)-1])break;for(k=0;;k++)if(termin[k]==ch)break;if(k==strlen(termin))printf("\n词法错误!");return;if(M[i][k]==-1)printf("\n语法错误!");return;elsem=M[i][k];if(right[m][0]=='^')S[strlen(S)-1]='\0';elsep=strlen(S)-1;q=p;for(n=strlen(right[m])-1;n>=0;n--)S[p++]=right[m][n];S[q+strlen(right[m])]='\0';printf("\nS:%s str:",S);for(p=j;p<=strlen(str)-1;p++)printf("%c",str[p]);printf(" ");一个用户调用函数void menu()syntax();printf("\n是否继续?(y or n):");scanf("%c",&choose);getchar();while(choose=='y')menu();主函数void main()int i,j;start=grammer(termin,non_ter,left,right); /*读入一个文法*/ printf("count=%d",count);printf("\nstart:%c",start);strcpy(v,non_ter);strcat(v,termin);printf("\nv:%s",v);printf("\nnon_ter:%s",non_ter);printf("\ntermin:%s",termin);printf("\nright:");for(i=0;i<=count-1;i++)printf("%s ",right[i]);printf("\nleft:");for(i=0;i<=count-1;i++)printf("%c ",left[i]);if(validity==1)validity=judge();printf("\nvalidity=%d",validity);if(validity==1)printf("\n文法有效");ll=ll1();printf("\nll=%d",ll);if(ll==0)printf("\n该文法不是一个LL1文法!");elseMM();printf("\n");for(i=0;i<=19;i++)for(j=0;j<=19;j++)if(M[i][j]>=0)printf("M[%d][%d]=%d ",i,j,M[i][j]);printf("\n");menu();测试二(1)测试输入一个文法(2)测试输入一个符号串(3)测试再次输入一个符号串,然后退出程序5.缺少功能要求(4)可将测试用的表达式事先放在文本文件中,一行存放一个表达式,以分号分割。

LL(1)文法预测分析法实验报告

LL(1)文法预测分析法实验报告

一、实验原理LL(1)分析法,就是指从左到右扫描输入串(源程序),同时采用最左推导,且对每次直接推导只需向前看一个输入符号,便可确定当前所应当选择的规则。

实现LL(1)分析的程序又称为LL(1)分析程序或LL(1)分析器。

一个文法要能进行LL(1)分析,那么这个文法应该满足:无二义性,无左递归,无左公因子。

当文法满足条件后,再分别构造文法每个非终结符的FIRST和FOLLOW集合,然后根据FIRST和FOLLOW集合构造LL(1)分析表,最后利用分析表,根据LL(1)语法分析构造一个分析器。

LL(1)的语法分析程序包含了三个部分:控制程序,预测分析表函数,先进先出的语法分析栈。

LL(1)预测分析程序的总控程序在判断STACK栈顶符号X和当前的输入符号a做哪种过程的。

对于任何(X,a),总控程序每次都执行下述三种可能的动作之一:(1)若X = a =‘#’,则宣布分析成功,停止分析过程。

(2)若X = a !=‘#’,则把X从STACK栈顶弹出,让a指向下一个输入符号。

(3)若X是一个非终结符,则查看预测分析表M。

若M[A,a]中存放着关于X的一个产生式,那么,首先把X弹出STACK栈顶,然后,把产生式的右部符号串按反序一一弹出STACK栈(若右部符号为ε,则不推什么东西进STACK栈)。

若M[A,a]中存放着“出错标志”,则调用出错诊断程序ERROR。

1 LL(1)分析法LL(1)分析法又称预测分析法,是一种不带回溯的非递归自顶向下分析法。

LL(1)的含义是:第一个L表明自顶向下分析是从左至右扫描输入串的;第二个L 表明分析过程中将用最左推导;“1”表明只需向右查看一个符号就可以决定如何推导(即可知用哪一个产生式进行推导)。

LL(1)分析器结构如图1:图 1 LL(1)分析器使用 L L(1)分析法将会涉及到 L L(1)分析表,而分析表又会涉及到 FIRST 集 和 F OLLOW 集。

FIRST 集构造对文法中的每一个非终结符 X 构造 F IRST(X),其方法是连续使用以下规则, 直到每个集合的 F IRST 不再增大为止。

(完整word版)SLR(1)文法分析实验报告

(完整word版)SLR(1)文法分析实验报告

《编译原理》课程设计报告—SLR(1)分析的实现学院计算机科学与技术专业计算机科学与技术学号学生姓名指导教师姓名2015年12月26日目录1.设计的目的与内容 (1)1。

1课程设计的目的 (1)1。

2设计内容 (1)1。

3设计要求 (1)1。

4理论基础 (1)2算法的基本思想 (2)2.1主要功能函数 (2)2.2算法思想 (3)SLR文法构造分析表的主要思想: (3)解决冲突的方法: (3)SLR语法分析表的构造方法: (4)3主要功能模块流程图 (5)3。

1主函数功能流程图 (5)4系统测试 (6)5 结论 (11)附录程序源码清单 (12)1.设计的目的与内容1.1课程设计的目的编译原理课程设计是计算机专业重要的教学环节,它为学生提供了一个既动手又动脑,将课本上的理论知识和实际有机的结合起来,独立分析和解决实际问题的机会.●进一步巩固和复习编译原理的基础知识.●培养学生结构化程序、模块化程序设计的方法和能力。

●提高学生对于编程语言原理的理解能力。

●加深学生对于编程语言实现手段的印象。

1.2设计内容构造LR(1)分析程序,利用它进行语法分析,判断给出的符号串是否为该文法识别的句子,了解LR(K)分析方法是严格的从左向右扫描,和自底向上的语法分析方法。

1。

3设计要求1)SLR(1)分析表的生成可以选择编程序生成,也可选择手动生成;2)程序要求要配合适当的错误处理机制;3)要打印句子的文法分析过程。

1。

4理论基础由于大多数适用的程序设计语言的文法不能满足LR(0)文法的条件,即使是描述一个实数变量说明这样简单的文法也不一定是LR(0)文法.因此对于LR(0)规范族中有冲突的项目集(状态)用向前查看一个符号的办法进行处理,以解决冲突。

这种办法将能满足一些文法的需要,因为只对有冲突的状态才向前查看一个符号,以确定做那种动作,因而称这种分析方法为简单的LR(1)分析法,用SLR(1)表示。

12算法的基本思想2。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
要求:
第一部分:分词
输入:输入是一个文本文件,里面的内容是符合某个语言语法、词法要求的源代码(输入文件为C++或者Java源程序,词语、语法定义参考C++、Java即可;C++、Java大家只需要选择一种自己熟悉的语言就可以),例如“position= initial + rate * 60;”;
输出:设计并实现对输入文件的处理(禁用正则表达式),以获得如下输出,输出是一个文本文件,对前面例子,里面内容是:
深圳大学实验报告
课程名称:编译原理
实验项目名称:文法分析方法及其应用
学院:计算机与软件学院
专业:软件工程
指导教师:陈飞
报告人:学号:班级:
实验时间:2015年10月12日至2015年11月9日
实验报告提交时间:
教务处制
实验目的与要求:
目的:针对分词、停用词过滤等文法分析应用问题,设计并实现相应的解决方案,再通过设计文法相关类族,以及实现文法化简等方法,既加深对抽象的文法、推导、语言等形式语言理论基础概念的理解与掌握,也加强对面向对象程序编写能力和计算思维的培养。
2.1如何识别保留字?
2.2如何识别标识符?
2.3如何识别数字?
特别的,如果你有多种方法来识别这3类单词,那这些方法有何优缺点?分析并作出你的选择。
请在这里,补充完善你的设计思路,完成后,请删去这句话。
3.如何产生符合要求的随机停用词和待处理文本
第二部分实验要求先产生随机的停用词和待处理文本,主要是如何产生符合要求的这些词或文本?
第三部分:文法化简
设计文法类,实现对文法G[S]=(Vt, Vn, P, S)的文件读写,文法的文件表示形式以及内存表示形式可自定义。本质上,文法就是3个集合+1个符号,重点(难点)是产生式集合如何处理。文法的文本形式可根据自己需要自由定义。在前述的基础上,实现文法化简的无用符号及无用产生式消除算法(即课本算法2.1、2.2)。
(标识符,position)
(赋值运算符,=)
(标识符,initial)
(加法运算符,+)
(标识符,rate)
(乘法运算符,*)
(整数,60)
(分隔符,; )
第二部分:停用词过滤,分为“产生随机停用词”、“产生随机待过滤文本”和“过滤停用词”3个小实验。
产生随机停用词:生成一个文件长度和单词平均长度可控的文本文件,要求字符集为26个字母,每行生产一个单词,每个单词的长度随机,全部单词的平均长度可控制,通常为4、5(非严格要求),总共输出的文件长度可控制。
实验结论:
1.测试用例的设计与说明
对每部分的实验,你分别设计了什么测试数据(测试用例)进行测试,你设计测试数据的出发点是什么,有什么目的?
2.测试结果的说明与分析
对测试(实验)结果进行分析说明
心得体会:
除了实验的心得体会外,
还要额外增加说明你对文法、直接推导、推导、句型、句子、语言这些概念的理解。
指导教师批阅意见:
3.1如何产生随机停用词?
3.2如何控制随机停用词的平均长度(而不是固定长度)?
3.3如何产生待处理文本中的“段落”?
3.4如何控制待处理文本的长度?
请在这里,补充完善你的设计思路,完成后,请删去这句话。理文本中出现的停用词替换为“**”,那你如何准确、快速判断出文本中的停用词?
产生随机待过滤文本:生成一个文件大小和单词平均长度可控的文本文件,要求
字符集为26个字母+“”(空格)+“\r\n”(回车换行);从文件开始一直到结束,持续输出,不额外换行(除非遇到生成的\r\n),总共输出的文件大小可控制。
过滤停用词:写一个程序,快速扫描待过滤文本,然后将待过滤文本中出现的所有停用词,替换为“**”,要求禁用正则表达式,不要误杀(例如,若停用词包括“abc”,那么“abcd”等不应该被误杀。
方法、步骤:
要完成本实验,依据实验要求进行分解,需要完成的实验步骤是:
1.如何读写文件?
读写文法文件内容,需要用到文件IO,查阅、复习文件IO操作。
请在这里,补充完善你的设计思路,完成后,请删去这句话。
2.如何分词?
第一部分实验要求进行分词,源代码中的单词可以分成3类,一类是约定的保留字,一类是普通标识符,最后一类是数字
成绩评定:
指导教师签字:陈飞
2015年11月17日
备注:
5.如何设计文法类?
文法类里面,有3个集合,1个特别的非终结符——开始符号。集合应如何表示?Set<Type>是常见的范型,可使用例如Set<Production>来表示产生式的集合。也可直接采用数组等形式来表示,那种方法更好?分析并做出你的设计。
请在这里,补充完善你的设计思路,完成后,请删去这句话。
6.如何实现无用文法的化简算法?
算法2.1、2.2课本已经给出了说明,那你如何将算法说明变成代码?有什么主要内容?
请在这里,补充完善你的设计思路,完成后,请删去这句话。
实验过程及内容:
实验过程及内容,处理代码设计说明、代码及其注释外,特别关注编程过程。
要求,至少有一张照片,照片上出现你(正面)+正在写的代码(电脑要有外观)
相关文档
最新文档