具体要求
已知文法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)
|
具体实现
#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];
};
}