編譯原理上機作業2——LL(1)語法分析
阿新 • • 發佈:2019-02-08
#include <stdio.h> #include <string.h> #include <stdlib.h> #include <iostream> char grammer[200][200]; char terSymbol[200]; char nterSymbol[200]; int firstSET[100][100]; int followSET[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 ) { if( local_terminal(ch) != -1 ) return false; else { if(firstSET[local_nterminal(ch)][vtnum-1] == 1) return true; else return false; } } bool have_first( int k ) { for( int i = 0; i < vtnum; i++ ) if( firstSET[k][i] == 1 ) return true; return false; } void addfirstSet( char ch, char X ) { int X_num = local_nterminal(X); if( local_terminal(ch) != -1 ) firstSET[X_num][local_terminal(ch)] = 1; else { int ch_num = local_nterminal(ch); for( int i = 0; i < vtnum; i++ ) if( firstSET[ch_num][i] == 1 ) firstSET[X_num][i] = 1; } } void first( char X ) { int p; 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 ) { addfirstSet( grammer[i][p], X ); break; } else { if(!have_first(local_nterminal(grammer[i][p]))) first( grammer[i][p] ); addfirstSet( grammer[i][p], X ); if( canbe_empty(grammer[i][p]) ) p++; else break; } } } } } bool have_follow( char ch ) { int j = local_nterminal(ch); for( int i = 0; i < vtnum; i++ ) if( followSET[j][i] == 1 ) return true; return false; } void addfollowSet( char ch, char X, int kind ) { int j, k; int X_num = local_nterminal(X); if( kind == 1 ) // add firstSET { if( (j = local_terminal(ch)) != -1 ) followSET[X_num][j] = 1; else { k = local_nterminal(ch); for( int i = 0; i < vtnum; i++ ) if( firstSET[k][i] == 1 ) followSET[X_num][i] = 1; } } else if( kind == 0 ) // add followSET { j = local_nterminal(ch); for( int i = 0; i <= vtnum; i++ ) if( followSET[j][i] == 1 ) followSET[X_num][i] = 1; } else printf( "wrong" ); } void follow( char X ) { int p; // add # to S followSET[0][vtnum-1] = 1; for( int i = 0; i < pronum; i++ ) { p = 3; while( grammer[i][p] !='\0' && grammer[i][p] != X ) p++; if( grammer[i][p] == X ) { p++; if( grammer[i][p] == '\0' ) { if( !have_follow(grammer[i][0]) ) follow( grammer[i][0] ); addfollowSet( grammer[i][0], X, 0); } else { while(canbe_empty(grammer[i][p]) && grammer[i][p]!='\0') { addfollowSet( grammer[i][p], X, 1 );//add first set but first can_empty if(!have_follow(grammer[i][0])&&grammer[i][0]!=X) follow( grammer[i][0] ); addfollowSet( grammer[i][0], X, 0 ); //add follow set p++; } if( !canbe_empty(grammer[i][p]) )//first no-empty addfollowSet( grammer[i][p], X, 1 ); // add first set } } } } void create_table() { for( int i = 0; i < vnnum; i++ ) for( int j = 0; j < vtnum; j++ ) M[i][j] = -1; for( int i = 0; i < pronum; i++ ) { int S = local_nterminal( grammer[i][0] ); int t = local_terminal( grammer[i][3] ); if( grammer[i][3] != '$' ) { for( int j = 0; j < vtnum; j++ ) { if( t != -1 ) { if(M[S][j] == -1 && grammer[i][3] == terSymbol[j]) M[S][j] = i; } else { int B = local_nterminal(grammer[i][3]); if( M[S][j] == -1 && firstSET[B][j] == 1) M[S][j] = i; } } } if( canbe_empty(grammer[i][0]) ) { for( int t = 0; t < vtnum; t++ ) if( followSET[S][t] == 1 ) M[S][t] = i; } } for( int i = 0; i < vnnum; i++ ) { for( int j = 0; j < vtnum; j++ ) { if( M[i][j] == -1 ) printf( " "); else printf( " %s", grammer[M[i][j]] ); } printf( "\n" ); } } int is_terminal( char X ) { for( int i = 0; i < vtnum; i++ ) { if( X == terSymbol[i] ) return 1; } return 0; } int control() { char stack[1000]; int top = 0; char input[200]; printf( "input the secentences:\n" ); scanf( "%s", input ); stack[top++] = '$'; stack[top++] = grammer[0][0]; char *p = input; while( 1 ) { char X = stack[top-1]; top--; if( is_terminal(X) && X != '$' ) { if( X == *p ) { p++;continue; } else { printf( "wrong 1\n" ); return 0; } } else { if( X == '$' ) { if( X == *p ) { printf( "end\n" ); return 1; } else { printf( "wrong!\n" ); return 0; } } else { int t; if( (t=M[local_nterminal(X)][local_terminal(*p)]) == -1 ) { printf( "wrong 3!\n" ); return 0; } else { if ( grammer[t][3] == '$' ) continue; else { for( int i = strlen(grammer[t])-1; i > 2; i-- ) stack[top++] = grammer[t][i]; } } } } } }; 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++ ) { firstSET[i][j] = 0; followSET[i][j] = 0; } for( int i = 0; i < vnnum; i++ ) first( nterSymbol[i] ); //print the firset set for( int i = 0; i < vnnum; i++ ) { for( int j = 0; j < vtnum; j++ ) printf( "%d ", firstSET[i][j] ); printf( "\n" ); } for( int i = 0; i < vnnum; i++ ) follow( nterSymbol[i] ); //print the follow set printf( "\n\n\n" ); for( int i = 0; i < vnnum; i++ ) { for( int j = 0; j < vtnum; j++ ) printf( "%d ", followSET[i][j] ); printf( "\n" ); } create_table(); if( control() ) printf( "success, this wenfa is true!!!\n\n" ); else printf( "this wenfa is false!!\n\n" ); return 0; }
輸入檔案
a^(),$
STB
S->a
S->^
S->(T)
T->SB
B->,SB
B->$
#
(a,a)$