1. 程式人生 > >編譯原理SLR(1)文法的C++實現(基於SLR(1)分析法的語法制導翻譯及中間程式碼生成程式設計原理與實現)

編譯原理SLR(1)文法的C++實現(基於SLR(1)分析法的語法制導翻譯及中間程式碼生成程式設計原理與實現)

程式功能描述

完成以下描述賦值語句 SLR(1)文法語法制導生成中間程式碼四元式的過程。
G[A]:
A→V=E
E→E+T∣E-T∣T
T→T*F∣T/F∣F
F→(E)∣i
V→i
[設計說明] 終結符號i為使用者定義的簡單變數,即識別符號的定義。
[設計要求]
(1)構造文法的SLR(1)分析表,設計語法制導翻譯過程,給出每一產生式對應的語義動作;
(2)設計中間程式碼四元式的結構;
(3)輸入串應是詞法分析的輸出二元式序列,即某賦值語句“專題1”的輸出結果,輸出為賦值語句的四元式序列中間檔案;
設計兩個測試用例(儘可能完備),並給出程式執行結果四元式序列。

 
主要資料結構描述
在實驗中主要使用結構體進行各類屬性的封裝。此外,還用到了stack和list的結構,其中stack主要由陣列進行簡易實現,便於輸出棧內內容;list使用C++ STL中的list進行動態的新增。以下對每一部分進行詳細說明。
此處使用sentence結構體對於專案集族中的每個產生式的屬性進行封裝。finish表示該產生式是否完成規約,即點操作是否進行完畢;tag即用來表示當前點的位置,因產生式包含有左部和->符號,故從3開始計數;string類的str用於儲存產生式的字串。
typedef struct
{
int finish = 0;  //是否結束
int tag = 3;  //當前圓點的位置
string str;
}sentence;
此處用act結構體對構造的ACTION表進行儲存。在實驗中,我並沒有使用二維陣列進行ACTION表的儲存,而是選用了一維的結構體:I代表輸入的目前的狀態,Vt代表輸入的終結符號,tag用於表示是r類還是s類,action用於記錄對應的r類的產生式標號或s類狀態標號。
typedef struct
{
int I;  //當前狀態
char Vt;  //終結符號
char tag;  //r||s
int action;  //動作
}act;
同上,此處使用結構體go對GOTO表進行儲存。I表示輸出的當前狀態,Vn表示輸入的非終結符,next_I表示GOTO的轉移結果,形如GOTO(I, Vn) = next_I。
typedef struct
{
int I;  //當前狀態
char Vn;  //非終結符
int next_I;  //轉移狀態
}go;
此處使用I進行構造專案集族時狀態的儲存。number對應於該專案的序號,如I0/I1等;l則為list<sentence>型別,用於儲存該狀態中的產生式。
typedef struct
{
int number;  //編號
list<sentence> l;
}I;  //狀態
此處使用siyuanshi進行四元式的儲存,形同四元式:(op, arg1, arg2, result)。在此不再贅述。
typedef struct
{
char op;
char arg1;
char arg2;
char result;
}siyuanshi;
此處使用var進行符號表的儲存。在構造四元式的過程中,需要對於上一次的操作中新生成的結果進行記錄,以便生成新的四元式時作為引數加入其中;故結構體中的name代表某一運算結果的變數名,如A/B/C/D;string類的value表示該變數對應的算術表示式(屬性)。
typedef struct
{
char name;
string value;  //place
}var;  //變數
以下是一些變數的定義。在這些過程中用到了大量的list:首先進行狀態集的定義,以list的形式對狀態進行儲存;之後是list-char的FIRST與FOLLOW集的定義;之後是list形式的ACTION表和GOTO表的定義,以及list-char的Vn/Vt集。最後,input用來儲存輸入串,在分析過程中也會使用input來主要進行分析。
list<I> DFA;  //狀態集
list<char> *First;  //FIRST集
list<char> *Follow;  //FOLLOW集
list<act> ACTION;  //ACTION[i][j]
list<go> GOTO;  //GO[i][j]
list<char> Vt;  //終結符號集
list<char> Vn;  //非終結符號集
char input[100];
下面是分析棧、符號棧以及其屬性棧的定義,分別儲存狀態號、符號以及其代表的屬性,並且設立棧頂指標。下面使用list結構進行四元式的儲存、記錄可以產生四元式的產生式標號以及變量表中變數的儲存。最後,在G[]陣列中,進行文法的定義。本實驗為自動造表,故此處可修改文法,僅作細微改動即可。
int S[100];  //分析棧
int S_top = 0;  //分析棧棧頂
char T[100];  //符號棧 棧頂與分析棧總相同
string value[100];  //儲存符號的屬性
list<siyuanshi> L_sys;  //四元式
list<int> sys;  //產生四元式的狀態集
list<var> V;  //變量表


int result_count = 0;
string G[11] = { "S->A", "A->V=E","E->E+T","E->E-T","E->T","T->T*F","T->T/F","T->F","F->(E)","F->i","V->i" };


程式結構描述:

整個程式較為龐大,自動構造文法分析所需的表,包括Vt/Vn/FIRST/FOLLOW/ACTION/ GOTO/變量表,之後進行SLR(1)分析,並且構造四元式。在這裡進行詳細說明:


