实验3《算符优先分析法设计与实现》
一、实验目的
加深对语法分析器工作过程的理解;加强对算符优先分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
二、实验内容
在实验1的基础上,用算符优先分析法编制语法分析程序,语法分析程序的实现可以采用任何一种编程语言和工具。
三、实验方法
1.实验采用C++程序语言进行设计,用户自定义输入文法进行分析;
2.开发工具为Visual Studio Code。
四、实验步骤
1.本程序中的文法,实质上是算数表达式的计算。
2.构建firstVT()和lastVT()这两个集合;
3.构建优先符号表;
4.构建词法分析的程序;
5.编写main函数,用户输入文法对语句利用算符优先文法进行判别。
6.算法的主体思想:
用栈存储已经看到的输入符号,用优先关系指导移动归约语法分析器的动作 ,如果栈顶的终结符和下一个输入符之间的优先关系是<或=,则语法分析器移动,表示还没有发现句柄的右端,如果是>关系,就调用归约。
五、实验结果
- 运行实验代码,用户先输入文法个数,之后输入具体文法,程序根据输入进行FIRSTVT集、LASTVT集和算符优先表的计算,之后再对句子进行文法判别。
实验输入数据为:
6
S->#E#
P->i
F->P
T->F
E->T
E->E+T
测试结果:
测试结果符合预期结果,能够对句子i+i进行正确判别,用户也可以自定义其他语句进行实验。实验截图如下所示:
六、实验结论
1.实验利用自定义的源程序进行测试,结果正确,符合预期结果,测试源码及结果截图和说明如上所示。
2.实验源代码如下所示:
test3.cpp
/**************************
Compiler Principle
test3 算符优先分析法设计与实现
author:zz
vs code
2019.05.05
***************************/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <cctype>
#define MAX 507
using namespace std;
class WF
{
public:
string left;
vector<string> right;
WF ( const string& str )
{
left = str;
}
void insert ( char str[] )
{
right.push_back(str);
}
void print ( )
{
printf ( "%s->%s" , left.c_str() , right[0].c_str() );
for ( int i = 1 ; i < right.size() ; i++ )
printf ( "|%s" , right[i].c_str() );
puts("");
}
};
char relation[MAX][MAX];
vector<char> VT;
vector<WF> VN_set;
map<string,int> VN_dic;
set<char> first[MAX];
set<char> last[MAX];
int used[MAX];
int vis[MAX];
void dfs ( int x )
{
if ( vis[x] ) return;
vis[x] = 1;
string& left = VN_set[x].left;
for ( int i = 0 ; i < VN_set[x].right.size() ; i++ )
{
string& str = VN_set[x].right[i];
if ( isupper(str[0]) )
{
int y = VN_dic[str.substr(0,1)]-1;
if ( str.length() > 1 && !isupper(str[1] ) )
first[x].insert ( str[1] );
dfs ( y );
set<char>::iterator it = first[y].begin();
for ( ; it!= first[y].end() ; it++ )
first[x].insert ( *it );
}
else
first[x].insert ( str[0] );
}
}
void make_first ( )
{
memset ( vis , 0 , sizeof ( vis ) );
for ( int i = 0 ; i < VN_set.size() ; i++ )
if ( vis[i] ) continue;
else dfs ( i );
#define DEBUG
#ifdef DEBUG
puts("------------FIRSTVT集-------------------");
for ( int i = 0 ; i < VN_set.size() ; i++ )
{
printf ( "%s : " , VN_set[i].left.c_str() );
set<char>::iterator it = first[i].begin();
for ( ; it!= first[i].end() ; it++ )
printf ( "%c " , *it );
puts ("" );
}
#endif
}
void dfs1 ( int x )
{
if ( vis[x] ) return;
vis[x]