编译原理上机作业3——算符优先算法

来源:互联网 发布:域名转出交费费用 编辑:程序博客网 时间:2024/05/17 08:25
#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--;}}elsebreak;}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;elsefind = 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];elseprintf( "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 setfor( 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 setprintf( "\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;}