完成整個程式的思路是:
->讀取檔案(獲取輸入的實驗一執行結果、得到表示式)
->掃描文法(構建終結符號、非終結符號集、First/Follow集)
->造表(構造專案集族、構造ACTION/GOTO、設定四元式)
->SLR分析(判斷是否可以被分析程式接受、生成四元式)


讀取檔案:readfile()將檔案中的實驗一的執行結果讀入,整合為字元陣列,準備好以待匹配,同前幾次試驗,在此不做贅述。


掃描文法:scan()將文法陣列G[]中的string字串進行掃描,構造終結符號集和非終結符號集;之後按照SLR(1)文法中FIRST集和FOLLOW集的構造方法進行這兩個集合的構造。在構造FIRST集時,用到了find函式,用來不斷地遞迴查詢產生式首符號為非終結符號的產生式,以構造FIRST集;在構造FOLLOW集時,使用到了findVn函式,用來返回指定的非終結符對應的標號,以進行FOLLOW集的計算。同時,通過不斷的迴圈、加入,當所有非終結符的FOLLOW集總大小不變時,跳出迴圈,構造完成。至此,造表前的準備工作全部完成,接下來進入造表階段。


造表:table()完成整個專案集族的生成以及ACTION/GOTO的構造,以及在造表過程中對於四元式的標註,也是個人認為整個程式中最難的部分。
首先,進行初始設定:新增文法的起始符號對應的產生式,用以從初態進行迭代;之後將該產生式(點還處在最開始的部位tag=3, 尚未進入規約狀態finish=0)加入第一個狀態I0中,接下來進行一波迴圈操作:首先對於當前所有的專案集族進行閉包操作,該功能被封裝在閉包函式closure()中(函式中對於每一個點操作的非終結符均進行閉包操作,加入該狀態中,最終返回經過閉包操作的該狀態);之後對於當前狀態的每一條待移進的產生式分別進行移進操作,並新增為新的狀態,等待迴圈到該狀態時的閉包操作。在移進過程中,對於不是規約的(即尚可移進的)產生式,若點操作為非終結符,置GOTO(當前狀態, 非終結符) = 新狀態號;若為終結符,則置ACTION(當前狀態,終結符號) = s+新狀態號。若存在移進時的相同符號,則加入同一狀態中,不再另設新狀態。之後即為對於新狀態的加入判斷:若新狀態的閉包操作closure()已經在已形成的專案集族中出現了,則不再新增這個新狀態,並且修改對應的ACTION或者GOTO(一個pop()操作+一個push()操作);否則新增。對於需要規約的產生式,首先對其進行判斷是否可以產生四元式:若可以,則進行記錄,以便之後判斷;否則不進行記錄。至此,造表結束,接下來正式進入分析階段。


SLR分析:SLR()完成最終整個SLR(1)文法的分析任務,也包括分析過程中完成的四元式構建。在分析過程起始時,首先將狀態I0壓入棧中,分析開始:若ACTION(棧頂,當前符號)不是acc(在程式中為r0),則開始迴圈:如果是err(在程式中使用0代替),報錯;否則如果是sj,狀態棧、符號棧、屬性棧均壓棧,讀取下一個符號;如果是ri,則通過需要規約第i條產生式,對於三個棧,執行第i條產生式右部的符號數次pop()操作,同時更新屬性棧,用以後續的四元式生成工作;在生成四元式時,首先判斷正在規約的產生式是否可以產生四元式,同時確定四元式的op,其次判斷兩個引數(arg1,arg2)是否為變數or變數組成的表示式。如果是表示式,則查詢之前的符號表,進行代替操作。若中間不報錯而跳出迴圈,則成功匹配。至此,按照事先約定好的輸出格式進行輸出,分析任務完成。


程式測試:
測試用例
在本程式中,使用檔案進行讀取表示式的操作。測試輸入串放在text.txt中,測試用例如下:


測試用例1:
12,<i>
32,<=>
12,<a>
23,<*>
28,<(>
12,<b>
21,<+>
12,<c>
29,<)>
33,</>
12,<d>
測試用例2:
12,<r>
32,<=>
28,<(>
12,<a>
21,<+>
12,<e>
29,<)>
33,</>
12,<b>
23,<*>
28,<(>
12,<c>
22,<->
12,<d>
29,<)>

測試結果

測試1:
讀入實驗一結果:
12,<i>
32,<=>
12,<a>
23,<*>
28,<(>
12,<b>
21,<+>
12,<c>
29,<)>
33,</>
12,<d>


輸入串為:i=a*(b+c)/d#


