#include <bits/stdc++.h>
#define FOR(i,s,t) for(int i=(s);i<=(t);i++)
#define ROF(i,s,t) for(int i=(s);i>=(t);i--)
#define pb push_back
#define mp make_pair
#define eb emplace_back
#define fi first
#define se second
#define endl '\n'
const int MAX = 500 + 1;
using namespace std;
struct TSET{
public:
string left;
vector<string> right;
TSET ( const string& str ){left = str;}
void insert ( char str[] ){right.pb(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 rlt[MAX][MAX];
vector<char> VT;
vector<TSET> VNset;
map<string,int> VNdic;
set<char> FIRSTVT[MAX], LASTVT[MAX];
int used[MAX], vis[MAX];
bool IsVN(char c){
return isupper(c);
}
void dfs ( int x ) { //深度优先搜索
if ( vis[x] ) return;
vis[x] = 1;
auto left = VNset[x].left;
FOR(i,0,(int)VNset[x].right.size()-1){
auto str = VNset[x].right[i];
if ( IsVN(str[0]) ) {
int y = VNdic[str.substr(0,1)]-1;
if ( str.length() > 1 && !IsVN(str[1] ) )
FIRSTVT[x].insert ( str[1] );
dfs ( y );
for (auto _ : FIRSTVT[y])FIRSTVT[x].insert(_);
}
else FIRSTVT[x].insert ( str[0] );
}
}
void make_FIRSTVT ( ){
memset ( vis , 0 , sizeof ( vis ) );
//for ( int i = 0 ; i < VNset.size() ; i++ )
FOR(i,0,(int)VNset.size()-1)
if ( vis[i] ) continue;
else dfs ( i );
#define DEBUG
#ifdef DEBUG
puts("------------FIRSTVTVT集-------------------");
for ( int i = 0 ; i < VNset.size() ; i++ )
{
printf ( "%s : " , VNset[i].left.c_str() );
set<char>::iterator it = FIRSTVT[i].begin();
for ( ; it!= FIRSTVT[i].end() ; it++ )
printf ( "%c " , *it );
puts ("" );
}
#endif
}
void dfs1 ( int x ){ //深度优先搜索
if ( vis[x] ) return;
vis[x] = 1;
auto left = VNset[x].left;
FOR(i, 0, (int)VNset[x].right.size()-1){
auto str = VNset[x].right[i];
int n = str.length() -1;
if ( IsVN(str[n] ) ){
int y = VNdic[str.substr(n,1)]-1;
if ( str.length() > 1 && !IsVN(str[n-1]) )
LASTVT[x].insert ( str[1] );
dfs1 ( y );
for (auto _:LASTVT[y]) LASTVT[x].insert(_);
}
else
LASTVT[x].insert ( str[n] );
}
}
void make_LASTVT ( ){
memset ( vis , 0 , sizeof ( vis ) );
for ( int i = 0 ; i < VNset.size() ; i++ )
if ( vis[i] ) continue;
else dfs1 ( i );
#define DEBUG
#ifdef DEBUG
puts("--------------LASTVTVT集---------------------");
for ( int i = 0 ; i < VNset.size() ; i++ )
{
printf ( "%s : " , VNset[i].left.c_str() );
set<char>::iterator it = LASTVT[i].begin();
for ( ; it!= LASTVT[i].end() ; it++ )
printf ( "%c " , *it );
puts ("" );
}
#endif
}
void make_table ( ){ //构造分析表
FOR(i,0,MAX-1)FOR(j,0,MAX-1) rlt[i][j] = ' ';
FOR(i, 0,(int)VNset.size()-1)
FOR(j, 0,(int)VNset[i].right.size()-1){
auto str = VNset[i].right[j];
FOR(k, 0, (int)str.length()-1){
if ( !IsVN(str[k]) && !IsVN(str[k+1]) )
rlt[str[k]][str[k+1]] = '=';
if ( !IsVN(str[k]) && IsVN(str[k+1]) ){
int x = VNdic[str.substr(k+1,1)]-1;
for (auto _:FIRSTVT[x]) rlt[str[k]][_] = '<';
}
if ( IsVN(str[k]) && !IsVN(str[k+1]) ){
int x = VNdic[str.substr(k,1)]-1;
for (auto _:LASTVT[x]) rlt[_][str[k+1]] = '>';
}
if ( k > str.length()-2 ) continue;
if ( !IsVN(str[k]) && !IsVN(str[k+2]) && IsVN(str[k+1]) )
rlt[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" , rlt[VT[i]][VT[j]] , "|" );
puts ("");
for ( int i = 0 ; i < (VT.size()+1)*10 ; i++ )
printf ("-");
puts("");
}
#endif
}
int fa[MAX];
/************************并查集**********************/
int _find ( int x ) { //并查集查询,路径压缩
return x==fa[x]?x:fa[x] = _find ( fa[x] );
}
bool judge ( char x , char y ){ //判断两个是否再同一个集合
if ( _find ( x ) == _find ( y ) ) return true;
return false;
}
void _union ( char x , char y ){ //合并两个集合
x = _find(x); y = _find(y);
fa[x] = y;
}
void print ( string s1 , string s2 , string s3 , string s4 , string s5 , string s6 ){
printf ( "%s\t|%-15s%-15s%-15s%-15s%-15s\n" , s1.c_str(), s2.c_str(), s3.c_str() ,s4.c_str(),s5.c_str() , s6.c_str() );
}
void init ( )
{
FOR(i,0,MAX-1) fa[i] = i; //并查集的初始化,首先将每一个元素独立分在一个集合中
FOR(i, 0, (int)VNset.size() -1) {
auto left = VNset[i].left;
FOR(j, 0, (int)VNset[i].right.size() - 1){
auto str = VNset[i].right[j];
if ( left.length() == 1 && str.length() == 1 ) _union ( left[0] , str[0] );
}
}
print("步骤","栈","优先关系","当前符号","剩余符号","动作");
}
string get_stk ( vector<char>& stk ){
string ret = "";
for ( int i = 0 ; i < stk.size() ; i++ ) ret += stk[i];
return ret;
}
bool check ( const string& str1 , const string& str2 ){
if ( str1.length() != str2.length() ) return false;
FOR(i, 0,(int)str1.length()-1)
if ( IsVN(str1[i]) ){
if ( !judge(str1[i],str2[i])) return false;
}
else{
if ( str1[i] != str2[i] ) return false;
}
return true;
}
string reduction ( string src ){
FOR(i, 0, (int)VNset.size()-1) FOR(j, 0, (int)VNset[i].right.size()-1)
if ( check ( VNset[i].right[j] , src ) ){
return VNset[i].left;
}
return "";
}
void move_reduction ( string src ){
init ();
vector<char> stk;
int steps= 1;
src += "#";
stk.pb ( '#' );
FOR (i, 0, (int)src.length()-1){
char top = stk[stk.size()-1];
ROF(j, (int)stk.size()-1, 0)
if ( IsVN(stk[j]) ) continue;
else{
top = stk[j];
break;
}
char ch = rlt[top][src[i]];
string temp ="";
if ( ch == '<' || ch == '=' ){ //如果在分析表中是‘<’ 或者是‘=’,则‘移进’
if ( i == src.length() - 1 ){
printf("%d", steps);
print (temp, get_stk( stk ) , temp+ch , temp+src[i] , "" , "移进" );
}
else{
printf("%d", steps);
print ( temp , get_stk( stk ) , temp+ch , temp+src[i] , src.substr(i+1,src.length()-i-1) , "移进" );
}
stk.pb ( src[i] );
}
else{ //如果出现‘>’ 则‘规约’
string temp ="";
string str ="";
int x = stk.size()-2;
if ( i == src.length() ){
printf("%d", steps);
print ( temp , get_stk(stk) , temp+ch , temp + src[i] , "" , "归约" );
}
else{
printf("%d", steps);
print ( temp , get_stk(stk) , temp+ch , temp + src[i] , src.substr(i+1,src.length()-i-1) , "归约" );
}
while (1) {
if ( x == 0 ) break;
if ( !IsVN(stk[x] ) && rlt[stk[x]][top] == '<' )
break;
x--;
}
ROF(j, (int)stk.size()-1, x + 1) {
str += stk[j];
stk.pop_back();
}
//cout << str << endl;
reverse(str.begin(), str.end());
str = reduction(str);
//str = "N";
FOR(j, 0, (int)str.length() - 1)
stk.pb ( str[j] );
i--;
}
steps++;
}
}
int main ( ){
int n;
char s[MAX];
printf("请输入文法:\n");
scanf ( "%d" , &n );
memset ( used , 0 , sizeof ( used ) );
FOR(i, 0, n - 1) {
scanf ( "%s" , s );
int len = strlen(s), j = 0;
for (; j < len ; j++ )
if ( s[j] == '-' )
break;
s[j] = 0;
if ( !VNdic[s] ){
VNset.pb ( TSET(s) );
VNdic[s] = VNset.size();
}
int x = VNdic[s]-1;
VNset[x].insert ( s+j+2 );
FOR(k , 0, j - 1)
if ( !IsVN(s[k] ) ){
if ( used[s[k]] ) continue;
used[s[k]] = 1;
VT.pb ( s[k] );
}
FOR(k, j + 2, len - 1)
if ( !IsVN(s[k] ) ) {
if ( used[s[k]] ) continue;
VT.pb ( 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 < VNset.size() ; i++ )
VNset[i].print();
puts("************************************");
#endif
make_FIRSTVT();
make_LASTVT();
make_table();
string teststr;
printf("请输入代分析串:\n");
cin >> teststr;
move_reduction(teststr);
}
/*
11
S->#E#
E->E+T
E->E-T
E->T
T->T*F
T->T/F
T->F
F->P^F
F->P
P->(E)
P->i
9
S->#E#
E->E@T
E->T
T->T&F
T->F
F->P^F
F->P
P->(E)
P->i
*/