1、实验目的及要求
1.1、实验目的
加深对语法分析器工作过程的理解;加强对算符优先分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
1.2、实验要求
花一周时间写出表达式的文法,优先符号表等理论准备。设计好程序结构,画出模块结构图,写出模块接口和调用关系。描述每个模块的功能。上机编制子模块代码,并测试。业余继续完成代码设计。第二次上机进行调试、修改,对照测试数据比对结果。第三次上机要求全部通过。有余力的同学可编制解释执行程序,对表达式进行求值(此时可不考虑赋值语句)。
2、实验步骤
2.1、模块一:构建firstVT()和lastVT()集合
3、实验内容
3.1、流程图
3.2、源代码
#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <string>
#include <cstdlib>
#include <cctype>
#define MAX 512
using namespace std;
class WF
{
public:
string left;//产生式的左部
vector<string> right;//产生式右部
WF ( const string& str )
{
left = str;
}
//一个非终结符可以有多个产生式
//把右部的起始指针存入right的最后
void insert ( char str[] )
{
right.push_back(str);
}
//合并和打印产生式
void print ( )
{
for ( unsigned i = 0 ; i < right.size() ; i++ )
{
if (i==0)
{
printf ( "%s->%s" , left.c_str() , right[i].c_str() );
}
else
{
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];//firstVT集合
set<char> last[MAX];//lastVT集合
int used[MAX];//终结符的出现顺序表
int vis[MAX];//标志第i条产生式是否处理了
//找出每个非终结符的对应的firstVT
//获取左部的非终结符
//遍历右部
void dfs_first (int x)
{
if ( vis[x] )
{
return;
}
vis[x] = 1;//表示第i条产生式处理过了
string& left = VN_set[x].left;
for ( unsigned 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_first ( y );
set<char>::iterator it = first[y].begin();
for ( ; it!= first[y].end() ; it++ )
{
first[x].insert ( *it );
}
}
else
{
first[x].insert ( str[0] );
}
}
}
//构建firstVT集
//如果vis[i]为0,表示第i条产生式还没处理,则调用dfs来查找它的firstVT,查找完后将vis[i]置1,表示已经处理了第i条产生式
void make_first ( )
{
//将vis数组元素置0
memset ( vis , 0 , sizeof ( vis ) );
for ( unsigned i = 0 ; i < VN_set.size() ; i++ )
{
if ( vis[i] )
{
continue;
}
else
{
dfs_first (i);
}
}
puts("------------FIRSTVT集-------------------");
for ( unsigned 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 ("" );
}
}
//找出每个非终结符的对应的lastVT
void dfs_last ( int x )
{
if ( vis[x] )
return;
vis[x] = 1;
string& left = VN_set[x].left;
for ( unsigned i = 0 ; i < VN_set[x].right.size() ; i++ )
{
string& str = VN_set[x].right[i];
int n = str.length() -1;
if ( isupper(str[n] ) )
{
int y = VN_dic[str.substr(n,1)]-1;
if ( str.length() > 1 && !isupper(str[n-1]) )
{
last[x].insert ( str[1] );
}
dfs_last ( y );
set<char>::iterator it = last[y].begin();
for ( ; it != last[y].end() ; it++ )
{
last[x].insert ( *it );
}
}
else
{
last[x].insert ( str[n] );
}
}
}
//构建lastVT集
void make_last ( )
{
memset ( vis , 0 , sizeof ( vis ) );//vis数组元素全部置0
for ( unsigned i = 0 ; i < VN_set.size() ; i++ )
if ( vis[i] ) continue;
else dfs_last ( i );
puts("--------------LASTVT集---------------------");
for ( unsigned i = 0 ; i < VN_set.size() ; i++ )
{
printf ( "%s : " , VN_set[i].left.c_str() );
set<char>::iterator it = last[i].begin();
for ( ; it!= last[i].end() ; it++ )
printf ( "%c " , *it );
puts ("" );
}
}
//构造算法关系优先表
void make_table ( )
{
for ( int i = 0 ; i < MAX ; i++ )
for ( int j = 0 ; j < MAX ; j++ )
relation[i][j] = ' ';
for ( unsigned i = 0 ; i < VN_set.size() ; i++ )
{
for ( unsigned j = 0 ; j < VN_set[i].right.size() ; j++ )
{
string& str = VN_set[i].right[j];
for ( unsigned k = 0 ; k < str.length()-1 ; k++ )
{
if ( !isupper(str[k]) && !isupper(str[k+1]) )
relation[str[k]][str[k+1]] = '=';
if ( !isupper(str[k]) && isupper(str[k+1]) )
{
int x = VN_dic[str.substr(k+1,1)]-1;
set<char>::iterator it = first[x].begin();
for ( ; it != first[x].end() ; it++ )
relation[str[k]][*it] = '<';
}
if ( isupper(str[k]) && !isupper(str[k+1]) )
{
int x = VN_dic[str.substr(k,1)]-1;
set<char>::iterator it = last[x].begin();
for ( ; it != last[x].end() ; it++ )
relation[*it][str[k+1]] = '>';
}
if ( k > str.length()-2 ) continue;
if ( !isupper(str[k]) && !isupper(str[k+2]) && isupper(str[k+1]) )
relation[str[k]][str[k+2]] = '=';
}
}
}
for ( unsigned i = 0 ; i < VT.size()*5 ; i++ )
{
printf ("-");
}
printf ( "算符优先关系表" );
for ( unsigned i = 0 ; i < VT.size()*5 ; i++ )
{
printf ( "-" );
}
puts("");
printf ( "|%8s|" , "" );
for ( unsigned i = 0 ; i < VT.size() ; i++ )
{
printf ( "%5c%5s" , VT[i] , "|" );
}
puts ("");
for ( unsigned i = 0 ; i < (VT.size()+1)*10 ; i++ )
{
printf ( "-" );
}
puts("");
for ( unsigned i = 0 ; i < VT.size() ; i++ )
{
printf ( "|%4c%5s" , VT[i] , "|");
for ( unsigned j = 0 ; j < VT.size() ; j++ )
{
printf ( "%5c%5s" , relation[VT[i]][VT[j]] , "|" );
}
puts ("");
for ( unsigned i = 0 ; i < (VT.size()+1)*10 ; i++ )
{
printf ( "-" );
}
puts("");
}
}
int main ( )
{
int n;
char s[MAX];
cout<<"产生式的条数n=";
while ( ~scanf ( "%d" , &n ) )
{
memset ( used , 0 , sizeof ( used ) );
cout<<"产生式:"<<endl;
for ( int i = 0 ; i < n ; i++ )
{
scanf ( "%s" , s );
int len = strlen(s);//每条产生式的长度
int j;
for ( j = 0 ; j < len ; j++ )
{
if ( s[j] == '-' )
break;
}
s[j] = 0;//-替换成\0,以便截断产生式的左右部分
//如果不存在这个非终结符,则会VN_dic中插入,对应的value为0
if ( !VN_dic[s] )
{
VN_set.push_back ( WF(s) );//放入VN_set中
VN_dic[s] = VN_set.size();//设置s的value当前元素个数
}
int x = VN_dic[s]-1;//获取这个产生式的下标
VN_set[x].insert ( s+j+2 );//s+j+2为产生式右部的起始地址
for ( int k = j+2 ; k < len; k++ )
{
if ( !isupper(s[k] ) )
{
if ( used[s[k]] )
continue;
VT.push_back ( s[k] );//把终结符放入终结符数组中
used[s[k]] = VT.size();//这个VT对应的位置,从1开始
}
}
}
puts ("************VT集*******************");
for ( unsigned i = 0 ; i < VT.size() ; i++ )
{
printf ( "%c " , VT[i] );
}
puts ("");
puts("*************产生式*****************");
for ( unsigned i = 0 ; i < VN_set.size() ; i++ )
{
VN_set[i].print();
}
puts("************************************");
make_first();
make_last();
make_table();
}
}
4、实验结果