#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char grammer[200][200];
char terSymbol[200];
char nterSymbol[200];
int firstVT[100][100];
int lastVT[100][100];
int vtnum, vnnum, pronum;
int M[200][200];
int local_terminal( char ch )
{
for( int i = 0; i < vtnum; i++ )
if( ch == terSymbol[i] )
return i;
return -1;
}
int local_nterminal( char ch )
{
for( int i = 0; i < vnnum; i++ )
if( ch == nterSymbol[i] )
return i;
return -1;
}
bool canbe_empty( char ch )
{
for( int i = 0; i < pronum; i++ )
{
if( grammer[i][0] == ch )
{
if( grammer[i][3] == '$' )
return true;
}
}
return false;
}
bool have_first( int k )
{
for( int i = 0; i < vtnum; i++ )
if( firstVT[k][i] == 1 )
return true;
return false;
}
bool have_last( int k )
{
for( int i = 0; i < vtnum; i++ )
if( lastVT[k][i] == 1 )
return true;
return false;
}
void addfirstvtSet( char ch, char X )
{
int X_num = local_nterminal(X);
if( local_terminal(ch) != -1 )
firstVT[X_num][local_terminal(ch)] = 1;
else
{
int ch_num = local_nterminal(ch);
for( int i = 0; i < vtnum; i++ )
if( firstVT[ch_num][i] == 1 )
firstVT[X_num][i] = 1;
}
}
void addlastvtSet( char ch, char X )
{
int X_num = local_nterminal(X);
if( local_terminal(ch) != -1 )
lastVT[X_num][local_terminal(ch)] = 1;
else
{
int ch_num = local_nterminal(ch);
for( int i = 0; i < vtnum; i++ )
if( lastVT[ch_num][i] == 1 )
lastVT[X_num][i] = 1;
}
}
void firstvt( char X )
{
int p, flag = 1;
for( int i = 0; i < pronum; i++ )
{
if( grammer[i][0] == X )
{
p = 3;
while( grammer[i][p] != '\0' )
{
if( local_terminal(grammer[i][p]) != -1 )
{
addfirstvtSet( grammer[i][p], X );
break;
}
else
{
do
{
if( grammer[i][p] != X )
{
flag = 1;
if(!have_first(local_nterminal(grammer[i][p])))
firstvt( grammer[i][p] );
addfirstvtSet( grammer[i][p], X );
if( canbe_empty(grammer[i][p]) )
{
flag = 0;
p++;
}
}
else
break;
}while( canbe_empty(grammer[i][p]) && grammer[i][p] != '\0' );
if( local_terminal(grammer[i][p+1]) != -1 && grammer[i][p+1] != '\0' && flag )
addfirstvtSet( grammer[i][p+1], X );
break;
}
}
}
}
}
void lastvt( char X )
{
int p, flag = 1;
for( int i = 0; i < pronum; i++ )
{
if( grammer[i][0] == X )
{
p = strlen(grammer[i])-1;
while( p != 2 )
{
if( local_terminal(grammer[i][p]) != -1 )
{
addlastvtSet( grammer[i][p], X );
break;
}
else
{
do
{
if( grammer[i][p] != X )
{
flag = 1;
if(!have_last(local_nterminal(grammer[i][p])))
lastvt( grammer[i][p] );
addlastvtSet( grammer[i][p], X );
if( canbe_empty(grammer[i][p]) )
{
flag = 0;
p--;
}
}
else
break;
}while( canbe_empty(grammer[i][p]) && p != 2 );
if( local_terminal(grammer[i][p-1]) != -1 && p != 2 && flag )
addlastvtSet( grammer[i][p-1], X );
break;
}
}
}
}
}
void print_table()
{
char x1 = '>';
char x2 = '<';
char x3 = '=';
printf( " " );
for( int i = 0; i < vtnum; i++ )
printf( "%c ", terSymbol[i] );
printf( "\n" );
for( int i = 0; i < vtnum; i++ )
{
printf( "%c ", terSymbol[i] );
for( int j = 0; j < vtnum; j++ )
{
if( M[i][j] == 1 )
printf( "%2c", x1 );
if( M[i][j] == 2 )
printf( "%2c", x2 );
if( M[i][j] == 3 )
printf( "%2c", x3 );
if( M[i][j] == -1)
printf( " " );
}
printf( "\n" );
}
printf( "\n\n" );
}
void create_table()
{
/* > means 1
* < means 2
* = means 3
*/
for( int i = 0; i < vtnum; i++ )
for( int j = 0; j < vtnum; j++ )
M[i][j] = -1;
for( int i = 0; i < vtnum; i++ )
{
M[i][vtnum-1] = 1;
M[vtnum-1][i] = 2;
}
M[vtnum-1][vtnum-1] = 3;
for( int i = 0; i < pronum; i++ )
{
int len = strlen(grammer[i]);
for( int j = 3; j < len-1; j++ )
{
int a1 = local_terminal(grammer[i][j]);
int b1 = local_terminal(grammer[i][j+1]);
int c1 = local_terminal(grammer[i][j+2]);
int a2 = local_nterminal(grammer[i][j]);
int b2 = local_nterminal(grammer[i][j+1]);
int c2 = local_nterminal(grammer[i][j+2]);
if( a1 != -1 && b1 != -1 )
{
M[a1][b1] = 3;
// print_table();
}
if( j <= len-2 && a1 != -1 && b1 == -1 && c1 != -1 )
{
M[a1][c1] = 3;
// print_table();
}
if( a1 != -1 && b1 == -1 )
{
for( int i = 0; i < vtnum; i++ )
{
if( firstVT[b2][i] )
M[a1][i] = 2;
}
// print_table();
}
if( a1 == -1 && b1 != -1 )
{
for( int i = 0; i < vtnum; i++ )
{
if( lastVT[a2][i] )
M[i][b1] = 1;
}
// print_table();
}
}
}
}
char prime( char * p )
{
char temp[100];
int flag, i, j, begin, end, begin_flag, end_flag;
begin = -1;
end = -1;
i = j = 0;
while( i < strlen(p) && j < strlen(p)-1 )
{
i = j;
while( local_terminal(*(p+i)) == -1 )
i++;
begin = local_terminal(*(p+i));
j = i+1;
while( local_terminal(*(p+j)) == -1 )
j++;
end = local_terminal(*(p+j));
if( M[begin][end] == 2 )
begin_flag = i+1;
if( M[begin][end] == 1 )
end_flag = j-1;
}
for( int i = begin_flag, j= 0; i <= end_flag; i++ )
{
temp[j++] = *(p+i);
temp[j] = '\0';
}
for( int i = 0; i < pronum; i++ )
{
char a[100];
flag = 0;
char *p = &grammer[i][3];
char *s = a;
while( (*s = *p) != '\0' )
{
s++;
p++;
}
if( !strcmp(a,temp) )
return grammer[i][0];
}
return -1;
}
void control()
{
/* This function had a little bug, but i don't wanna correct it */
char stack[200], input[100], save[100];
int top = 0, temp, j, find, flag;
stack[top++] = '$';
scanf( "%s", input );
for( int i = 0; i < strlen(input); i++ )
{
flag = 1;
int a = local_terminal(input[i]);
if( local_terminal(stack[top-1]) != -1 )
find = top-1;
else
find = top-2;
while( !(top ==2 && input[i] == '$') )
{
j = local_terminal(stack[find]);
if( M[j][a] == 1 ) // S[j] > a
{
do
{
find--;
if( local_terminal(stack[find]) == -1 )
find--;
}while( M[local_terminal(stack[find])][j] != 2 ); // S[j] < Q
// stack[find+1] ---- stack[top-1] guiyue top = find +1
int in = 0;
for( int t = find; t <= top-1; t++ )
save[in++] = stack[t];
save[in] = '$';
save[in+1] = '\0';
// printf( "%s", save );
top = find+1;
stack[top++] = prime( save );
// printf( "wrong" );
}
else
{
flag = 0;
if( M[j][a] == 2 || M[j][a] == 3 )
stack[top++] = input[i];
else
printf( "error" );
break;
}
}
if( flag )
printf( "success\n" );
}
}
int main()
{
pronum = 0;
char temp[100];
freopen( "1.txt", "r", stdin );
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);
printf( "please input the grammarElement\n" );
while( scanf( "%s", temp) && temp[0] != '#' )
strcpy(grammer[pronum++], temp );
for( int i = 0; i < 100; i++ )
for( int j = 0; j < 100; j++ )
{
firstVT[i][j] = 0;
lastVT[i][j] = 0;
}
for( int i = 0; i < vnnum; i++ )
firstvt( nterSymbol[i] );
//print the firset set
for( int i = 0; i < vnnum; i++ )
{
for( int j = 0; j < vtnum; j++ )
printf( "%d ", firstVT[i][j] );
printf( "\n" );
}
for( int i = 0; i < vnnum; i++ )
lastvt( nterSymbol[i] );
//print the last set
printf( "\n\n\n" );
for( int i = 0; i < vnnum; i++ )
{
for( int j = 0; j < vtnum; j++ )
printf( "%d ", lastVT[i][j] );
printf( "\n" );
}
create_table();
print_table();
control();
return 0;
}