问题
【问题描述】已知文法G[E]:
E → E + T | T
T → (E) | id | id[E]
设计LR分析表,并用c++语言编写语法分析器。
【输入形式】一个句子
【输出形式】句子语法结构正确,输出“Syntax analysis is right”反之输出“Error on syntax analysis”
【样例输入】a1+a2
【样例输出】Syntax analysis is right
【样例说明】
【评分标准】根据通过的测试数据个数评分
思路
其中
I1,I4存在移入规约冲突
且
对于I1:
{+} ∩ FOLLOW(S) = { + } ∩ {#} = $ \emptyset $
对于I4:
{ [ } ∩ FOLLOW(T) = {[} ∩ FOLLOW(E) ={ [ } ∩ { +,),],# } = $ \emptyset $
所以,适用SLR(1)文法
0x02 做出SLR分析表
ACTION | GOTO | ||||||||
---|---|---|---|---|---|---|---|---|---|
+ | ( | ) | [ | ] | id | # | E | T | |
0 | s3 | s4 | 1 | 2 | |||||
1 | s5 | acc | |||||||
2 | r2 | r2 | r2 | r2 | |||||
3 | s3 | s4 | 6 | 2 | |||||
4 | r4 | r4 | s7 | r4 | r4 | ||||
5 | s3 | s4 | 8 | ||||||
6 | s5 | s9 | |||||||
7 | s3 | s4 | 10 | 2 | |||||
8 | r1 | r1 | r1 | r1 | |||||
9 | r3 | r3 | r3 | r3 | |||||
10 | s5 | s11 | |||||||
11 | r5 | r5 | r5 | r5 |
对于产生式:
0、S -> E
1、E -> E+T
2、E ->T
3、T ->(E)
4、T ->id
5、T ->id[E]
进行代码编写模拟分析过程:
代码:
#include <iostream>
#include <stack>
#include <vector>
#include <queue>
#include <string>
#include <map>
using namespace std;
//action 表
vector<string> action[12];
void initial_action_table()
{
for (int i = 0;i < 12;i++)
{
for (int j = 0;j < 7;j++)
{
action[i].push_back("NULL");
}
}
action[0][1] = "s3";action[0][5] = "s4";
action[1][0] = "s5";action[1][6] = "acc";
action[2][0] = "r2";action[2][2] = "r2";action[2][4] = "r2";action[2][6] = "r2";
action[3][1] = "s3";action[3][5] = "s4";
action[4][0] = "r4";action[4][2] = "r4";action[4][3] = "s7";action[4][4] = "s7";action[4][4] = "r4";action[4][6] = "r4";
action[5][1] = "s3";action[5][5] = "s4";
action[6][0] = "s5";action[6][2] = "s9";
action[7][1] = "s3";action[7][5] = "s4";
action[8][0] = "r1";action[8][2] = "r1";action[8][4] = "r1";action[8][6] = "r1";
action[9][0] = "r3";action[9][2] = "r3";action[9][4] = "r3";action[9][6] = "r3";
action[10][0] = "s5";action[10][4] = "s11";
action[11][0] = "r5";action[11][2] = "r5";action[11][4] = "r5";action[11][6] = "r5";
}
//goto表
int goTo[12][2] = {
1, 2,
0, 0,
0, 0,
6, 2,
0, 0,
0, 8,
0, 0,
10, 2,
0, 0,
0, 0,
0, 0,
0, 0
};
//Vt、Vn
vector<char> Vn = {'+', '(', ')', '[', ']', 'a', '#'};
vector<char> Vt = {'S', 'E', 'T'};
/*
我们需要表达用
1、表达式左部 进行归约
2、表达式右部的长度用于出栈
对产生式进行编号:
0、S -> E
1、E -> E+T
2、E ->T
3、T ->(E)
4、T ->id
5、T ->id[E]
*/
struct Production{
char Vt;
int length;
};
Production pro[6] = { {'S',1}, {'E',3}, {'E',1}, {'T',3}, {'T',1}, {'T',4}};
//状态栈
stack<int> state;
//符号栈
queue<char> symbol;
void initial_queue()
{
//输入:
char ch;
// {'+', '(', ')', '[', ']', 'i', '#'};
while((ch = getchar()) != EOF)
{
switch(ch)
{
case '+': symbol.push('+');break;
case '(': symbol.push('(');break;
case ')': symbol.push(')');break;
case '[': symbol.push('[');break;
case ']': symbol.push(']');break;
case 'a':
if (isdigit(getchar()))
symbol.push('a');
break;
default:
break;
}
}
symbol.push('#');
}
int main()
{
initial_action_table();
initial_queue();
state.push(0);
map<char, int> Vn2num;
int k = 0;
for (vector<char>::iterator it = Vn.begin();it != Vn.end(); it++)
{
Vn2num.insert(pair<char,int>(*it, k));
k++;
}
while(1)
{
char ch = symbol.front();
int top = state.top();
int index = Vn2num[ch];
string str = action[top][index];
if(str[0] == 's')
{
int nextstate = 0;
for(int i = 1; str[i] ; i++)
{
nextstate = nextstate*10 + (str[i] - '0');
}
state.push(nextstate);
symbol.pop();
}
if(str[0] == 'r')
{
int pro_index = 0; //产生式标号
for(int i = 1; str[i] ; i++)
{
pro_index = pro_index*10 + (str[i] - '0');
}
int popnum = pro[pro_index].length;
char Vt = pro[pro_index].Vt;
//出栈
for(int i = 0;i < popnum;i ++)
{
state.pop();
}
//GOTO 查出栈后的状态的GOTO表
if(Vt == 'E')
{
state.push(goTo[state.top()][0]);
}
else
{
state.push(goTo[state.top()][1]);
}
}
if(str[0] == 'a')
{
cout << "Syntax analysis is right"; break;
}
if(str[0] == 'N')
{
cout << "Error on syntax analysis"; break;
}
}
}