编译原理c++基于LR分析表编写语法分析器

具体要求

已知文法G[E]:

E->E+T | T

T->(E) | id | id[E] //其中E,T为非终结符,其余符号为终结符

(1)为该文法建立LR分析表。//通过构造项目集规范族完成识别可归前缀的DFA。

(2)根据测试样例及你建立的LR分析表,用c++完成语法分析器的设计。

测试样例

要求格式完全一致,第一行为输入,第二行为要求的输出,共四组样例。

a1 + a2

Syntax analysis is right

 

a1 + (a2)

Syntax analysis is right

 

a1++a2

Error on syntax analysis

 

a1[a2 + a3] + a4 + a5

Syntax analysis is right

 

a1 + a2[a3] + a4 + (a5 + a6)

Syntax analysis is right

PS

1.代码仅考虑了变量为a0-a9的情况,如有变化,需要进行修改。

2.代码在本机测试时完全正确,在上传在线平台验证时报错,信息如下:

 具体原因未知,怀疑是数组或栈的问题,在解决后更新。。。

 运行时错误(SIGSEGV)
错误原因可能是:
非法的内存引用, 具体原因可能是:
1.数组越界使用;
2.指针的错误使用, 一般是对非用户区的地址空间进行读或者写操作;
3.越权操作文件指针, 程序中却未捕捉该类错误;
4.栈溢出, 一般是因为过多的递归调用或者过大的临时变量导致;5.程序使用的内存超过了题目设定的上限。

 

具体实现

#include <iostream>

#include <stdlib.h>

#include <stdio.h>

#include <stack>
 
#include <cstring> 

#include <map>

#define MAXNUM 1000

using namespace std;

int symbolNum;
string inputSymbol[MAXNUM];
stack<int> status;
stack<string> instr;
stack<string> symbol;

int table1[12][7]={0,1,0,0,0,1,0,
					1,0,0,0,0,0,-1,
					2,0,2,0,2,0,2,
					2,0,2,0,2,1,2,
					2,0,2,1,2,0,2,
					0,1,0,0,0,1,0,
					0,1,0,0,0,1,0,
					1,0,1,0,0,0,0,
					1,0,0,0,1,0,0,
					2,0,2,0,2,0,2,
					2,0,2,0,2,0,2,
					2,0,2,0,2,0,2};
int table2[12][7]={0,3,0,0,0,4,0,
					5,0,0,0,0,0,0,
					2,0,2,0,2,0,2,
					4,0,4,0,4,4,4,
					4,0,4,6,4,0,4,
					0,3,0,0,0,4,0,
					0,3,0,0,0,4,0,
					5,0,10,0,0,0,0,
					5,0,0,0,11,0,0,
					1,0,1,0,1,0,1,
					3,0,3,0,3,0,3,
					5,0,5,0,5,0,5};;
int table3[12][2]={1,2,
					0,0,
					0,0,
					7,2,
					0,0,
					0,9,
					8,2,
					0,0,
					0,0,
					0,0,
					0,0,
					0,0};;

map<string, string> infer;
map<string, int> infernum;
map<int, string> inferstr;

void initial(){
	
	infer["E+T"] = "E";
  	infer["T"] = "E";
  	infer["(E)"] = "T";
  	infer["id"] = "T";
  	infer["id[E]"] = "T";
  	
	infernum["E+T"] = 3;
  	infernum["T"] = 1;
  	infernum["(E)"] = 3;
  	infernum["id"] = 1;
  	infernum["id[E]"] = 4;
  	
  	inferstr[1]="E+T";
  	inferstr[2]="T";
  	inferstr[3]="(E)";
  	inferstr[4]="id";
  	inferstr[5]="id[E]";
  	
	status.push(0);

	instr.push("#");
	symbol.push("#");

	for (int i=symbolNum-1; i>=0; i--) {
		symbol.push(inputSymbol[i]);
	}
}

bool isnumber (char ch){
		
		if(ch>=48 && ch<=57){
            return 1;
        }
     
    return 0;
}

int symboltoint(string ch){
	if(ch=="+")return 0;
	if(ch=="(")return 1; 
	if(ch==")")return 2;
	if(ch=="[")return 3;
	if(ch=="]")return 4;
	if(ch=="id")return 5;
	if(ch=="#")return 6;
}

int instrtoint(string ch){
	if(ch=="E")return 0;
	if(ch=="T")return 1;
}

void grammerAnalysis(){
	int action,change,number;
	while(true){
		action=table1[status.top()][symboltoint(symbol.top())];//1,2
		change=table2[status.top()][symboltoint(symbol.top())];//4,2
		//action:S,移进
		if(action==1){
		 	instr.push(symbol.top());
		 	symbol.pop();
		 	status.push(change);
		}
		//action:r,规约 
		else if(action==2){
			string n=inferstr[change];
			for(int i=0;i<infernum[n];i++){
				status.pop();
				instr.pop();
			}
			instr.push(infer[n]);
			number=table3[status.top()][instrtoint(instr.top())];//2
			status.push(number);
		}
		//acc
		else if(action==-1){
			cout<<"Syntax analysis is right";
			break;
		}
		//action=0
		else{
			cout<<"Error on syntax analysis";
			break;
		}
}
}

int main(){
	//输入句子
	char x,y;
	string a;
	do{
    	scanf("%c",&x);
    	if(x==' '){
    		continue;
		}
    	else if(x=='a') {
    		scanf("%c",&y);
    		if(isnumber(y)){
    			a="id";
				inputSymbol[symbolNum++]=a;
			}
			else{
				continue;
			}	
		}
		else if(x=='\n'){
			break;
		}
		else{
			inputSymbol[symbolNum++]=x;
		};
	}while(x!='\n');
	
	if(symbolNum==0){
		cout<<"Error on syntax analysis";
	}
	else{
		//栈初始化 
		initial(); 
		//语法分析 
		grammerAnalysis();
	}

	return 0;
}

12月19日更新:

不容易,花了好几个小时终于过了。

报错原因:系统中,scanf函数不接受换行符‘\n’

解决办法:用getline函数直接获取一整行字符串的输入,再把字符串的每一个字符挨个放进字符数组里

代码如下:修改main函数中读取输入的部分

	string input;
	char ch[1024];
	int number;
	getline(cin,input);
	for(int i=0;i<=input.length();i++){
		ch[number++]=input[i];
	}
	//cout<<ch<<endl<<number-1<<endl;
	for(int i=0;i<=number-2;i++){
		if(ch[i]==' '){
    		continue;
		}
    	else if(ch[i]=='a') {   			
    		if(isnumber(ch[++i])){
				inputSymbol[symbolNum++]="id";
			}
			else{
				continue;
			}
		}
		else{
			inputSymbol[symbolNum++]=ch[i];
			//cout<<input[i];
		};
	}

 

  • 8
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值