終結符號集:=+-*/()i#
非終結符號集:SAVETF
FIRST
S     i
A     i
V     i
E     ( i
T     ( i
F     ( i
FOLLOW
S     #
A     #
V     =
E     # + - )
T     # + - * / )
F     # + - * / )
狀態0:
  S->·A
  A->·V=E
  V->·i
狀態1:
  S->A·
狀態2:
  A->V·=E
狀態3:
  V->i·
狀態4:
  A->V=·E
  E->·E+T
  E->·E-T
  E->·T
  T->·T*F
  T->·T/F
  T->·F
  F->·(E)
  F->·i
狀態5:
  A->V=E·
  E->E·+T
  E->E·-T
狀態6:
  E->T·
  T->T·*F
  T->T·/F
狀態7:
  T->F·
狀態8:
  F->(·E)
  E->·E+T
  E->·E-T
  E->·T
  T->·T*F
  T->·T/F
  T->·F
  F->·(E)
  F->·i
狀態9:
  F->i·
狀態10:
  E->E+·T
  T->·T*F
  T->·T/F
  T->·F
  F->·(E)
  F->·i
狀態11:
  E->E-·T
  T->·T*F
  T->·T/F
  T->·F
  F->·(E)
  F->·i
狀態12:
  T->T*·F
  F->·(E)
  F->·i
狀態13:
  T->T/·F
  F->·(E)
  F->·i
狀態14:
  F->(E·)
  E->E·+T
  E->E·-T
狀態15:
  E->E+T·
  T->T·*F
  T->T·/F
狀態16:
  E->E-T·
  T->T·*F
  T->T·/F
狀態17:
  T->T*F·
狀態18:
  T->T/F·
狀態19:
  F->(E)·
GOTO(0, A) = 1
GOTO(0, V) = 2
GOTO(4, E) = 5
GOTO(4, T) = 6
GOTO(4, F) = 7
GOTO(8, E) = 14
GOTO(8, T) = 6
GOTO(8, F) = 7
GOTO(10, T) = 15
GOTO(10, F) = 7
GOTO(11, T) = 16
GOTO(11, F) = 7
GOTO(12, F) = 17
GOTO(13, F) = 18
ACTION(0, i) = s3
ACTION(1, #) = r0
ACTION(2, =) = s4
ACTION(3, =) = r10
ACTION(4, () = s8
ACTION(4, i) = s9
ACTION(5, #) = r1
ACTION(5, +) = s10
ACTION(5, -) = s11
ACTION(6, #) = r4
ACTION(6, +) = r4
ACTION(6, -) = r4
ACTION(6, )) = r4
ACTION(6, *) = s12
ACTION(6, /) = s13
ACTION(7, #) = r7
ACTION(7, +) = r7
ACTION(7, -) = r7
ACTION(7, *) = r7
ACTION(7, /) = r7
ACTION(7, )) = r7
ACTION(8, () = s8
ACTION(8, i) = s9
ACTION(9, #) = r9
ACTION(9, +) = r9
ACTION(9, -) = r9
ACTION(9, *) = r9
ACTION(9, /) = r9
ACTION(9, )) = r9
ACTION(10, () = s8
ACTION(10, i) = s9
ACTION(11, () = s8
ACTION(11, i) = s9
ACTION(12, () = s8
ACTION(12, i) = s9
ACTION(13, () = s8
ACTION(13, i) = s9
ACTION(14, )) = s19
ACTION(14, +) = s10
ACTION(14, -) = s11
ACTION(15, #) = r2
ACTION(15, +) = r2
ACTION(15, -) = r2
ACTION(15, )) = r2
ACTION(15, *) = s12
ACTION(15, /) = s13
ACTION(16, #) = r3
ACTION(16, +) = r3
ACTION(16, -) = r3
ACTION(16, )) = r3
ACTION(16, *) = s12
ACTION(16, /) = s13
ACTION(17, #) = r5
ACTION(17, +) = r5
ACTION(17, -) = r5
ACTION(17, *) = r5
ACTION(17, /) = r5
ACTION(17, )) = r5
ACTION(18, #) = r6
ACTION(18, +) = r6
ACTION(18, -) = r6
ACTION(18, *) = r6
ACTION(18, /) = r6
ACTION(18, )) = r6
ACTION(19, #) = r8
ACTION(19, +) = r8
ACTION(19, -) = r8
ACTION(19, *) = r8
ACTION(19, /) = r8
ACTION(19, )) = r8


分析棧:(| |中的為非終結符號的屬性)
0  3                                              i
0  2                                              V |i|
0  2  4                                           V |i| =
0  2  4  9                                        V |i| = a
0  2  4  7                                        V |i| = F |a|
0  2  4  6                                        V |i| = T |a|
0  2  4  6  12                                    V |i| = T |a| *
0  2  4  6  12 8                                  V |i| = T |a| * (
0  2  4  6  12 8  9                               V |i| = T |a| * ( b
0  2  4  6  12 8  7                               V |i| = T |a| * ( F |b|
0  2  4  6  12 8  6                               V |i| = T |a| * ( T |b|
0  2  4  6  12 8  14                              V |i| = T |a| * ( E |b|
0  2  4  6  12 8  14 10                           V |i| = T |a| * ( E |b| +
0  2  4  6  12 8  14 10 9                         V |i| = T |a| * ( E |b| + c
0  2  4  6  12 8  14 10 7                         V |i| = T |a| * ( E |b| + F |c|
0  2  4  6  12 8  14 10 15                        V |i| = T |a| * ( E |b| + T |c|
0  2  4  6  12 8  14                              V |i| = T |a| * ( E |b+c|
0  2  4  6  12 8  14 19                           V |i| = T |a| * ( E |b+c| )
0  2  4  6  12 17                                 V |i| = T |a| * F |b+c|
0  2  4  6                                        V |i| = T |a*b+c|
0  2  4  6  13                                    V |i| = T |a*b+c| /
0  2  4  6  13 9                                  V |i| = T |a*b+c| / d
0  2  4  6  13 18                                 V |i| = T |a*b+c| / F |d|
0  2  4  6                                        V |i| = T |a*b+c/d|
0  2  4  5                                        V |i| = E |a*b+c/d|
0  1                                              A |i=a*b+c/d|


匹配成功!


四元式:
(+,c,b,A)
(*,A,a,B)
(/,d,B,C)
請按任意鍵繼續. . .
測試用例2:

讀入實驗一結果:
12,<r>
32,<=>
28,<(>
12,<a>
21,<+>
12,<e>
29,<)>
33,</>
12,<b>
23,<*>
28,<(>
12,<c>
22,<->
12,<d>
29,<)>




輸入串為:r=(a+e)/b*(c-d)#


終結符號集:=+-*/()i#
非終結符號集:SAVETF
FIRST
S     i
A     i
V     i
E     ( i
T     ( i
F     ( i
FOLLOW
S     #
A     #
V     =
E     # + - )
T     # + - * / )
F     # + - * / )
狀態0:
  S->·A
  A->·V=E
  V->·i
狀態1:
  S->A·
狀態2:
  A->V·=E
狀態3:
  V->i·
狀態4:
  A->V=·E
  E->·E+T
  E->·E-T
  E->·T
  T->·T*F
  T->·T/F
  T->·F
  F->·(E)
  F->·i
狀態5:
  A->V=E·
  E->E·+T
  E->E·-T
狀態6:
  E->T·
  T->T·*F
  T->T·/F
狀態7:
  T->F·
狀態8:
  F->(·E)
  E->·E+T
  E->·E-T
  E->·T
  T->·T*F
  T->·T/F
  T->·F
  F->·(E)
  F->·i
狀態9:
  F->i·
狀態10:
  E->E+·T
  T->·T*F
  T->·T/F
  T->·F
  F->·(E)
  F->·i
狀態11:
  E->E-·T
  T->·T*F
  T->·T/F
  T->·F
  F->·(E)
  F->·i
狀態12:
  T->T*·F
  F->·(E)
  F->·i
狀態13:
  T->T/·F
  F->·(E)
  F->·i
狀態14:
  F->(E·)
  E->E·+T
  E->E·-T
狀態15:
  E->E+T·
  T->T·*F
  T->T·/F
狀態16:
  E->E-T·
  T->T·*F
  T->T·/F
狀態17:
  T->T*F·
狀態18:
  T->T/F·
狀態19:
  F->(E)·
GOTO(0, A) = 1
GOTO(0, V) = 2
GOTO(4, E) = 5
GOTO(4, T) = 6
GOTO(4, F) = 7
GOTO(8, E) = 14
GOTO(8, T) = 6
GOTO(8, F) = 7
GOTO(10, T) = 15
GOTO(10, F) = 7
GOTO(11, T) = 16
GOTO(11, F) = 7
GOTO(12, F) = 17
GOTO(13, F) = 18
ACTION(0, i) = s3
ACTION(1, #) = r0
ACTION(2, =) = s4
ACTION(3, =) = r10
ACTION(4, () = s8
ACTION(4, i) = s9
ACTION(5, #) = r1
ACTION(5, +) = s10
ACTION(5, -) = s11
ACTION(6, #) = r4
ACTION(6, +) = r4
ACTION(6, -) = r4
ACTION(6, )) = r4
ACTION(6, *) = s12
ACTION(6, /) = s13
ACTION(7, #) = r7
ACTION(7, +) = r7
ACTION(7, -) = r7
ACTION(7, *) = r7
ACTION(7, /) = r7
ACTION(7, )) = r7
ACTION(8, () = s8
ACTION(8, i) = s9
ACTION(9, #) = r9
ACTION(9, +) = r9
ACTION(9, -) = r9
ACTION(9, *) = r9
ACTION(9, /) = r9
ACTION(9, )) = r9
ACTION(10, () = s8
ACTION(10, i) = s9
ACTION(11, () = s8
ACTION(11, i) = s9
ACTION(12, () = s8
ACTION(12, i) = s9
ACTION(13, () = s8
ACTION(13, i) = s9
ACTION(14, )) = s19
ACTION(14, +) = s10
ACTION(14, -) = s11
ACTION(15, #) = r2
ACTION(15, +) = r2
ACTION(15, -) = r2
ACTION(15, )) = r2
ACTION(15, *) = s12
ACTION(15, /) = s13
ACTION(16, #) = r3
ACTION(16, +) = r3
ACTION(16, -) = r3
ACTION(16, )) = r3
ACTION(16, *) = s12
ACTION(16, /) = s13
ACTION(17, #) = r5
ACTION(17, +) = r5
ACTION(17, -) = r5
ACTION(17, *) = r5
ACTION(17, /) = r5
ACTION(17, )) = r5
ACTION(18, #) = r6
ACTION(18, +) = r6
ACTION(18, -) = r6
ACTION(18, *) = r6
ACTION(18, /) = r6
ACTION(18, )) = r6
ACTION(19, #) = r8
ACTION(19, +) = r8
ACTION(19, -) = r8
ACTION(19, *) = r8
ACTION(19, /) = r8
ACTION(19, )) = r8


分析棧:(| |中的為非終結符號的屬性)
0  3                                              r
0  2                                              V |r|
0  2  4                                           V |r| =
0  2  4  8                                        V |r| = (
0  2  4  8  9                                     V |r| = ( a
0  2  4  8  7                                     V |r| = ( F |a|
0  2  4  8  6                                     V |r| = ( T |a|
0  2  4  8  14                                    V |r| = ( E |a|
0  2  4  8  14 10                                 V |r| = ( E |a| +
0  2  4  8  14 10 9                               V |r| = ( E |a| + e
0  2  4  8  14 10 7                               V |r| = ( E |a| + F |e|
0  2  4  8  14 10 15                              V |r| = ( E |a| + T |e|
0  2  4  8  14                                    V |r| = ( E |a+e|
0  2  4  8  14 19                                 V |r| = ( E |a+e| )
0  2  4  7                                        V |r| = F |a+e|
0  2  4  6                                        V |r| = T |a+e|
0  2  4  6  13                                    V |r| = T |a+e| /
0  2  4  6  13 9                                  V |r| = T |a+e| / b
0  2  4  6  13 18                                 V |r| = T |a+e| / F |b|
0  2  4  6                                        V |r| = T |a+e/b|
0  2  4  6  12                                    V |r| = T |a+e/b| *
0  2  4  6  12 8                                  V |r| = T |a+e/b| * (
0  2  4  6  12 8  9                               V |r| = T |a+e/b| * ( c
0  2  4  6  12 8  7                               V |r| = T |a+e/b| * ( F |c|
0  2  4  6  12 8  6                               V |r| = T |a+e/b| * ( T |c|
0  2  4  6  12 8  14                              V |r| = T |a+e/b| * ( E |c|
0  2  4  6  12 8  14 11                           V |r| = T |a+e/b| * ( E |c| -
0  2  4  6  12 8  14 11 9                         V |r| = T |a+e/b| * ( E |c| - d
0  2  4  6  12 8  14 11 7                         V |r| = T |a+e/b| * ( E |c| - F |d|
0  2  4  6  12 8  14 11 16                        V |r| = T |a+e/b| * ( E |c| - T |d|
0  2  4  6  12 8  14                              V |r| = T |a+e/b| * ( E |c-d|
0  2  4  6  12 8  14 19                           V |r| = T |a+e/b| * ( E |c-d| )
0  2  4  6  12 17                                 V |r| = T |a+e/b| * F |c-d|
0  2  4  6                                        V |r| = T |a+e/b*c-d|
0  2  4  5                                        V |r| = E |a+e/b*c-d|
0  1                                              A |r=a+e/b*c-d|


匹配成功!


四元式:
(+,e,a,A)
(/,b,A,B)
(-,d,c,C)
(*,C,B,D)
請按任意鍵繼續. . .

學習總結:
起初,只是想動手做一個手動造表的SLR程式。後來在實際操作的過程中,聽說這次實驗比較難,涉及到分析過程、還包括四元式,就有些覺得不是那麼容易。不過,後來還是鐵了心,想完成一個自動造表的程式,從開始到結尾沒有人為設定的表和其他設定。剛開始做的時候還是比較不太舒服,畢竟規則還沒有掌握清楚,開始上手做時還是不太順利的。到後來慢慢了解整個演算法的原理,再到後來不去翻書也大概明白整個演算法是怎麼回事,主動去迎接一個不是那麼輕鬆就可以完成的實驗...個人感覺收穫還是很大的。目前實驗的不足是部分輸出還不是很規範(不包括在字元介面還是對齊的棧到了word裡面不知道為什麼就不齊了),還有提升空間。


附:完整實現程式碼(詳見.cpp檔案)
/*
完成以下描述賦值語句 SLR(1)文法語法制導生成中間程式碼四元式的過程。
G[A]:
A→V=E
E→E+T∣E-T∣T
T→T*F∣T/F∣F
F→(E)∣i
V→i
[設計說明] 終結符號 i 為使用者定義的簡單變數, 即識別符號的定義。
[設計要求]
(1)構造文法的 SLR(1)分析表,設計語法制導翻譯過程,給出每一產生式對應的語義動作;
(2)設計中間程式碼四元式的結構;
(3)輸入串應是詞法分析的輸出二元式序列,即某賦值語句“專題 1”的輸出結果,
輸出為賦值語句的四元式序列中間檔案;
(4)設計兩個測試用例(儘可能完備),並給出程式執行結果四元式序列。
*/
#include "stdafx.h"
#include <string>
#include <list>
#include <stack>
#include <iostream>


using namespace std;


typedef struct
{
	int finish = 0;  //是否結束
	int tag = 3;  //當前圓點的位置
	string str;
}sentence;


typedef struct
{
	int I;  //當前狀態
	char Vt;  //終結符號
	char tag;  //r||s
	int action;  //動作
}act;


typedef struct
{
	int I;  //當前狀態
	char Vn;  //非終結符
	int next_I;  //轉移狀態
}go;


typedef struct
{
	int number;  //編號
	list<sentence> l;
}I;  //狀態


typedef struct
{
	char op;
	char arg1;
	char arg2;
	char result;
}siyuanshi;


typedef struct
{
	char name;
	string value;  //place
}var;  //變數


list<I> DFA;  //狀態集
list<char> *First;  //FIRST集
list<char> *Follow;  //FOLLOW集
list<act> ACTION;  //ACTION[i][j]
list<go> GOTO;  //GO[i][j]
list<char> Vt;  //終結符號集
list<char> Vn;  //非終結符號集


char input[100];// = { 'i','=','a','*','(','b','+','c',')','/','d','#' };


void readfile()
{
	cout << "讀入實驗一結果:" << endl;
	char read[10];  //讀取檔案
	FILE *fp;
	fp = fopen("text.txt", "r+");
	int num = 0;
	while (fgets(read, 10, fp) != NULL)
	{
		int i;
		cout<<read;
		for (i = 0; i < 10; i++)	
			if (read[i] == ',')
			{
				break;
			}
		input[num] = read[i + 2];
		num++;
	}
	cout << endl;
	input[num] = '#';
	cout << endl << "輸入串為:" << input << endl << endl;
}


int S[100];  //分析棧
int S_top = 0;  //分析棧棧頂
char T[100];  //符號棧 棧頂與分析棧總相同
string value[100];  //儲存符號的屬性
list<siyuanshi> L_sys;  //四元式
list<int> sys;  //產生四元式的狀態集
list<var> V;  //變量表


int result_count = 0;
string G[11] = { "S->A", "A->V=E","E->E+T","E->E-T","E->T","T->T*F","T->T/F","T->F","F->(E)","F->i","V->i" };


act getACTION(int i,char b)
{
	char c = b;
	if (b >= 'a'&&b <= 'z')
		b = 'i';
	list<act>::iterator it;
	for (it = ACTION.begin(); it != ACTION.end(); it++)
	{
		if (it->I == i &&it->Vt == b)
		{
			return *it;
		}
	}
	return {0,0,0,0};  //ERROR
}


int getGOTO(int i, char b)
{
	list<go>::iterator it;
	for (it = GOTO.begin(); it != GOTO.end(); it++)
	{
		if (it->I == i &&it->Vn == b)
			return  it->next_I;
	}
	return -1;  //ERROR
}


char newTemp()
{
	char c = 'A';
	result_count++;
	return c + result_count-1;
}


void SLR()
{
	int V_num = 0;  //符號表
	int index = 0;
	S[0] = 0;  //init
	cout << "分析棧:(| |中的為非終結符號的屬性)" << endl;
	while (getACTION(S[S_top],input[index]).tag != 'r' || getACTION(S[S_top], input[index]).action != 0)  //acc
	{
	/*	if (input[index] >= 'a'&&input[index] <= 'z')
		{
			string str = "i";
			str += to_string(V_num);
			V_num++;
			V.push_back({ str,input[index] });
		}
		for (list<var>::iterator v = V.begin(); v != V.end(); v++)
		{
			cout << v->name << " " << v->value << endl;
		}
	*/	
		if (getACTION(S[S_top], input[index]).tag == 0)  //ERROR
		{
			cout<<"error!"<<endl;  //出錯處理
			return;
		}
		else if (getACTION(S[S_top], input[index]).tag == 's')
		{   //		push
			S[S_top + 1] = getACTION(S[S_top], input[index]).action;  //push操作
			T[S_top + 1] = input[index];
			value[S_top + 1] = input[index];
			S_top++;
			index++;  //advance();讀取下一個符號
		}
		else if(getACTION(S[S_top], input[index]).tag == 'r')
		{
			char arg1, arg2, result;  //四元式
			int i = getACTION(S[S_top], input[index]).action;  //要規約的產生式
			string str = "";
			for (int j = 0; j < G[i].length() - 3; j++)
			{
		//		pop操作
				if (value[S_top] != "(" && value[S_top] != ")")
				{
					string ss = "";
					ss += value[S_top];
					ss += str;
					str = string(ss);
				}


				if (j == 0)
					if (value[S_top].length() == 1)  //只是單個符號
						arg1 = value[S_top][0];
					else  //查表,查詢符號
					{
						for (list<var>::iterator v = V.begin(); v != V.end(); v++)
						{
							if (v->value == value[S_top])
							{
								arg1 = v->name;
								break;
							}
						}
					}
				if (j == 2)
					if (value[S_top].length() == 1)
						arg2 = value[S_top][0];
					else
						for (list<var>::iterator v = V.begin(); v != V.end(); v++)
						{
							if (v->value == value[S_top])
							{
								arg2 = v->name;
								break;
							}
						}
				S[S_top] = -1;
				T[S_top] = 0;
				value[S_top] = "";
				S_top--;
			}
			for (list<int>::iterator ii = sys.begin(); ii != sys.end(); ii++)  //生成四元式
				if (i == *ii)
				{
					result = newTemp();
					V.push_back({ result,str });
					L_sys.push_back({ G[i][4],arg1,arg2,result });
					break;
				}
			//push
			S[S_top + 1] = getGOTO(S[S_top], G[i][0]);
			T[S_top + 1] = G[i][0];
			value[S_top + 1] = str;  //屬性傳遞
			S_top++;
		}
		for (int tt = 0; tt <= 15; tt++)
		{
			if (tt <= S_top)
				if (S[tt] >= 10)
					cout << S[tt] << " ";
				else
					cout << S[tt] << "  ";
			else
				cout << "   ";
		}


		for (int tt = 0; tt <= S_top; tt++)
		{
			if (tt <= S_top)
			{
				cout << T[tt]<<" ";
				if(isupper(T[tt]))
					cout << "|" << value[tt] << "| ";
			}
			else
				cout << "  ";
		}
		cout << endl;
	}
	cout << endl << "匹配成功!" << endl;
	cout << endl << "四元式:" << endl;
	for (list<siyuanshi>::iterator s = L_sys.begin(); s != L_sys.end(); s++)
	{
		cout << '(' << s->op << "," << s->arg1 << "," << s->arg2 << ',' << s->result << ')' << endl;
	}
}


void print(sentence s)
{
	int r;
	cout << "  ";
	for (r = 0; r < s.str.length(); r++)
		if (r == s.tag)
			cout << "·" << s.str[r];
		else
			cout << s.str[r];
	if (r == s.tag)
		cout << "·";
	cout << endl;
}




void find(char ch, int tag_Vn)
{
	for (int qq = 0; qq < 11; qq++)
	{
		if (ch == G[qq][0])
		{
			if (G[qq][3] >= 'A'&&G[qq][3] <= 'Z')
				if (G[qq][3] == ch)  //避免死迴圈重複查詢
					;
				else
					find(G[qq][3], tag_Vn);
			else
			{
				int tag = 0;
				for (list<char>::iterator i = First[tag_Vn].begin(); i != First[tag_Vn].end(); i++)
				{
					if (*i == G[qq][3])
					{
						tag = 1;
						break;
					}
				}
				if (tag == 0)
					First[tag_Vn].push_back(G[qq][3]);
			}
		}
	}
}


int findVn(char c)
{
	int tag = -1;
	for (list<char>::iterator i = Vn.begin(); i != Vn.end(); i++)
	{
		tag++;
		if (c == *i)
			return tag;
	}
	return -1;
}




void scan()  //構造符號集
{
	for (int i = 0; i < 11; i++)//文法長度
	{
		for (int j = 0; j < G[i].length(); j++)
		{
			if (j == 1 || j == 2)
				continue;
			if (isupper(G[i][j]))
			{
				if (find(Vn.begin(), Vn.end(), G[i][j]) == Vn.end())
					Vn.push_back(G[i][j]);
			}
			else
			{
				if (find(Vt.begin(), Vt.end(), G[i][j]) == Vt.end())
					Vt.push_back(G[i][j]);
			}
		}
	}
	Vt.push_back('#');




	First = new list<char>[Vn.size()];
	int tag_Vn = -1;
	for (list<char>::iterator ch = Vn.begin(); ch != Vn.end(); ch++)
	{
		tag_Vn++;
		for (int qq = 0; qq < 11; qq++)
		{
			if (*ch == G[qq][0])
			{
				if (G[qq][3] >= 'A'&&G[qq][3] <= 'Z')
				{
					find(G[qq][3], tag_Vn);
				}
				else
				{
					First[tag_Vn].push_back(G[qq][3]);
				}
			}
		}
	}




	Follow = new list<char>[Vn.size()];
	Follow[0].push_back('#');


	int follow_sum = 0;  //follow集數量總和
	int previous_sum = -1;  //之前的總和
	while (follow_sum != previous_sum)
	{
		for (int i = 0; i < 11; i++)
		{
			for (int j = 3; j < G[i].length() - 1; j++)
			{
				if (isupper(G[i][j]))
					if (!isupper(G[i][j + 1]))  //是終結符號
					{
						int tag = 0;
						for (list<char>::iterator ii = Follow[findVn(G[i][j])].begin(); ii != Follow[findVn(G[i][j])].end(); ii++)
						{
							if (*ii == G[i][j + 1])
							{
								tag = 1;
								break;
							}
						}
						if (tag == 0)
							Follow[findVn(G[i][j])].push_back(G[i][j + 1]);
					}
					else  //是非終結符號
					{
						for (list<char>::iterator ii = Follow[findVn(G[i][j + 1])].begin(); ii != Follow[findVn(G[i][j + 1])].end(); ii++)
						{
							if (find(Follow[findVn(G[i][j + 1])].begin(), Follow[findVn(G[i][j + 1])].end(), *ii) == Follow[findVn(G[i][j + 1])].end())  //不重複
								Follow[findVn(G[i][j])].push_back(*ii);
						}
					}
			}
			if (isupper(G[i][G[i].length() - 1]))
				for (list<char>::iterator ii = Follow[findVn(G[i][0])].begin(); ii != Follow[findVn(G[i][0])].end(); ii++)
				{
					if (find(Follow[findVn(G[i][G[i].length() - 1])].begin(), Follow[findVn(G[i][G[i].length() - 1])].end(), *ii) == Follow[findVn(G[i][G[i].length() - 1])].end())  //不重複
						Follow[findVn(G[i][G[i].length() - 1])].push_back(*ii);
				}
		}
		previous_sum = follow_sum;
		follow_sum = 0;
		for (int ii = 0; ii < Vn.size(); ii++)
		{
			follow_sum += Follow[ii].size();
		}
	}
	list<char>::iterator iter;
	cout<<"終結符號集:";
	for (iter = Vt.begin(); iter != Vt.end(); iter++)
	{
	    cout<<*iter;
	}
	cout << endl;
	cout<<"非終結符號集:";
	for (iter = Vn.begin(); iter != Vn.end(); iter++)
	{
		cout << *iter;
	}
	cout << endl;
	int pp;
	cout << "FIRST" << endl;
	for (pp = 0, iter = Vn.begin(); pp < Vn.size(); pp++, iter++)
	{
		cout << *iter << "     ";
		for (list<char>::iterator ch = First[pp].begin(); ch != First[pp].end(); ch++)
		{
			cout << *ch << " ";
		}
		cout << endl;
	}
	cout <<"FOLLOW"<< endl;
	for (pp = 0, iter = Vn.begin(); pp < Vn.size(); pp++, iter++)
	{
		cout << *iter << "     ";
		for (list<char>::iterator ch = Follow[pp].begin(); ch != Follow[pp].end(); ch++)
		{
			cout << *ch << " ";
		}
		cout << endl;
	}


}




I closure(I &dfa)
{
	list<sentence>::iterator iter;
	for (iter = dfa.l.begin(); iter != dfa.l.end(); iter++)
	{
		if ((iter->tag <= iter->str.length()))
			if ((iter->str[iter->tag] >= 'A'&&iter->str[iter->tag] <= 'Z'))
			{
				for (int tt = 0; tt < 11; tt++)  //查詢對應的產生式
				{
					if (iter->str[iter->tag] == G[tt][0])
					{
						int q = 0;
						list<sentence>::iterator it;
						sentence x;
						x.str = G[tt];
						for (it = dfa.l.begin(); it != dfa.l.end(); it++)
						{
							if ((it->str == x.str) && (it->tag == x.tag))
							{
								q = 1;
								break;
							}
						}
						if (q == 0)
						{
							dfa.l.push_back(x);
						}
					}
				}
			}
	}
	return dfa;
}
int compare(I a, I b) //是否相等
{
	
	if (a.l.size() != b.l.size())
		return 1;
	else
	{
		for (list<sentence>::iterator iii = a.l.begin(), jjj = b.l.begin(); iii != a.l.end() || jjj != b.l.end(); iii++, jjj++)
			if (iii->str != jjj->str || iii->tag != jjj->tag)  //判斷是否相等
			{
				return 1;
			}
	}
	return 0;
}


void table() 
{
	int num = 0;
	sentence first;  //起始符號
	first.str = G[0];
	
	I L;
	L.number = 0;
	L.l.push_back(first);
	DFA.push_back(L);


	list<I>::iterator dfa;
	for (dfa = DFA.begin(); dfa != DFA.end(); dfa++)
	{
		list<sentence>::iterator iter;
		closure(*dfa);
		for (iter = dfa->l.begin(); iter != dfa->l.end(); iter++)  //對狀態中的每一產生式右部進行處理
			if (iter->finish == 0)
			{
				I C;  //新狀態
				C.number = DFA.size();
				if (iter->tag < iter->str.length())  //尚未完成
				{
					sentence s;
					s.str = iter->str;
					if (iter->str[iter->tag] >= 'A'&&iter->str[iter->tag] <= 'Z')
					{
						GOTO.push_back({ dfa->number,iter->str[iter->tag],C.number });
					}
					else 
					{
						ACTION.push_back({ dfa->number,iter->str[iter->tag],'s',C.number });
					}
					s.tag = iter->tag + 1;
					iter->finish = 1;
					C.l.push_back(s);
					list<sentence>::iterator i;
					for (i = iter, i++; i != dfa->l.end(); i++)
						if (i->str[i->tag] == iter->str[iter->tag])
						{
							s.str = i->str;
							s.tag = i->tag + 1;
							i->finish = 1;
							C.l.push_back(s);
						}


					int judge = 0, count = 0;
					for (list<I>::iterator ii = DFA.begin(); ii != DFA.end(); ii++, count++)  //判斷是否有重複
					{
						judge = compare(*ii, closure(C));  //修改C
						if (judge == 0)
							break;
					}
					if (judge == 0)
					{
						if (iter->str[iter->tag] >= 'A'&&iter->str[iter->tag] <= 'Z')
						{
							GOTO.pop_back();
							GOTO.push_back({ dfa->number,iter->str[iter->tag], count });
						}
						else
						{
							ACTION.pop_back();
							ACTION.push_back({dfa->number,iter->str[iter->tag],'s',count});
						}
					}
					else
						DFA.push_back(C);
				}
				else  //已經完成
				{
					int cc = 0, tt;
					for (tt = 0; tt < 11; tt++)
					{
						if (iter->str == G[tt])
							break;
					}
					for (list<char>::iterator c = Vn.begin(); c != Vn.end(); c++, cc++)
						if (*c == iter->str[0])
							break;
					for (list<char>::iterator c = Follow[cc].begin(); c != Follow[cc].end(); c++)
					{
						ACTION.push_back({ dfa->number,*c,'r',tt });  //對應的第j條產生式
						for (int ss = 3; ss < G[tt].length(); ss++)  //查詢四元式對應的產生式
							if ( G[tt][ss] == '+' || G[tt][ss] == '-' || G[tt][ss] == '*' || G[tt][ss] == '/')
							{
								sys.push_back(tt);
							}
					}
				}
			}
	}


	num = 0;
	for (dfa = DFA.begin(); dfa != DFA.end(); dfa++)
	{
		cout << "狀態" << num++ << ":" << endl;
		for (list<sentence>::iterator iii = dfa->l.begin(); iii != dfa->l.end(); iii++)
		{
			print(*iii);
		}
	}
	for (list<go>::iterator g = GOTO.begin(); g != GOTO.end(); g++)
	{
		cout <<"GOTO("<< g->I << ", " << g->Vn << ") = " << g->next_I <<endl;
	}
	for (list<act>::iterator a = ACTION.begin(); a != ACTION.end(); a++)
	{
		cout << "ACTION(" << a->I << ", " << a->Vt << ") = " << a->tag << a->action << endl;
	}
	cout << endl;
}




int main()
{
	readfile();
	scan();
	table();
	SLR();
    return 0;
}