0 実験目的
SLR(1) パーサーを設計、コンパイル、実装、デバッグして、パーサーの理解を深めます。
1 実験要件
コンパイル理論コースで学習した算術式文法と文法のLR解析表に従って、C言語を使用して算術式を入力として受け取る文法アナライザを作成し、コンソール(またはテキストファイル、またはそれと組み合わせて)で完成させます。字句アナライザー) ) を入力として使用すると、コンソール (またはファイル) が生成シーケンスの形式で分析結果を出力します。
2 実験内容
LR構文アナライザの実現、実行処理例:id+id*idを解析し、PPT上の予測解析テーブルに従ってid+id*id#を入力し、ポップされて出力された内容を解析します。
文法:
E'->E
E->E+T
E->T
T->T*F
T->F
F->(E)
F->id
3 実験のアイデア
1. まず、最も重要な SLRScanner() 関数 (SLR 文法解析用)、statestack() 関数 (出力状態スタック)、signstack() 関数 (出力シンボル スタック)、print( ) 関数 (残りの文字列出力)、Action() 関数 (分析および出力アクションの説明用)、xfind() 関数 (予測分析変数の検索用)、yfind() 関数 (予測分析テーブルの列変数の検索用)。次に、予測分析テーブルを格納するために文字列の 2 次元配列が定義され、拡張文法を格納するために 2 次元の文字配列が定義され、シンボル スタックと状態スタックの 2 つのスタックが定義されます。
2. この実験プログラムで最も重要なのは SLRScanner() 関数です 次に、これを簡単に分析します: 最初に、フラグ変数 flag が 0 に等しい (初期シフト演算を行う)、次のテーブル検索を容易にするために行変数と列変数を継続的に更新し、0、# をそれぞれ状態スタックとシンボル スタックにプッシュします。次に、xfind 関数と yfind 関数を使用して、行変数と列変数を検索して値を代入し、対応する予測分析テーブル内のデータを判断します。0 に等しい場合は、文法に準拠していないことを返します。そうでない場合は、対応するシンボルと状態をそれぞれシンボル スタックと状態スタックにプッシュし、同時に残りの文字列と対応するアクションの説明を出力します。「s」と等しい場合は flag を 0 に設定し、そうでない場合は 1 に設定します。flag が 1 の場合、指定を実行します (SR(1) と対応する拡張文法を比較し、同時にシンボル スタック、状態スタック、残りの文字列、アクション記述を操作し、対応する生成式を出力します。)を2に変更し、goto後にシフト演算を行った後、予測分析テーブルと比較し、SRが0であればテーブル参照の結果が間違っていることを示し、SRがaccと等しい場合はプログラムを終了し、出力文字列は文法に従っています。
3. 他の関数もさらに重要です。これらは SLR 文法解析関数で呼び出されます。スタックの操作を通じてシンボルと状態の出力が実現され、プログラムが大幅に簡素化されます。アクション関数はアクションの記述の出力に役立ちます。 xfind と yfind は予測分析テーブルの検索に役立ち、どちらも不可欠な役割を果たします。
4 実験コード
#include <bits/stdc++.h>
using namespace std;
string SLRGrammer[12][9]{
"s5", "0", "0", "s4", "0", "0", "1", "2", "3",
"0", "s6", "0", "0", "0", "acc", "0", "0", "0",
"0", "r2", "s7", "0", "r2", "r2", "0", "0", "0",
"0", "r4", "r4", "0", "r4", "r4", "0", "0", "0",
"s5", "0", "0", "s4", "0", "0", "8", "2", "3",
"0", "r6", "r6", "0", "r6", "r6", "0", "0", "0",
"s5", "0", "0", "s4", "0", "0", "0", "9", "3",
"s5", "0", "0", "s4", "0", "0", "0", "0", "a",
"0", "s6", "0", "0", "s11", "0", "0", "0", "0",
"0", "r1", "s7", "0", "r1", "r1", "0", "0", "0",
"0", "r3", "r3", "0", "r3", "r3", "0", "0", "0",
"0", "r5", "r5", "0", "r5", "r5", "0", "0", "0"};
char Grammer[7][10] = {"E→E'", "E→E+T", "E→T", "T→T*F", "T→F", "F→(E)", "F→id"};
char x[12] = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b'};
char y[9] = {'i', '+', '*', '(', ')', '#', 'E', 'T', 'F'};
int xfind(char a);
int yfind(char a);
int stri = 0;
int flag = 0;
int strlength;
string SR;
string strs;
string str;
stack<char> state;
stack<char> sign;
void SLRScanner(string str);
void statestack();
void signstack();
void print(string s, int n);
void VerbScanner(string str, int i);
void Action(int i, int flag2, int x, int y);
string Convert(char a, string b);
void SLRScanner(string str)
{
for (; stri < str.length();)
{
if (flag == 0)
{
stri++;
int x, y;
state.push(SR[1]);
sign.push(str[stri - 1]);
x = xfind(SR[1]);
y = yfind(str[stri]);
SR = SLRGrammer[x][y];
if (SR == "0")
{
cout << "\t输入的字符串不符合SLR文法" << endl;
break;
}
print(str, stri);
signstack();
cout << "\t\t";
statestack();
cout << "\t\t\t";
Action(stri, 0, x, y);
printf("\n");
if (SR[0] == 's')
flag = 0;
else
flag = 1;
}
if (flag == 1)
{
int x, y;
char r, c;
if (SR[1] == '1')
{
for (int i = 0; i < 3; i++)
{
state.pop();
sign.pop();
}
sign.push('E');
r = state.top();
c = sign.top();
x = xfind(r);
y = yfind(c);
print(str, stri);
signstack();
cout << "\t\t";
statestack();
cout << "\t\t" << Grammer[1];
Action(stri, 1, x, y);
printf("\n");
SR = SLRGrammer[x][y];
}
else if (SR[1] == '2')
{
for (int i = 0; i < 1; i++)
{
state.pop();
sign.pop();
}
sign.push('E');
r = state.top();
c = sign.top();
x = xfind(r);
y = yfind(c);
print(str, stri);
signstack();
cout << "\t\t";
statestack();
cout << "\t\t" << Grammer[2] << "\t";
;
Action(stri, 1, x, y);
printf("\n");
SR = SLRGrammer[x][y];
}
else if (SR[1] == '3')
{
for (int i = 0; i < 3; i++)
{
state.pop();
sign.pop();
}
sign.push('T');
r = state.top();
c = sign.top();
x = xfind(r);
y = yfind(c);
print(str, stri);
signstack();
cout << "\t\t";
statestack();
cout << "\t\t" << Grammer[3];
Action(stri, 1, x, y);
printf("\n");
SR = SLRGrammer[x][y];
}
else if (SR[1] == '4')
{
for (int i = 0; i < 1; i++)
{
state.pop();
sign.pop();
}
sign.push('T');
r = state.top();
c = sign.top();
x = xfind(r);
y = yfind(c);
print(str, stri);
signstack();
cout << "\t\t";
statestack();
cout << "\t\t" << Grammer[4] << "\t";
;
Action(stri, 1, x, y);
printf("\n");
SR = SLRGrammer[x][y];
}
else if (SR[1] == '5')
{
for (int i = 0; i < 3; i++)
{
state.pop();
sign.pop();
}
sign.push('F');
r = state.top();
c = sign.top();
x = xfind(r);
y = yfind(c);
print(str, stri);
signstack();
cout << "\t\t";
statestack();
cout << "\t\t" << Grammer[5] << "\t";
;
Action(stri, 1, x, y);
printf("\n");
SR = SLRGrammer[x][y];
}
else if (SR[1] == '6')
{
for (int i = 0; i < 1; i++)
{
state.pop();
sign.pop();
}
sign.push('F');
r = state.top();
c = sign.top();
x = xfind(r);
y = yfind(c);
print(str, stri);
signstack();
cout << "\t\t";
statestack();
cout << "\t\t" << Grammer[6] << "\t";
;
Action(stri, 1, x, y);
printf("\n");
SR = SLRGrammer[x][y];
}
flag = 2;
}
if (flag == 2)
{
int prow, pcol;
state.push(SR[0]);
prow = xfind(SR[0]);
pcol = yfind(str[stri]);
SR = SLRGrammer[prow][pcol];
if (SR == "0")
{
cout << "\t 输入的字符串不符合SLR文法" << endl;
break;
}
print(str, stri);
signstack();
cout << "\t\t";
statestack();
cout << "\t\t\t";
Action(stri, 0, prow, pcol);
cout << endl;
if (SR[0] == 's')
flag = 0;
else
flag = 1;
}
if (SR == "acc")
{
cout << "\n\t该字符串符合SLR文法。" << endl;
break;
}
}
}
void statestack()
{
stack<char> temp;
string b;
int l = state.size();
for (int i = 0; i < l; i++)
{
char a = state.top();
state.pop();
temp.push(a);
}
for (int i = 0; i < l; i++)
{
char a = temp.top();
b = Convert(a, b);
temp.pop();
state.push(a);
}
cout << std::left << setw(7) << b;
}
void VerbScanner(string str, int i)
{
if (isalpha(str[i]))
{
string lett;
while (isdigit(str[i]) || isalpha(str[i]) || str[i] == '_' || str[i] == '.')
{
lett += str[i];
i++;
}
i--;
if (lett == "id")
strs = strs + 'i';
}
else if (str[i] == '+')
strs = strs + '+';
else if (str[i] == '*')
strs = strs + '*';
else
strs = strs + '#';
}
int xfind(char a)
{
int n;
for (int i = 0; i < 12; i++)
{
if (a == x[i])
{
n = i;
return n;
}
}
return 0;
}
int yfind(char a)
{
int n;
for (int i = 0; i < 9; i++)
{
if (a == y[i])
{
n = i;
return n;
}
}
return 0;
}
string Convert(char a, string b)
{
if (a == 'i')
b = b + "id";
else
b = b + a;
return b;
}
void Action(int i, int flag2, int x, int y)
{
char G = sign.top();
if (flag2 == 0)
cout << "\t"
<< " Action(" << x << "," << str[i] << ")";
else
cout << "\t"
<< " Goto(" << x << "," << G << ")";
}
void signstack()
{
stack<char> temp;
string b;
int l = sign.size();
for (int i = 0; i < l; i++)
{
char a = sign.top();
sign.pop();
temp.push(a);
}
for (int i = 0; i < l; i++)
{
char a = temp.top();
b = Convert(a, b);
temp.pop();
sign.push(a);
}
cout << "\t" << std::left << setw(7) << b;
}
void print(string s, int n)
{
string a;
for (; n < s.length(); n++)
if (s[n] == 'i')
a = a + "i";
else
a = a + s[n];
cout << std::right << setw(10) << a;
}
int main()
{
cout << "请输入需要分析的符号串:";
cin >> str;
strlength = str.length();
for (int i = 0; i < strlength; i++)
{
if (str[i] == ' ' || str[i] == '\n')
continue;
else
VerbScanner(str, i);
}
cout << " 输入串"
<< "\t状态栈"
<< "\t\t符号栈"
<< "\t\t所用产生式"
<< "\t 所做动作" << endl;
cout << " " << str;
str = strs;
cout << " ";
sign.push('#');
state.push('0');
SR = "s5";
signstack();
cout << "\t\t";
statestack();
cout << "\t\t\t";
Action(0, 0, 0, 0);
printf("\n");
SLRScanner(str);
return 0;
}
5 実験結果
6 実験の概要
这个实验要求不尽相同,需要改一下,可以与我私信讨论。
7 实验程序以及实验报告下载链接
编译原理实验:包括实验一词法分析器,实验二进制分析,实验三语法分析器,实验四SLR语法分析器等其中含有实验报告,实验代码等等-C++文档类资源-CSDN文库