精华内容
下载资源
问答
  • 算符优先文法

    2021-07-25 07:16:25
    算符优先分析 算符优先文法及优先表构造 FIRSTVT LASTVT

    算符优先分析

    算符优先文法及优先表构造

    FIRSTVT

    LASTVT

    展开全文
  • 算符优先文法是一种自下而上的分析方法,其文法的特点是文法的产生式中不含两个相邻的非终结符。 生成FIRSTVT LASTVT集合 算符优先关系表 可以对输入的语言进行分析 样例 1: S->#E# E->E+T E->T T->T*F T->...
  • 编译原理算符优先文法实验源码
  • 算符优先文法实验

    2015-06-30 12:10:21
    编译原理的算符优先文法,以及实验报告,截图等
  • 编译原理 算符优先文法 实验报告 代码 运行成功
  • 是一个算符优先文法的C语言实现,在这里和大家分享,需要的可以下载。
  • 算符优先文法 需求描述 对于任意给定的文法,判断其是否是算符优先文法,如果是则构造出算符优先关系表。 算法描述 主要是先判断输入的数据是否是一个文法,然后通过判断是否存在连续两个相邻的非终结符来判断它是否...

    算符优先文法

    需求描述

    对于任意给定的文法,判断其是否是算符优先文法,如果是则构造出算符优先关系表。

    算法描述

    主要是先判断输入的数据是否是一个文法,然后通过判断是否存在连续两个相邻的非终结符来判断它是否是算符优先文法,若不是,则直接提示并退出程序;否则,依次求得所有非终结符的FIRSTVT集与LASTVT集,然后根据规则构造优先关系表,当任意两终结符之间不存在多种优先关系时,说明它是算符优先文法,否则不是。

    FIRSTVT集与LASTVT集的构造

    Firstvt

    找Firstvt的三条规则:如果要找A的Firstvt,A的候选式中出现:

    A->a…,即以终结符开头,该终结符入Firstvt
    A->B…,即以非终结符开头,该非终结符的Firstvt入A的Firstvt
    A->Ba…,即先以非终结符开头,紧跟终结符,则终结符入Firstvt

    Lastvt

    找Lastvt的三条规则:如果要找A的Lastvt,A的候选式中出现:

    A->…a,即以终结符结尾,该终结符入Lastvt
    A->…B,即以非终结符结尾,该非终结符的Lastvt入A的Lastvt
    A->…aB,即先以非终结符结尾,前面是终结符,则终结符入Firstvt

    #include<cstdio>
    #include<cstring>
    #include<stdlib.h>
    
    const int maxn = 1000;
    const int maxm = 100; 
    char Vt[maxn];//终结符数组
    char Vn[maxn];//非终结数组
    char table[maxn][maxn];
    int t;//终结符个数;
    int n; //非终结个数 
    typedef struct Last{
    	char Vn;//非终结符 
    	char LASTVT[20];
    	int index;
    }Last;
    Last last[maxm];
    typedef struct First{
    	char Vn;//非终结符 
    	char FIRSTVT[20];
    	int inde;
    }First;
    First first[maxm];
    typedef struct NODE{
    	char left;
    	char right;
    }NODE;
    
    //输入的表达式文法保存的数据结构 
    typedef struct Input{
    	char Vn;
    	char str[maxm];
    	int len;
    }Input;
    Input input[maxn], inpu[maxn];
    int in; //表达式文法的个数 
    
    char arr[100];//保存要分析的字符串 
    int len = 0;
    typedef struct ANS{
    	int step; //步骤
    	char stack[maxn];//分析栈
    	int top;//指向栈顶元素 
    	int index;//指向当前符号 
    	int j;
    	char flage[20];
    	char op;//当前符号 
    }ANS;
    ANS ans;
    
    
    //判断字符是否为终结符
    //终结符返回ture 
    bool isVt(char ch){
    	for(int i=0; i<t; i++){
    		if(Vt[i]==ch){
    			return true;
    		}
    	}
    	return false;
    }
    //判断字符是否为非终结符
    //非终结符返回ture
    bool isVn(char ch){
    	for(int i=0; i<n; i++){
    		if(Vn[i]==ch){
    			return true;
    		}
    	}
    	return false;
    }
    
    //获取终结符在终结符数组中的位置 
    int indexVt(char ch){
    	for(int i=0; i<t; i++){
    
    		if(Vt[i]==ch){
    			return i;
    		}
    	} 
    	return -1;
    }
    
    //获取非终结符在非终结符数组中的位置 
    int indexVn(char ch){
    	for(int i=0; i<n; i++){
    		if(Vn[i]==ch){
    			return i;
    		}
    	} 
    	return -1;
    }
    
    void getFIRSTVT(){
    	
    	bool F[maxm][maxm]; //布尔数组,用于计算FIRSTVT 
    	NODE stack[maxm];
    	NODE node;
    	int top = -1; //指向栈顶元素 
    	
    	//初始化F数组
    	for(int i=0; i<=n; i++)
    		for(int j=0; j<=t; j++)
    			F[i][j] = false;
    	
    	//若有产生式A->a...或A->Ba..., 则a属于FIRSTVT(A);
    	for(int i=0; i<in; i++){
    		if(isVt(input[i].str[0])){//A->a...
    			int nn = indexVn(input[i].Vn);
    			int tt = indexVt(input[i].str[0]);
    			F[nn][tt] = true;
    			//入栈 
    			stack[++top].left = input[i].Vn;
    			stack[top].right = input[i].str[0];
    		} else if (isVt(input[i].str[1])&&isVn(input[i].str[0])){//A->Ba...
    			int nn = indexVn(input[i].Vn);
    			int tt = indexVt(input[i].str[1]);
    			F[nn][tt] = true;
    			stack[++top].left = input[i].Vn;
    			stack[top].right =  input[i].str[1];
    		}
    	} 
    	while(top!=-1){
    		
    		node = stack[top--];//栈顶元素标记出栈 
    		for(int i=0; i<in; i++){
    			if(isVn(input[i].str[0])&&input[i].str[0]==node.left&&input[i].Vn!=input[i].str[0]){ //寻找A->B类型  B->a
    				//将A->a压栈 
    				int indexn = indexVn(input[i].Vn);
    				int indext = indexVt(node.right);
    				stack[++top].left = Vn[indexn];
    				stack[top].right = node.right;
    				F[indexn][indext] = true;
    				break;
    			}
    		}	
    	}
    	//按照得到的F数组,求出FISTVT
    	for(int i=0; i<n; i++){
    		first[i].inde = 0;
    		first[i].Vn = Vn[i];
    		for(int j=0; j<t; j++){
    			if(F[i][j]){
    				first[i].FIRSTVT[first[i].inde++] = Vt[j]; 
    			}
    		}
    	}
    	for(int i=0; i<n; i++){
    		printf("FIRSTVT( %c ) = { ", first[i].Vn);
    		for(int j=0; j<first[i].inde; j++){
    			printf("%c ", first[i].FIRSTVT[j]);
    		}
    		printf("}\n");
    	}
    }
    void getLASTVT(){
    	
    	bool F[maxm][maxm]; //布尔数组,用于计算LASTVT 
    	NODE stack[maxm];
    	NODE node;
    	int top = -1; //指向栈顶元素 
    	//初始化F数组
    	for(int i=0; i<=n; i++)
    		for(int j=0; j<=t; j++)
    			F[i][j] = false;	
    	//若有产生式A->...a或A->...aB, 则a属于FIRSTVT(A);
    	for(int i=0; i<in; i++){
    		int len = input[i].len-1;
    		if(isVt(input[i].str[len])){//A->...a
    			int nn = indexVn(input[i].Vn);
    			int tt = indexVt(input[i].str[len]);
    			//F数组进行标记 
    			F[nn][tt] = true;
    			//入栈	
    			stack[++top].left = input[i].Vn;
    			stack[top].right = input[i].str[len];	
    		} else if (isVt(input[i].str[len-1])&&isVn(input[i].str[len])){//A->...aB
    			int nn = indexVn(input[i].Vn);
    			int tt = indexVt(input[i].str[len-1]);
    			F[nn][tt] = true;
    			stack[++top].left = input[i].Vn;
    			stack[top].right =  input[i].str[len-1];
    		}
    	}
    	while(top!=-1){
    		node = stack[top--];//栈顶元素标记出栈 
    		for(int i=0; i<in; i++){
    			int len = input[i].len-1;
    			if(isVn(input[i].str[len])&&input[i].str[len]==node.left&&input[i].Vn!=input[i].str[len]){ //寻找A->...B类型  B->a
    				//将A->a压栈
    				int indexn = indexVn(input[i].Vn);
    				int indext = indexVt(node.right);
    				stack[++top].left = Vn[indexn];
    				stack[top].right = node.right;
    				F[indexn][indext] = true;
    				break;
    			}
    		}
    			
    	}
    	//按照得到的F数组,求出Last
    	for(int i=0; i<n; i++){
    		last[i].index = 0;
    		last[i].Vn = Vn[i];
    		for(int j=0; j<t; j++){
    			if(F[i][j]){
    				last[i].LASTVT[last[i].index++] = Vt[j]; 
    			}
    		}
    	}
    	//打印LASTVT集合 
    	for(int i=0; i<n; i++){
    		printf("LASTVT( %c ) = { ", first[i].Vn);
    		for(int j=0; j<last[i].index; j++){
    			printf("%c ", last[i].LASTVT[j]);
    		}
    		printf("}\n");
    	}
    	
    }
    
    void getTable(){
    	
    	for(int i=0; i<in; i++){//遍历每个产生式
    		int len = input[i].len;
    		for(int j=0; j<len; j++){
    			if((j+1)<len&&isVt(input[i].str[j])&&isVt(input[i].str[j+1])){
    				int indext1 = indexVt(input[i].str[j]);
    				int indext2 = indexVt(input[i].str[j+1]);
    				table[indext1][indext2] = '=';
    			}
    			if((j+2)<len&&isVt(input[i].str[j])&&isVt(input[i].str[j+2])){
    				int indext1 = indexVt(input[i].str[j]);
    				int indext2 = indexVt(input[i].str[j+2]);
    				table[indext1][indext2] = '=';
    			}
    			if((j+1)<len&&isVt(input[i].str[j])&&isVn(input[i].str[j+1])){
    				int index1 = indexVt(input[i].str[j]);
    				for(int k=0; k<n; k++){
    					if(first[k].Vn==input[i].str[j+1]){
    						for(int h=0; h<first[k].inde; h++){
    							int index2 = indexVt(first[k].FIRSTVT[h]);
    							table[index1][index2] = '<';
    						}
    					}
    				}
    			}
    			if((j+1)<len&&isVn(input[i].str[j])&&isVt(input[i].str[j+1])){
    				int index1 = indexVt(input[i].str[j+1]);
    				for(int k=0; k<n; k++){
    					if(last[k].Vn==input[i].str[j]){
    						for(int h=0; h<last[k].index; h++){
    							int index2 = indexVt(last[k].LASTVT[h]);
    							table[index2][index1] = '>';
    						}
    					}
    				}
    			}
    		}
    	}
    	printf("  ");
    	for(int i=0; i<t; i++){
    		printf("%c ", Vt[i]);
    	}printf("\n");
    	for(int i=0; i<t; i++){
    		printf("%c ", Vt[i]);
    		for(int j=0; j<t; j++){
    			printf("%c ", table[i][j]);
    		}printf("\n");
    	}
    }
    void init(){
    	char a[maxn];
    	printf("请输入表达的个数:");
    	int nn = 0;
    	scanf("%d", &nn);
    	printf("请输入文法表达式:\n");
    	for(int i=0; i<nn; i++){
    		getchar();
    		char c;//A->jhdakjh
    		scanf("%c%c%c%s", &input[i].Vn, &c, &c, input[i].str);
    		input[i].len = strlen(input[i].str);
    		if(!isVn(input[i].Vn)){//非终结符存入数组 
    			Vn[n++] = input[i].Vn;
    		} 
    	}
    	//终结符存入数组 
    	for(int i=0; i<nn; i++){
    		for(int j=0; j<strlen(input[i].str); j++){
    			if(!(isVn(input[i].str[j]))&&!isVt(input[i].str[j])&&input[i].str[j]!='|'){
    				Vt[t++] = input[i].str[j];
    			}
    		}
    	}
    	in = nn;
    	//将输入的文法拆分成标准格式
    	for(int i=0; i<nn; i++){
    		for(int j=0; j<input[i].len; j++){
    			if(input[i].str[j]=='|'){
    				
    				input[in].Vn = input[i].Vn;
    				input[in].len = 0;
    				
    				for(int k=0; j+k+1<input[i].len; k++){
    					
    					input[in].str[k] = input[i].str[j+k+1];
    					input[in].len++;
    					printf("%c_", input[in].str[k]);
    				}
    				input[i].str[j] = '\0';
    				input[i].len = j;
    				input[in].str[input[in].len] = '\0';
    				printf("%c->%s\n", input[in].Vn, input[in].str);
    				in++;
    				break;
    			}
    		}
    	}
    	for(int i=0; i<in; i++){
    		inpu[i].len = input[i].len;
    		inpu[i].Vn = input[i].Vn;
    		strcpy(inpu[i].str, input[i].str);
    		for(int j=0; j<inpu[i].len; j++){
    			if(isVn(inpu[i].str[j])){
    				inpu[i].str[j] = 'N';
    			}
    		}
    	}
    	printf("终结符个数:%d\n非终结符个数:%d\n", t, n);
    	for(int i=0; i<n; i++){
    		printf("%c ", Vn[i]);
    	}printf("\n");
    	for(int i=0; i<t; i++){
    		printf("%c ", Vt[i]);
    	} printf("\n");
    	
    	printf("输入的文法表达式为:\n");
    	for(int i=0; i<in; i++){
    		printf("%c->%s  %d\n", input[i].Vn, input[i].str, input[i].len); 
    	}
    	//初始化优先关系表
    	for(int i=0; i<maxn; i++){
    		for(int j=0; j<maxn; j++){
    			table[i][j] = ' ';
    		}
    	}
    }
    
    void Print(){
    	//步骤 
    	printf("\t%d\t\t", ans.step);
    	//分析栈 
    	for(int i=0; i<=ans.top; i++)
    		printf("%c", ans.stack[i]);
    	//优先关系 
    	printf("\t  \t%c\t\t", ans.op);
    	//当前符号 
    	printf("%c\t\t", arr[ans.index]);
    	//剩余输入串 
    	//printf("%d", ans.index+1);
    	for(int i=ans.index+1; i<=len; i++){
    		printf("%c", arr[i]);
    	} printf("\t\t");
    	//移进/规约 
    	printf("%s\n", ans.flage);
    	
    }
    void out(int j, int k, char *s) {
    	
    	int nn=0;
    	for(int i=j; i<=k; i++) {
    		printf("%c",s[i]);
    		nn++;
    	}
    	for(; nn<15; nn++) {
    		printf(" ");
    	}
    }
    void OPAnalysis(){
    	strcmp(ans.flage, "");
    	ans.index = 0;
    	ans.top = -1;//指向栈顶元素
    	ans.step = 0;
    	ans.stack[++ans.top] = '#';//初始换栈
    	ans.index = 0;//指向要分析字符串的当前符号
    	ans.step = 0;
    	//当前输入符读入a
    	char a = arr[ans.j];
    	while(a !='\0'){
    		ans.step++;
    		//判断栈顶元素是否为终结符 
    		//j指向栈顶的第一个非终结符 
    		if(isVt(ans.stack[ans.top])){
    			ans.j = ans.top;
    		} else {
    			ans.j = ans.top - 1;
    		}
    		//确定栈顶元素和 a 的下标 
    		int x = indexVt(ans.stack[ans.j]);
    		int y = indexVt(a);
    		ans.op = table[x][y];
    		if(table[x][y]=='>'){//规约 	
    			/*
    			栈顶当前符号ai为句柄尾,由此向左在栈中找到句柄的头符号ak即找到ak-1<ak为止 
    			*/
    			do{
    				//Q为栈顶的第一个终结符 
    				char Q = ans.stack[ans.j];
    				if(isVt(ans.stack[ans.j-1])){
    					ans.j = ans.j - 1;
    				}else {
    					ans.j = ans.j - 2;
    				}
    				x = indexVt(ans.stack[ans.j]);
    				y = indexVt(Q);
    			}while(table[x][y]!='<');
    	
    			/*
    			S[j+1]...S[K]规约为N
    			k = j + 1;
    			S[K] = N; 
    			*/
    			char str[maxn];
    			int leng = 0;
    			for(int h=ans.j+1; h<=ans.top; h++){
    				str[leng++] = ans.stack[h];
    			}str[leng] = '\0';	
    			for(int i=0; i<in; i++){
    				int flag = 0;
    				for(int j=0; j<inpu[i].len; j++){
    					if(inpu[i].str[j]=='N'){
    						continue;
    					}if(input[i].str[j]!=str[j]){
    						flag = 1;
    						break;
    					}
    				}
    				if(flag==0){
    					ans.top = ans.j + 1;
    					ans.stack[ans.top] = input[i].Vn;
    					strcpy(ans.flage,"规约"); 
    					break;
    				}
    			}
    			ans.top = ans.j + 1;
    			if(ans.top==1&&a=='#'){
    				ans.op = '=';
    				strcpy(ans.flage, "结束\n输入串符合文法的定义!\n");
    				Print(); 
    				return;
    			}
    		} else if(table[x][y]=='<'||table[x][y]=='='){//移进 
    			strcpy(ans.flage, "移进"); 
    			ans.stack[++ans.top] = a;
    			ans.index++;
    		} else {
    				printf("ERROE\n");
    				break;
    		}
    		Print();
    		a = arr[ans.index];
    	}
    }
    
    
    int main(){
    	init();
    	printf("FIRESTVT集合为:\n\n");
    	getFIRSTVT();
    	printf("\n\n\n\nLASTVT集合为:\n\n");
    	getLASTVT();
    	printf("\n\n\n\n算符优先关系表:\n\n");
    	getTable();
    	printf("请输入要分析的字符串:");
    	while(scanf("%s", arr)!=EOF){
    		len = strlen(arr);
    		arr[len++] = '#';
    		arr[len] = '\0';
    		printf("%s\n", arr);
    		printf("\t步骤\t\t分析栈\t\t优先关系\t当前符号\t剩余输入串\t\操作\n");
    		printf("--------------------------------------------------------------------------------------------------------\n");
    		OPAnalysis();
    	} 
    	return 0;
    } 
    
    //样例 1: 
    //S->#E#
    //E->E+T
    //E->T
    //T->T*F
    //T->F
    //F->(E)
    //F->i
    
    //样例2
    //S->#E#
    //E->E+T|T 
    //T->T*F|F 
    //F->(E)|i 
    

    运行结果
    运行结果

    展开全文
  • 算符优先文法处理判断算术表达式源代码、说明文档、输入输出详细说明及截图
  • 实验要求: 1.[实验项目] 实现LL(1)分析中控制程序(表驱动程序);完成以下描述赋值语句的LL(1)文法的LL(1...(1)构造该算符优先文法的优先关系矩阵或优先函数; (2)输入串应是词法分析的输出二元式序列,即某算...

    实验要求:

    1.[实验项目]

    实现LL(1)分析中控制程序(表驱动程序);完成以下描述赋值语句的LL(1)文法的LL(1)分析过程。

    G[E]:

    E →E+T∣E-T∣T

    T→T*F∣T/F∣F

    F→(E)∣i

    2.[设计说明]

    终结符号i 为用户定义的简单变量,即标识符的定义。

    3.[设计要求]

    (1)构造该算符优先文法的优先关系矩阵或优先函数;

    (2)输入串应是词法分析的输出二元式序列,即某算术表达式“专题
    1”的输出结果。输出为输入串是否为该文法定义的算术表达式的判断结果。

    (3)算符优先分析过程应能发现输入串出错。

    (4)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果;

    (5)考虑编写程序根据算符优先文法构造算符优先关系矩阵,并添加到你的算符优先分析程序中。

    实验过程:

    1、算符优先分析程序设计说明

    1.1设计要求:

    (1)构造该算符优先文法的优先关系矩阵或优先函数;

    (2)输入串应是词法分析的输出二元式序列,即某算术表达式“专题
    1”的输出结果。输出为输入串是否为该文法定义的算术表达式的判断结果。

    (3)算符优先分析过程应能发现输入串出错。

    (4)设计两个测试用例(尽可能完备,正确和出错),并给出测试结果;

    (5)考虑编写程序根据算符优先文法构造算符优先关系矩阵,并添加到你的算符优先分析程序中。

    1.2设计说明:

    (1)该语言大小写不敏感;

    (2)字母为a-zA-Z,数字为0-9;

    (3)对文法进行扩充和改造;

    (4)根据FIRSTVT集和LASTVE集的构造规则,构造出文法的FIRSTVT集和LASTVT集

    (5)根据FIRSTVT集和LASTVT集构造算符优先矩阵;

    (6)根据分析规则,构造算符优先矩阵分析器。

    3、程序功能描述

    (1)、能够录入一个.tys文件中的二元式内容;二元式内容为表达式

    (2)、根据.tys文件内容进行算符优先分析,可识别

    (3)、根据输入的二元式内容进行分析语法分析,并打印结果;

    (4)、打印分析过程(分析栈和保留串)和错误提示;

    (5)、根据文法构造FIRSTVT集和LASTVT集;

    (6)、根据构造FIRSTVT集和LASTVT集,构造出算符优先矩阵分析表;

    (7)、算符优先矩阵分析器。

    4、主要的数据结构描述

    4.1主要使用的java数据结构类型
    4.1.1 List

    //终结符号集

    private List<Character> Vt = new ArrayList<Character>();

    //非终结符号集

    private List<Character> Vn = new ArrayList<Character>();

    使用List保存文法的非终结符号和终结符号,一旦文法给定,非终结符号集合和终结符号集合也就确定,所以对Vt、Vn的操作一般是查找元素和遍历元素。

    List添加元素

    //设置非终结符号

    Vn.add(‘S’);

    Vn.add(‘E’);

    Vn.add(‘T’);

    Vn.add(‘F’);

    //设置终结符号

    Vt.add(’#’);

    Vt.add(’+’);

    Vt.add(’-’);

    Vt.add(’*’);

    Vt.add(’/’);

    Vt.add(’(’);

    Vt.add(’)’);

    Vt.add(‘i’);

    使用add()方法即可添加元素,上面的程序保存了Vt、Vn集合。

    list中是否包含某个元素

    方法:.contains(Object o); 返回true或者false

    例如下面在程序中使用到的:

    Vn.contains(nArryStr[i].charAt(0))&&Vt.contains(nArryStr[i].charAt(1))

    list获取长度:

    Vt.size()

    使用size()即可返回List的长度

    list中查看(判断)元素的索引

    注意:.indexOf(); 和 lastIndexOf()的不同;

    List<String> names=new ArrayList<>();

    names.add(“刘备”); //索引为0

    names.add(“关羽”); //索引为1

    names.add(“张飞”); //索引为2

    names.add(“刘备”); //索引为3

    names.add(“张飞”); //索引为4

    System.out.println(names.indexOf(“刘备”));

    System.out.println(names.lastIndexOf(“刘备”));

    System.out.println(names.indexOf(“张飞”));

    System.out.println(names.lastIndexOf(“张飞”));

    根据元素索引位置进行的判断
    if (names.indexOf("刘备")==0) {
        System.out.println("刘备在这里");
    }else if (names.lastIndexOf("刘备")==3) {
        System.out.println("刘备在那里");
    }else {
        System.out.println("刘备到底在哪里?");
    }
    
    

    在程序中使用OPGtable[Vt.indexOf(Vt1)][Vt.indexOf(Vt2)]

    判断list是否为空

    //空则返回true,非空则返回false

    
    if (person.isEmpty()) {
        System.out.println("空的");
    }else {
        System.out.println("不是空的");
    }
    
    
    4.1.2 Map
    HashMap

    最常用的Map,它根据键的HashCode
    值存储数据,根据键可以直接获取它的值,具有很快的访问速度。HashMap最多只允许一条记录的键为Null(多条会覆盖);允许多条记录的值为
    Null。非同步的。

    常用API
    clear()从 Map 中删除所有映射
    remove(Object key)从 Map 中删除键和关联的值
    put(Object key, Object value)将指定值与指定键相关联
    putAll(Map t)将指定 Map 中的所有映射复制到此 map
    entrySet()返回 Map 中所包含映射的 Set 视图。Set 中的每个元素都是一个 Map.Entry 对象,可以使用 getKey() 和 getValue() 方法(还有一个 setValue() 方法)访问后者的键元素和值元素
    keySet()返回 Map 中所包含键的 Set 视图。删除 Set 中的元素还将删除 Map 中相应的映射(键和值)
    values()返回 map 中所包含值的 Collection 视图。删除 Collection 中的元素还将删除 Map 中相应的映射(键和值)
    get(Object key)返回与指定键关联的值
    containsKey(Object key)如果 Map 包含指定键的映射,则返回 true
    containsValue(Object value)如果此 Map 将一个或多个键映射到指定值,则返回 true
    isEmpty()如果 Map 不包含键-值映射,则返回 true
    size()返回 Map 中的键-值映射的数目

    在程序中使用了MAP:

    //文法

    private Map<String, String> grammar = new HashMap<String, String>();

    //FIRSTVT集

    private Map<Character,Set<Character>> FIRSTVT = new
    HashMap<Character,Set<Character>>();

    //LASTVT集

    private Map<Character,Set<Character>> LASTVT = new
    HashMap<Character,Set<Character>>();

    使用map保存文法,和FIRSTVT,LASTVT。

    Map添加元素

    grammar.put(“S”, “#E#”);

    grammar.put(“E”, “E+T|E-T|T”);

    grammar.put(“T”, “T*F|T/F|F”);

    grammar.put(“F”, “(E)|i”);

    上面程序将题目要求的文法保存到map对象grammar中

    Map的遍历
    
    		grammar.forEach((k,v)->{
    			String []nArryStr = v.split("\\|");
    			for(int i=0 ;i<nArryStr.length;i++)
    				
    			{
    				//System.out.println(nArryStr[i]);
    				if(Vt.contains(nArryStr[i].charAt(0)))
    				{
    					char b= nArryStr[i].charAt(0);
    					FIRSTVT.get(k.charAt(0)).add(b);
    				}
    				if(nArryStr[i].length()>=2)
    				if(Vn.contains(nArryStr[i].charAt(0))&&Vt.contains(nArryStr[i].charAt(1)))
    				{
    					char b=nArryStr[i].charAt(1);
    					FIRSTVT.get(k.charAt(0)).add(b);
    				}
    			}
    			
    			
    		});
    
    

    使用forEach方法,参数(k,v)

    其中k为每个values的索引值,通过forEach的方法,遍历map的所有元素,就返回每个元素的key和values,并赋给参数(k,v)。

    Map获取元素

    Map获取元素一般根据key值获取对应的values:

    例如:

    LASTVT.get(k.charAt(0))

    结果返回的是,key对应的values,而且values是声明map时设置的类型对应,

    比如:

    private Map<Character,Set<Character>> LASTVT = new
    HashMap<Character,Set<Character>>();

    key的类型为Character

    values的类型为Set<Character>

    所以通过LASTVT.get(key)获得values时,得到类型为Set<Character>。

    4.2 二元式文件结构

    二元式文件通过专题1的词法分析程序得到:

    其中一个测试用例为:

    (1,a)
    (4,+)
    (1,b)
    (10,*)
    (3,()
    (1,c)
    (5,-)
    (2,34)
    (3,))
    (11,/)
    (1,num5)

    二元式文件内容被录入到

    br = new BufferedReader(new InputStreamReader(new FileInputStream(fp.getName())));
    			String erYuanShi = "";
    			while((erYuanShi=br.readLine())!=null) {
    				//截取符号串
    				String substr=erYuanShi.substring(erYuanShi.indexOf("(") + 1, erYuanShi.lastIndexOf(","));
    				if(substr.equals("1")||substr.equals("2"))
    				{		
    					s+="i";
    				}
    				else 
    				{
    					s+=erYuanShi.substring(erYuanShi.indexOf(",") + 1, erYuanShi.lastIndexOf(")"));
    				}
    
    			}
    
    

    二元式文件的录入和专题2一样,InputStream是一个Java
    List列表的一个对象,list列表是一系列的String类型的字符串,具体的操作:

    br = new BufferedReader(new InputStreamReader(new FileInputStream(fp.getName())));
    			String erYuanShi = "";
    			while((erYuanShi=br.readLine())!=null) {
    				//截取符号串
    				InputStream.add(erYuanShi.substring(erYuanShi.indexOf(",") + 1, erYuanShi.lastIndexOf(")")));
    			}
    			InputStream.add("#");  //末尾添加#号
    
    

    br为一个文件的读入流,通过使用br.readLine()方法读入二元式文件当前行内容并返回给String类型的变量erYuanShi,然后每一行的内容类似为(1,num1)的形式,但是我们需要就是num1,所以通过erYuanShi.substring(erYuanShi.indexOf(",")+ 1,
    erYuanShi.lastIndexOf(")"))方法将num1截取下来,放入List列表对象中,继续读文件,直到读取结束。这样就将二元式文件的内容读取到了字符串s中。1
    和2表示标识符和数字在符号表中的序号,也即1表示当前二元式的实际内容为标识符,2表示为数字,所以如果是标识符和数字时,就将内容转换为i保存到s中。

    最后得到字符串s类似为: i+i*(i-i)/i

    但是实际算术表达式为:a+a*(b-c)/2。

    也就是将用户定义的标识符和数字都转为i。

    4.5 FIRSTVT 集

    private Map<Character,Set<Character>> FIRSTVT = new HashMap<Character,Set<Character>>();

    根据构造规则:

    U∈Vn

    FIRSTVT(U)=

    {b∣U=+>b…, 或U =+> Vb…, b∈Vt,V∈Vn }

    则形如W→…aU…的规则 a < b

    b ∈ FIRSTVT(U)

    在这里插入图片描述

    编写代码:

    //遍历文法。进行非终结符号的FIRSTVT的初始化
    		grammar.forEach((k,v)->{
    			String []nArryStr = v.split("\\|");
    			for(int i=0 ;i<nArryStr.length;i++)
    				
    			{
    				//System.out.println(nArryStr[i]);
    				if(Vt.contains(nArryStr[i].charAt(0)))
    				{
    					char b= nArryStr[i].charAt(0);
    					FIRSTVT.get(k.charAt(0)).add(b);
    				}
    				if(nArryStr[i].length()>=2)
    				if(Vn.contains(nArryStr[i].charAt(0))&&Vt.contains(nArryStr[i].charAt(1)))
    				{
    					char b=nArryStr[i].charAt(1);
    					FIRSTVT.get(k.charAt(0)).add(b);
    				}
    			}
    			
    			
    		});
    		
    		do 
    		{
    			FIRSTVTAllNochange=1;
    			grammar.forEach((k,v)->{
    				String []nArryStr = v.split("\\|");
    				for(int i=0 ;i<nArryStr.length;i++)
    					
    				{
    					char U=k.charAt(0);
    					char V=nArryStr[i].charAt(0);
    					if(Vn.contains(U)&&U!=V&&Vn.contains(V))
    					{
    						
    							FIRSTVT.get(V).forEach(values->{
    								if(!FIRSTVT.get(U).contains(values))
    								{
    								//	System.out.println(values);
    								 FIRSTVT.get(U).add(values);
    								 FIRSTVTAllNochange = 0;
    								}
    							
    							});
    							
    						
    					}
    					
    				}
    				
    				
    			});
    			if(FIRSTVTAllNochange==1)
    				break;
    		}while(true);
    
    

    获得FIRSTVT集:

    S:[#]
    T:[(, i, *, /]
    E:[(, i, *, +, -, /]
    F:[(, i]

    4.6 LASTVT 集

    //LASTVT集 private Map<Character,Set<Character>> LASTVT = new
    HashMap<Character,Set<Character>>();

    LASTVT构造规则:

    U∈Vn

    LASTVT(U)=

    {a∣U=+>…a, 或U =+>…aV, a∈Vt, V ∈Vn }

    则形如W→…Ub…的规则 a > b

    a ∈LASTVT(U)

    编写代码:

    //遍历文法。进行非终结符号的LASTVT的初始化
    		grammar.forEach((k,v)->{
    			String []nArryStr = v.split("\\|");
    			for(int i=0 ;i<nArryStr.length;i++)
    				
    			{
    				//System.out.println(nArryStr[i]);
    				int len= nArryStr[i].length();
    				if(Vt.contains(nArryStr[i].charAt(len-1)))
    				{
    					char b= nArryStr[i].charAt(len-1);
    					LASTVT.get(k.charAt(0)).add(b);
    				}
    				if(nArryStr[i].length()>=2)
    				if(Vt.contains(nArryStr[i].charAt(len-2))&&Vn.contains(nArryStr[i].charAt(len-1)))
    				{
    					char b=nArryStr[i].charAt(len-2);
    					LASTVT.get(k.charAt(0)).add(b);
    				}
    			}
    			
    			
    		});
    		
    		do 
    		{
    			FIRSTVTAllNochange=1;
    			grammar.forEach((k,v)->{
    				String []nArryStr = v.split("\\|");
    				for(int i=0 ;i<nArryStr.length;i++)
    					
    				{
    					int len =nArryStr[i].length();
    					char U=k.charAt(0);
    					char V=nArryStr[i].charAt(len-1);
    					if(Vn.contains(U)&&U!=V&&Vn.contains(V))
    					{
    						
    						LASTVT.get(V).forEach(values->{
    								if(!LASTVT.get(U).contains(values))
    								{
    									//System.out.println(values);
    									LASTVT.get(U).add(values);
    								 FIRSTVTAllNochange = 0;
    								}
    							
    							});
    							
    						
    					}
    					
    				}
    				
    				
    			});
    			if(FIRSTVTAllNochange==1)
    				break;
    		}while(true);
    
    

    最后得到LASTVT集:

    S:[#]

    T:[), i, *, /]

    E:[), i, *, +, -, /]

    F:[), i]

    4.7 算符优先矩阵

    /算符优先权关系表
    /**
    * 在OPGtable中,用-1,0,1,2表示优先权关系
    * 0 表示优先关系等于
    * 1 表示优先关系小于
    * 2 表示优先关系大于
    * -1 表示不存在优先权关系
    * *
    */
    private int [][]OPGtable = new int [N][N];

    在这里插入图片描述

    构造规则:

    编写代码:

    /**
    		 * 在OPGtable中,用-1,0,1,2表示优先权关系
    		 * 0 表示优先关系等于
    		 * 1 表示优先关系小于
    		 * 2 表示优先关系大于
    		 * -1 表示不存在优先权关系
    		 * *
    		 */
    		grammar.forEach((k,v)->{
    			String []nArryStr = v.split("\\|");
    			
    			for(int i=0 ;i<nArryStr.length;i++)			
    			{		
    				String ruleRight=nArryStr[i];
    				int  len = ruleRight.length();
    				if(len>=2)
    				{
    					for(int i1= 0 ;i1<len-1 ;i1++)
    					{
    						char X1=ruleRight.charAt(i1);
    						char X2=ruleRight.charAt(i1+1);
    						
    						if(Vt.contains(X1)&&Vt.contains(X2))				
    							OPGtable[Vt.indexOf(X1)][Vt.indexOf(X2)]=0;//0 表示优先关系等于
    						if(Vt.contains(X1)&&Vn.contains(X2))
    						{
    							FIRSTVT.get(X2).forEach(values->{
    								OPGtable[Vt.indexOf(X1)][Vt.indexOf(values)]=1;//1 表示优先关系小于
    							});
    						}
    						if(Vn.contains(X1)&&Vt.contains(X2))				
    						{
    							LASTVT.get(X1).forEach(values->{
    								OPGtable[Vt.indexOf(values)][Vt.indexOf(X2)]=2;//2 表示优先关系大于
    							});
    						}
    						if(len>=3&&i1<len-2)
    						{
    							char X3=ruleRight.charAt(i1+2);
    							if(Vt.contains(X1)&&Vn.contains(X2)&&Vt.contains(X3))
    							{	
    								OPGtable[Vt.indexOf(X1)][Vt.indexOf(X3)]=0; //0 表示优先关系等于
    							}
    						}
    							
    							
    					}
    					
    				}
    				
    			}
    			
    			
    		});
    
    

    最终的算符优先矩阵:

    在这里插入图片描述

    5、程序结构描述

    5.1Java 主类:OPGMain

    在这里插入图片描述

    5.1.1全局变量
    变量类型变量名称变量作用
    private List<Character>Vt保存终结符号集,需要手动设置
    Private List<Character>Vn保存非终结符号集。需要手动设置
    private Map<Character, String>grammar保存文法,需要手动设置
    private Map<Character,Set<Character>>FIRSTVT保存非终结符号的FIRSTVT集,由函数生成内容
    private Map<Character,Set<Character>>LASTVT保存非终结符号的LASTVT集,有相应的生成函数生成其内容
    private Map<String,Set<Character>>OPGtable//算符优先权关系矩阵 /** * 在OPGtable中,用-1,0,1,2表示优先权关系 * 0 表示优先关系等于 * 1 表示优先关系小于 * 2 表示优先关系大于 * -1 表示不存在优先权关系 * * */
    5.1.2函数
    类型返回值函数名功能
    publicOPGMain构造函数,初始化文法,Vt和Vn
    publicvoidCreate_FIRSTVT构造FIRSTVT集
    publicvoidCreate_LASTVT输出LASTVT集
    publicvoidCreate_OPGTable构造算符优先关系矩阵
    publicvoidOPGanalysis算符优先文法分析器
    publicintget_PriorityRelationship获得两个终结符号的优先关系
    publicstatic voidmain类的主函数,实例化主类,并传入中间文件。
    ./media/image5.png

    5.1.3函数调用关系图
    在这里插入图片描述

    绿色虚线为调用

    6、程序测试

    6.1 正确用例

    测试用例为二元式文件结构部分的用例

    (1,a)
    (4,+)
    (1,b)
    (10,*)
    (3,()
    (1,c)
    (5,-)
    (2,34)
    (3,))
    (11,/)
    (1,num5)

    结果为:

    在这里插入图片描述

    在这里插入图片描述

    6.2 错误用例

    通过修改测试用例1使其不符合赋值语句语法:

    6.2.1缺少操作符

    在这里插入图片描述

    6.2.2缺少 ‘)’符号

    在这里插入图片描述
    源代码:https://github.com/Topdu/Compilation-principle/tree/master/16281002-杜永坤-专题4

    展开全文
  • C++实现算符优先文法

    2020-09-05 12:14:43
    C++读取文件,求解firstvt集与lastvt集,构建算符优先关系表,打印文法分析过程,实现算符优先文法 文章目录Operator-precedence-grammar概述FIRSTVT集和LASTVT集构造算符优先关系表构计算分析过程实现过程输出结果...

    Operator-precedence-grammar

    C++读取文件,求解firstvt集与lastvt集,构建算符优先关系表,打印文法分析过程,实现算符优先文法

    概述

    算符优先分析法(Operator Precedence Parse)是仿效四则运算的计算过程而构造的一种语法分析方法。算符优先分析法的关键是比较两个相继出现的终结符的优先级而决定应采取的动作。

    ​ 优点:简单,有效,适合表达式的分析。

    ​ 缺点:只适合于算符优先文法,是一个不大的文法类。

    FIRSTVT集和LASTVT集

    FIRSTVT集

    定义:FIRSTVT§={a|P=>a…,或P=>Qa…,a属于VT,Q 属于VN}

    求法

    若P→a…或P→Qa…, 则a属于FIRSTVT§;

    若P→Q…, 则FIRSTVT(Q)含于FIRSTVT§;

    直至FIRSTVT§不再增大。

    LASTVT集

    定义:LASTVT§={a|P=>…a,或P=>…aQ,a含于VT,Q 含于VN}

    求法

    若P→…a或P→…aQ, 则a属于LASTVT§;

    若P→…Q, 则LASTVT(Q)含于LASTVT§;

    直至LASTVT§不再增大。

    构造算符优先关系表

    以以下文法为例:

    ​ E→E+T|T

    ​ T→T*F|F

    ​ F→(E)|i

    终结符之间的优先关系

    对算符文法G, a,b属于VT 定义

    (1)a=b: G中有P→. . .ab. . .或P→. . .aQb. . .

    (2)a<b: G中有P→. . .aQ. . .且Q=>b…或Q=>Rb…

    (3)a>b: G中有P→. . .Qb. . . 且Q=>. …a或Q=>…aR

    算符优先关系表的构造

    (1) 在文法中添加E→#E#。

    (2) 求出FIRSTVT和LASTVT集

    (3) 找出所有终结符,并画出关系表的结构

    • 从文法中找出形为aQb(终结符+非终结符+终结符)和ab(终结符+终结符)的部分,本例中为(E)和#E#,然后在(和)与#和#相应的表格填等于号。
    • 从文法中找出形为aQ(终结符+非终结符)的部分,a与Q的FIRSTVT集合中每一个元素在表格中的交叉点填小于号。
    • 从文法中找出形为Qa(非终结符+终结符)的部分, Q的LASTVT集合中每一个元素与a在表格中的交叉点填大于号。

    img

    构计算分析过程

    初始时,输入指针指向输入串的第一个符号,#入栈;然后比较栈顶终结符a和输入符号b的优先关系:
    1.如a=b,且都是#,输入串合法,分析结束。
    2.如a<b或a=b, b入栈,输入指针右移。
    3.如a>b,寻找位于栈顶的包含a的最小的可规约串(最左素短语) ,
    3.1如果找到,将该串规约。
    3.2如果未找到,输入串非法,分析结束。
    4.如a和b不存在优先关系,输入串非法,分析结束。

    实现过程

    输出结果

    代码链接

    C++实现算符优先文法

    展开全文
  • 算符优先文法(MFC)

    2012-07-03 17:58:21
    这是一个用MFC C++编写的一个算符优先文法的语法分析器
  • 编译原理算符优先文法C实现
  • 编译原理中的算符优先文法,构造出一个优先表。
  • 编译原理——判断文法是否为算符优先文法

    千次阅读 多人点赞 2019-12-10 12:29:33
    编译原理——判断文法是否为算符优先文法 在判断之前我们需要看一下该文法是否为算符文法。 算符文法定义 一个文法,如果它的任意产生式的右部都不含两个相继(并列)的非终结符,即不含如下形式的产生式右部: …QR...
  • java写的算符优先文法分析器 包括括号匹配,进出栈操作……
  • 算符优先文法 编译原理大作业 简单 算符
  • 算符优先文法的编程实现

    千次阅读 2017-12-01 09:57:51
    实验三 算符优先文法的编程实现 一、实验目的 1. 通过本次实验,加深对移进规约分析法中算符优先法的理解; 2. 学习程序设计语言的语法分析器的手工编程方法。   二、实验内容 1. 对于任意给定的文法,判断其是否是...
  • 通过初始化文法,以及要检验的输入串,自动构造算符优先表,是很实用的VC程序,适合一切算符优先文法程序的课堂作业
  • 算符优先文法0 目录10 语法分析-自下而上分析110.4 算符优先文法10.4.1 课堂重点10.4.2 测试与作业11 下一章 0 目录 10 语法分析-自下而上分析1 10.4 算符优先文法 10.4.1 课堂重点 10.4.2 测试与作业 11...
  • 基于算符优先文法的分析程序 用java实现 只有程序 没有文档 程序中有说明
  • 实现算符优先文法分析程序;完成对以下表达式文法的分析程序。 G[E]: E->E+T E->T T->T*F T->F F->(E) F->i
  • 检查语法错误,从文件中输入文法,出错语法错误到文件中,对算符优先文法适用

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 1,140
精华内容 456
关键字:

算符优先文法