算符优先文法语法分析

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、实验结果

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值