編譯原理上機作業4——LR(0)分析的DFA生成

塵埃092發表於2013-12-09

input檔案

=*i
XSLR
X->S
S->L=R
S->R
L->*R
L->i
R->L
#

code

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>


#define INIT_LIST -1
#define HAVE_LIST 1
using namespace std;
typedef struct grammer
{
	char content[24];	// init value: "\0"
	int s_pos;			// init value: 3
	int s_len;			// init value: -1
}grammer;
typedef struct item
{
	int id;
	grammer gram[200];	// init value: see grammer
	int next[200];	//init value: all -1
	int num;
}item;

/*  global variable */					
item my_item[200];
item stand;
//queue<item> process;
item process[1000];
char terSymbol[200];
char nterSymbol[200];
char Symbol[400];
int vtnum, vnnum, vnum, id = 0;
int front = 0, rear = 0;

/* functions */
void closure( item & temp );
int is_nterminal( char ch );
int local( char x );
bool do_not_have( int x, item temp );
bool same( item a, item b[] /* b is my_item*/ );
void init( item temp[], int num );
void input();
void add_to_item( int yuan, int sym, item temp );
void add( int i, int j, item temp[], item current );
bool end( item temp );
int local( char x );
int is_nterminal( char ch );
void print_item( );
void next( item & temp );
bool can_closure( item temp );
bool cmp( item a, item b );


int main()
{
	freopen( "input.txt", "r", stdin );
	init( my_item, 200 );
	input();
	item ini;

	ini.id = 1;
	ini.num = 1;
	strcpy( ini.gram[0].content, my_item[0].gram[0].content );
	ini.gram[0].s_len = strlen( ini.gram[0].content);
	ini.gram[0].s_pos = 3;
	
	closure( ini );
	next( ini );
	id = 1;
	my_item[id] = ini;
	//add_to_item( my_item[id] );
//	process.push( ini );
	process[rear++] = ini;
	
	//don't forget :)
	my_item[0].id = 1;
//	while(!process.empty())
	while( front < rear )
 	{
 		/* the C++ STL pop() functions doesn't return a value
 			you need to use front() to r eturn a value
 			and use pop() to pop the top of the queue
 			make them happy :) */
    //	item current = process.front();
    //	process.pop();
		item current = process[front++];
		item temp[vnum];
		init( temp, vnum );
		for( int i = 0; i < vnum; i++ )
		{
			if( current.next[i] == HAVE_LIST )
			{
				for( int j = 0; j < current.num; j++ )
					add( i, j, temp, current );
				closure( temp[i] );
				next( temp[i] );
				if( same( temp[i], my_item ) )
				{
					my_item[id].next[i] = id;
				}
				else
				{
					add_to_item( current.id, i, temp[i]/*add to my_item[id]*/ );
					if( !end( temp[i] ) )
				//		process.push( temp[i] );
					//	process[rear++] = temp[i];
						process[rear++] = my_item[id-1];
				}
			}
		}
	}
	print_item();
}
void next( item & temp )
{
	for( int i = 0; i < temp.num; i++ )
	{
		if( temp.gram[i].s_pos < temp.gram[i].s_len )
			temp.next[local(temp.gram[i].content[temp.gram[i].s_pos])] = HAVE_LIST;
	}
}
void print_item( )
{
	for( int i = 0; i < id; i++ )
	{
		cout << my_item[i].id << endl;
		for( int j = 0; j < my_item[i].num; j++ )
		{
			cout << my_item[i].gram[j].content << "  ";
		}
		cout << endl;
		cout << "from:";
		for( int t = 0; t < vnum; t++ )
			cout << Symbol[t] << " ";
		cout << "    " << endl; 
		for( int t = 0; t < vnum; t++ )
			cout << my_item[i].next[t] << " ";
		cout << endl;
		cout << endl;
	}
}
bool end( item temp )
{
	for( int i = 0; i < temp.num; i++ )
	{
		if( temp.gram[i].s_pos < temp.gram[i].s_len )
			return false; 
	}
	return true;
}

