经过一学期的学习编译原理考试也是成功结束,学校安排的课程设计也圆满完成。编译原理我复习的资料写了很多最终也没有辜负努力吧成功拿到了A+的成绩。课程设计抽取到的题目是LR(1)语法分析器,刚开始对我来说确实不知道从哪里下手。最后也是通过自己查阅资料以及努力成功实现了LR(1)语法分析器的功能。
关于课程设计的部分,基于LR(1)的语法分析器。我采用的是C++的方法进行的书写跟大家分享一下。由于身体原因当时采用的是从文件中读取ACTION和GOTO表的方式,然后对从文件中读取进去的句子进行分析是采用上课所讲述基础知识进行分析。
主要书写的函数及相应功能:
读取文件功能
readFile
菜单功能
menu
初始化功能
init
,
分析句子功能 analyze
输出
ACTION
和
GOTO
表功能
print Actions
和
print Gotos
,
逆序输出固定长度字符串功能
Reverse
将栈转换成字符串功能
stacktostring
,
判断是不是终结符功能 isvt
找寻终结符下标
findvt
找寻非终结符下标
findvn
,
输出剩余输入串功能
printRestInput
主函数功能
main
主要代码:
void analyze(string exp) {
int len = exp.length();
stack<char> chars; // 符号栈
stack<int> state; // 状态栈
state.push(0); // 初始状态为0
chars.push('#'); // 初始符号为#
string charsStr = "#";//符号栈的字符串形式
int cnt = 1; // 序号
int idx = 0; // 当前输入串的指针其实就是指向的下标
cout << "步骤\t状态栈\t 符号栈\t剩余输入串 ACTION\tGOTO" << endl;
cout << cnt++ <<setw(10)<< stacktostring(state) <<"\t "<< charsStr <<"\t"<< exp<<"\t";
while(1) {
int nowState = state.top();//当前状态
char nowChar = exp[idx]; // 当前输入字符
int isT = findvt(nowChar);
if(isT == Null) { // 非终结符
cout << "Error!" << "出现非法字符,程序错误退出" <<endl;
return;
}
string actionStr = action[nowState][isT];//寻找当前所需要的动作
if(actionStr == "acc") {
cout << cnt++ <<"\t";
Reverse(stacktostring(state));
cout<<"\t"<< charsStr <<"\t"<< '#' <<"\t "<< " ACC" << endl;
return;
} else if(actionStr == "N") {
cout << cnt++ <<"\t";
Reverse(stacktostring(state));
cout<< '\t' << charsStr << '\t' << exp << '\t' << "Error! 程序出错了" << endl;
return;
} else if(actionStr[0] == 'r') { // 归约
int num = stoi(actionStr.substr(1)); // 选用第几个产生式归约
int len1 = LR[num-1].length()-3;//求出产生式右部长度
while(len1--) {
chars.pop(); // 出栈,归约
state.pop(); // 便于输出
charsStr = charsStr.substr(0, charsStr.length()-1);
}
chars.push(LR[num-1][0]); // 产生式左部入符号栈
charsStr=charsStr+LR[num-1][0];
//规约之后需要寻找新的状态
int nowState = state.top();
int gidx = findvn(LR[num-1][0]);
int newState = _goto[nowState][gidx];
state.push(newState);
cout <<"\t"<< "r" << num<<"\t"<<newState<< endl;
if(newState==1&&nowChar=='#')
continue;
else{
cout << cnt++ <<"\t";
Reverse(stacktostring(state));
cout<<"\t"<< charsStr<<"\t";
printRestInput(exp, idx, len);
}
} else if(actionStr[0] == 's') {
cout <<"\t"<< actionStr<< endl; // 移进
int newState = stoi(actionStr.substr(1));
state.push(newState);
chars.push(nowChar);
charsStr += nowChar;
idx++; // 输入指针后移
cout << cnt++ <<'\t';
Reverse(stacktostring(state));
cout<<"\t"<< charsStr <<"\t";
printRestInput(exp, idx, len);
} else {
cout << "Error!" << "程序异常退出" <<endl;
return;
}
}
}
int len = exp.length();
stack<char> chars; // 符号栈
stack<int> state; // 状态栈
state.push(0); // 初始状态为0
chars.push('#'); // 初始符号为#
string charsStr = "#";//符号栈的字符串形式
int cnt = 1; // 序号
int idx = 0; // 当前输入串的指针其实就是指向的下标
cout << "步骤\t状态栈\t 符号栈\t剩余输入串 ACTION\tGOTO" << endl;
cout << cnt++ <<setw(10)<< stacktostring(state) <<"\t "<< charsStr <<"\t"<< exp<<"\t";
while(1) {
int nowState = state.top();//当前状态
char nowChar = exp[idx]; // 当前输入字符
int isT = findvt(nowChar);
if(isT == Null) { // 非终结符
cout << "Error!" << "出现非法字符,程序错误退出" <<endl;
return;
}
string actionStr = action[nowState][isT];//寻找当前所需要的动作
if(actionStr == "acc") {
cout << cnt++ <<"\t";
Reverse(stacktostring(state));
cout<<"\t"<< charsStr <<"\t"<< '#' <<"\t "<< " ACC" << endl;
return;
} else if(actionStr == "N") {
cout << cnt++ <<"\t";
Reverse(stacktostring(state));
cout<< '\t' << charsStr << '\t' << exp << '\t' << "Error! 程序出错了" << endl;
return;
} else if(actionStr[0] == 'r') { // 归约
int num = stoi(actionStr.substr(1)); // 选用第几个产生式归约
int len1 = LR[num-1].length()-3;//求出产生式右部长度
while(len1--) {
chars.pop(); // 出栈,归约
state.pop(); // 便于输出
charsStr = charsStr.substr(0, charsStr.length()-1);
}
chars.push(LR[num-1][0]); // 产生式左部入符号栈
charsStr=charsStr+LR[num-1][0];
//规约之后需要寻找新的状态
int nowState = state.top();
int gidx = findvn(LR[num-1][0]);
int newState = _goto[nowState][gidx];
state.push(newState);
cout <<"\t"<< "r" << num<<"\t"<<newState<< endl;
if(newState==1&&nowChar=='#')
continue;
else{
cout << cnt++ <<"\t";
Reverse(stacktostring(state));
cout<<"\t"<< charsStr<<"\t";
printRestInput(exp, idx, len);
}
} else if(actionStr[0] == 's') {
cout <<"\t"<< actionStr<< endl; // 移进
int newState = stoi(actionStr.substr(1));
state.push(newState);
chars.push(nowChar);
charsStr += nowChar;
idx++; // 输入指针后移
cout << cnt++ <<'\t';
Reverse(stacktostring(state));
cout<<"\t"<< charsStr <<"\t";
printRestInput(exp, idx, len);
} else {
cout << "Error!" << "程序异常退出" <<endl;
return;
}
}
}
运行截图:
完整代码下载地址: