LL(1)文法

本文介绍了LL(1)分析法和算符优先分析法在编译原理实验中的应用。实验中,LL(1)分析法通过预测分析表实现了自上而下的语法分析,算符优先分析法则是自下而上的方法,定义了算符的优先关系。实验详细展示了两种方法的实现步骤,并给出了具体源代码及输入、输出示例。
摘要由CSDN通过智能技术生成

编译原理实验报告

LL(1)grammar:LL(1)分析法
operator precedence grammar算符优先分析法


一、LL(1)、OPG

LL(1)分析法:功能是利用LL(1)控制程序根据显示栈栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。

算符优先分析法:是一种简单直观、广泛使用、便于手工实现的自下而上的语法分析方法。定义算符之间的某种优先关系,寻找“归约串”,并进行归约。

二、LL(1)步骤

1.创建test2.txt

i+i*i#

2.源代码

代码如下:

 
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <iostream>
using namespace std;
struct Stack {
	char s[30];
	int top; //栈顶指针
}Stack;
char v1[6] = { 'i','+','*','(',')','#' };//终结符
char v2[5] = { 'E','G','T','S','F' };//非终结符
//预测分析表,用符号^来代替ε
char table[5][6][4] = { { "TG","","","","TG","" },
{ "","+TG","","","^","^" },
{ "FS","","","FS","","" },
{ "","^","*FS","","^","^" },
{ "i","","","(E)","","" } };
void push(char ch) {
	Stack.s[Stack.top] = ch;
	Stack.top++;
}
char pop() {
	Stack.top--;
	return Stack.s[Stack.top];
}
/**逆序进栈**/
void InversePush(int row, int line) {
	char temp[4];
	int i;
	for (i = 0; i < 4; i++) {
		if (table[row][line][i] != '\0')//字符串结束位是'\0'
			temp[i] = table[row][line][i];
		else {
			temp[i] = '\0';
			break;
		}
	}
	if (i == 0)
		return;
	cout << v2[row] << "->";
	for (int k = 0; k < i; k++) 
		cout << temp[k];
	cout << endl;
	for (i = i - 1; i >= 0; i--) {
		if (temp[i] != '^')	//^代表ε
			push(temp[i]);
	}
}
/**判断X是否为终结符**/
int IsTerminal(char X) {//若是则返回下标,非终结符返回-1
	for (int i = 0; i<6; i++) {
		if (X == v1[i])
			return i;
	}
	return -1;
}
/**查找预测表**/
bool FindTable(char X, char a) {//若为空白则出错,否则进栈
	int row;
	for (row = 0; row < 5; row++){
		if (X == v2[row])
			break;
	}
	if (row == 5)
		return false;
 
	int line = IsTerminal(a);
	if (line == -1)
		return false;
 
	if (table[row][line][0] == '\0')
		return false;
	else
		InversePush(row, line);	
	return true;
}
 
int  main()
{
	FILE *fp; 
	char a, X; 
	bool flag = true;
	char str[20]; 
	int len = 0;
//	if (() != NULL) {
//		printf("error opening.\n");
//		exit(1);
//	}
    fp = fopen("D:\\VS1\\code2\\compile\\ll1grammar\\test2.txt", "r");
    
	Stack.top = 0;
	push('#'); //栈底放一个’#’
	push('E');//放入文法开始符号
	a = fgetc(fp);
	str[len] = a;
	str[++len] = '\0';
    while (flag) {
		X = pop();
		if (X == '#') {
			if (a == '#') {
				cout << str << "是合法符号串" << endl;
                system("pause");
				return 0;
			}
		}
		else if ((IsTerminal(X)) != -1) {//栈顶是终结符
			if (a == X) {//栈顶和输入串第一个字符进行抵消
				a = fgetc(fp);
				str[len] = a;
				str[++len] = '\0';
			}
			else {
				flag = false;
			}
		}
		else if (!FindTable(X, a))
			flag = false;
	}
	cout << str << "是非法符号串" << endl;
    fclose(fp);
    fp = NULL;
    system("pause");
	return 0;
}
 