void add_to_item( int yuan, int sym, item temp )
{
	/*  add temp to my_item set */
	int last = id++;
	my_item[last] = temp;
	my_item[last].id = id;
	
	/*  last my_item's point to the new my_item */
	my_item[yuan].next[sym] = id;
}
bool cmp( item a, item b )
{
	int flag = 0;
	for( int i = 0; i < a.num; i++ )
	{
		flag = 0;
		for( int j = 0; j < b.num; j++ )
		{
			if( !strcmp(a.gram[i].content, b.gram[j].content) )
			{
				flag = 1;
				break;
			}
		}
		if( flag != 1 )
			return false;
	}
	return true;
}
bool same( item a, item b[] /* b is my_item*/ )
{
	int flag;

	for( int x = 0; x <= id; x++ )
	{
		if( a.num == b[x].num )
		{
			if( cmp( a, b[x] ) )
				return true;
		}
	}
	return false;
}
void add( int i, int j, item temp[], item current )
{
	int s = current.gram[j].s_pos;
	int l = current.gram[j].s_len;
	if( current.gram[j].content[s] == Symbol[i] )
	{
		temp[i].gram[temp[i].num] = current.gram[j];
		temp[i].gram[temp[i].num].s_pos++;
		s = temp[i].gram[temp[i].num].s_pos;
		if( s < l )
			temp[i].next[local(temp[i].gram[temp[i].num].content[s])] = HAVE_LIST;
		temp[i].num++;
	}
}
bool can_closure( item temp )
{
	for( int i = 0; i < temp.num; i++ )
	{
		char s = temp.gram[i].content[temp.gram[i].s_pos];
		if( is_nterminal(s) )
			return true;
	}
	return false; 
}
void closure( item & temp )
{
	int f;
//	while( can_closure( temp ) )
//	{
		f++;
		for( int i = 0; i < temp.num; i++ )		// closure 
		{
			if(temp.gram[i].s_pos < temp.gram[i].s_len && is_nterminal(temp.gram[i].content[temp.gram[i].s_pos]) != -1 )		
			{
				char x = temp.gram[i].content[temp.gram[i].s_pos];
				if( is_nterminal(x) )
				{
					for( int h = 0; h < my_item[0].num; h++ )
					{
						if( my_item[0].gram[h].content[0] == x && do_not_have( h, temp ) )
						{
							strcpy( temp.gram[temp.num].content, my_item[0].gram[h].content );
							temp.gram[temp.num].s_pos = 3;
							temp.gram[temp.num].s_len = strlen( temp.gram[temp.num].content);
							temp.num++;	
							temp.next[local(x)] = HAVE_LIST;
						}
					}
				}
			}
		}  
//	}
}
bool do_not_have( int x, item temp )
{
	for( int i = 0; i < temp.num; i++ )
	{
		if( !strcmp( my_item[0].gram[x].content, temp.gram[i].content) 
			&& my_item[0].gram[x].s_pos == temp.gram[i].s_pos )
			return false;
	}
	return true; 
}
void init( item temp[], int num )
{
	for( int i = 0; i < num; i++ )
	{
		temp[i].id = -1;
		temp[i].num = 0;
		for( int j = 0; j < 200; j ++ )
		{
			temp[i].next[j] = -1;
			strcpy( temp[i].gram[j].content, "\0" );
			temp[i].gram[j].s_pos = 3;
			temp[i].gram[j].s_len = -1;
		}
	}
}
void input()
{
	char temp[30], i = 0;
	printf( "please input terminal-Symbol\n" );  
        scanf( "%s", terSymbol );  
    printf( "plaese input no-terminal-Symbol\n" );  
        scanf( "%s", nterSymbol );  
    vtnum = strlen( terSymbol );  
    vnnum = strlen( nterSymbol );
	 
	strcpy( Symbol, nterSymbol );
	strcat( Symbol, terSymbol );
	vnum = vtnum + vnnum;
	 
	printf( "please input the grammer(end with #):\n" );
	i = 0;
	while( scanf( "%s", temp ) && temp[0] != '#' )
	{
		strcpy( my_item[id].gram[i].content, temp );
		my_item[id].gram[i].s_len = strlen(temp);
		my_item[id].gram[i].s_pos = 3;
		i++;
	}
	my_item[id].num = i;
	
}
int local( char x )
{
	for( int i = 0; i < vnum; i++ )
		if( Symbol[i] == x )
			return i; 
	return -1;
}
int is_nterminal( char ch )
{
	for( int i = 0; i < vnnum; i++ )
		if( ch == nterSymbol[i] )
			return i;
	return -1;
}


相關文章