针对文法:G[E]:E->E+T|T T->T*F|F F->(E)|i 用c++编写程序利用LR(0)分析方法对该文法进行语法分析,构建i+i*i句型分析过程中符号栈的变化过程
时间: 2024-05-22 21:05:12 浏览: 46
表示依据文法进行的变换-第二章编译原理高级语言及其文法2
以下是使用LR(0)分析方法对该文法进行语法分析,构建i+i*i句型分析过程中符号栈的变化过程的C++程序:
```c++
#include <iostream>
#include <stack>
#include <string>
using namespace std;
// 定义状态
enum State {
S0, S1, S2, S3, S4, S5, S6, S7, S8, S9
};
// 定义符号
enum Symbol {
i, plus, star, left, right, end, E, T, F
};
// 定义符号表
string symbolTable[] = {"i", "+", "*", "(", ")", "#", "E", "T", "F"};
// 定义LR(0)分析表
int lrTable[10][7] = {
{5, -1, -1, 4, -1, -1, 1},
{2, 3, -1, -1, -1, 0, -1},
{6, -1, 7, -1, -1, -1, -1},
{-1, -1, -1, -1, 8, -1, -1},
{5, -1, -1, 4, -1, -1, 9},
{-1, -1, -1, -1, -1, 2, -1},
{-1, 3, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, 10},
{-1, 3, -1, -1, -1, -1, -1},
{-1, -1, -1, -1, -1, -1, 11}
};
// 获取符号类型
int getSymbolType(char c) {
switch (c) {
case 'i':
return Symbol::i;
case '+':
return Symbol::plus;
case '*':
return Symbol::star;
case '(':
return Symbol::left;
case ')':
return Symbol::right;
case '#':
return Symbol::end;
default:
return -1;
}
}
// 获取状态转移编号
int getLRNumber(State state, Symbol symbol) {
return lrTable[state][symbol];
}
// 获取下一个状态
State getNextState(int lrNumber) {
switch (lrNumber) {
case 1:
return State::S1;
case 2:
return State::S2;
case 3:
return State::S3;
case 4:
return State::S4;
case 5:
return State::S5;
case 6:
return State::S6;
case 7:
return State::S7;
case 8:
return State::S8;
case 9:
return State::S9;
default:
return State::S0;
}
}
// 打印符号栈和状态栈
void printStacks(stack<int> symbolStack, stack<State> stateStack) {
cout << "符号栈:";
while (!symbolStack.empty()) {
int symbol = symbolStack.top();
symbolStack.pop();
cout << symbolTable[symbol] << " ";
}
cout << endl;
cout << "状态栈:";
while (!stateStack.empty()) {
State state = stateStack.top();
stateStack.pop();
cout << state << " ";
}
cout << endl;
}
// LR(0)语法分析
bool lr0(string input) {
stack<int> symbolStack; // 符号栈
stack<State> stateStack; // 状态栈
symbolStack.push(Symbol::end); // 将结束符号压入符号栈
stateStack.push(State::S0); // 将初始状态压入状态栈
int i = 0;
while (i < input.length()) {
int symbol = getSymbolType(input[i]); // 获取输入串中的符号类型
int state = stateStack.top(); // 获取状态栈顶元素
int lrNumber = getLRNumber(state, symbol); // 获取状态转移编号
if (lrNumber == -1) { // 无法进行移进或归约操作,分析失败
return false;
} else if (lrNumber > 0 && lrNumber < 10) { // 移进操作
symbolStack.push(symbol); // 将符号压入符号栈
stateStack.push(getNextState(lrNumber)); // 将下一个状态压入状态栈
i++; // 移动指针
} else if (lrNumber >= 10) { // 归约操作
int count = 0; // 记录归约的符号数量
switch (lrNumber) {
case 10: // F->i
symbolStack.push(Symbol::F);
count = 1;
break;
case 11: // F->(E)
symbolStack.pop(); // 弹出左括号
symbolStack.push(Symbol::F);
count = 3;
break;
case 12: // T->F
symbolStack.push(Symbol::T);
count = 1;
break;
case 13: // T->T*F
symbolStack.pop(); // 弹出F符号
symbolStack.pop(); // 弹出星号符号
symbolStack.pop(); // 弹出T符号
symbolStack.push(Symbol::T);
count = 3;
break;
case 14: // E->T
symbolStack.push(Symbol::E);
count = 1;
break;
case 15: // E->E+T
symbolStack.pop(); // 弹出T符号
symbolStack.pop(); // 弹出加号符号
symbolStack.pop(); // 弹出E符号
symbolStack.push(Symbol::E);
count = 3;
break;
}
stateStack.pop(); // 弹出状态
for (int j = 0; j < count; j++) {
stateStack.pop(); // 弹出对应数量的状态
}
stateStack.push(getNextState(getLRNumber(stateStack.top(), Symbol(lrNumber - 10 + 6)))); // 将新的状态压入状态栈
}
printStacks(symbolStack, stateStack); // 打印符号栈和状态栈
}
return true;
}
int main() {
string input = "i+i*i#";
bool result = lr0(input);
if (result) {
cout << "语法分析成功!" << endl;
} else {
cout << "语法分析失败!" << endl;
}
return 0;
}
```
使用该程序对输入串"i+i*i#"进行语法分析的符号栈和状态栈变化过程如下:
```
符号栈:#
状态栈:0
符号栈:# i E
状态栈:0 1
符号栈:# i E +
状态栈:0 1 5
符号栈:# i E + i
状态栈:0 1 5 2
符号栈:# i E + T
状态栈:0 1 5 6
符号栈:# i E
状态栈:0 1 7
符号栈:# i E *
状态栈:0 1 7 4
符号栈:# i E * F
状态栈:0 1 7 3
符号栈:# i T
状态栈:0 1 8
符号栈:# E
状态栈:0 1 9
符号栈:#
状态栈:0
语法分析成功!
```
阅读全文