2.实验结果

在这里插入图片描述

三、OPG步骤

1.源代码

代码如下:

#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] = 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];
        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] );
            dfs1 ( y );
            set<char>::iterator it = last[y].begin();
            for ( ; it != last[y].end() ; it++ )
                last[x].insert ( *it );
        }
        else 
            last[x].insert ( str[n] );
    }
}
 
 
void make_last ( )
{
    memset ( vis , 0 , sizeof ( vis ) );
    for ( int i = 0 ; i < VN_set.size() ; i++ )
        if ( vis[i] ) continue;
        else dfs1 ( i );
#define DEBUG
#ifdef DEBUG
    puts("--------------LASTVT集---------------------");
    for ( int 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 ("" );
    }
#endif
}
 
void make_table ( )
{
    for ( int i = 0 ; i < MAX ; i++ )
        for ( int j = 0 ; j < MAX ; j++ )
            relation[i][j] = ' ';
    for ( int i = 0 ; i < VN_set.size() ; i++ )
        for ( int j = 0 ; j < VN_set[i].right.size() ; j++ )
        {
            string& str = VN_set[i].right[j];
            for ( int 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]] = '=';
            }
        }
#define DEBUG
#ifdef DEBUG
    for ( int i = 0 ; i < VT.size()*5 ; i++ )
        printf ("-");
    printf ( "算符优先关系表" );
    for ( int i = 0 ; i < VT.size()*5 ; i++ )
        printf ( "-" );
    puts("");
    printf ( "|%8s|" , "" );
    for ( int i = 0 ; i < VT.size() ; i++ )
        printf ( "%5c%5s" , VT[i] , "|" );
    puts ("");
    for ( int i = 0 ; i < (VT.size()+1)*10 ; i++ )
        printf ("-");
    puts("");
    for ( int i = 0 ; i < VT.size() ; i++ )
    {
        printf ( "|%4c%5s" , VT[i] , "|");
        for ( int j = 0 ; j < VT.size() ; j++ )
            printf ( "%5c%5s" , relation[VT[i]][VT[j]] , "|" );
        puts ("");
        for ( int i = 0 ; i < (VT.size()+1)*10 ; i++ )
            printf ("-");
        puts("");
    }
#endif
}
 
 
int main()
{
    int n;
    char s[MAX];
    while ( ~scanf ( "%d" , &n ) )
    {
        memset ( used , 0 , sizeof ( used ) );
        for ( int i = 0 ; i < n ; i++ )
        {
            scanf ( "%s" , s );
            int len = strlen(s),j;
            for ( j = 0 ; j < len ; j++ )
                if ( s[j] == '-' ) 
                    break;
            s[j] = 0;
            if ( !VN_dic[s] )
            {
                VN_set.push_back ( WF(s) );
                VN_dic[s] = VN_set.size();
            }
            int x = VN_dic[s]-1;
            VN_set[x].insert ( s+j+2 );
            for ( int k = 0 ; k < j; k++ )
                if ( !isupper(s[k] ) )
                {
                    if ( used[s[k]] ) continue;
                    used[s[k]] = 1;
                    VT.push_back ( s[k] );
                }
            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();
                }   
        }
#define DEBUG
#ifdef DEBUG
        puts ("************VT集*******************");
        for ( int i = 0 ; i < VT.size() ; i++ )
            printf ( "%c " , VT[i] );
        puts ("");
        puts("*************产生式*****************");
        for ( int i = 0 ; i < VN_set.size() ; i++ )
            VN_set[i].print();
        puts("************************************");
#endif
        make_first();
        make_last();
        make_table();
    }
    printf("按Ctrl+Z退出");
    system("pause");
}

2.输入:

5
S->a
S->^
S->(T)
T->T,S
T->S
在这里插入图片描述

3.实验结果

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值