- 規定終結符用小寫字母開頭和後面接若干“`”表示例如a,b,i,i`,i``表示不同的終結符。非終結符用大寫字母和後面接若干“`”表示非終結符例如A,B,T`,T``表示不同的非終結符。用“&”代表空串。連續輸入的“-”“>”代表推導,分割產生式左右部。輸入的文法的第一個產生式爲文法開始符的產生式。
- 設置變量SIZE,代表非終結符的最大的數量。對終結符和非終結符進行編號,規定數值0爲空串(&)。用1~SIZE的正整數對終結符和非終結符分別進行編號。爲了在候選式中不發生衝突,候選式的終結符使用終結符的相反數。例如:編號A:1, B:2, a:1, b:2 。則二維數組{{1,2},{-1,2},{0} } 代表候選式 AB | aB | & 。FIRST和FOLLOW集合存儲的是非終結符的編號和終結符的編號的相反數。
- 將候選式分開存儲進pro結構體中,屬性Vn表示產生式左部,candy數組表示產生式右部。都是存儲符號的編號。每個pro的下標代表產生式的編號。項目集結構體中屬性pro集合代表一對序偶一個代表產生式的編號,一個表示‘.’號的位置。集合v代表項目集的邊。go集合也是一對序偶,第一個數表示邊代表的字符編號,第二個數代表指向的項目集。
#include <bits/stdc++.h>
using namespace std;
#include "definition.h"
#include "Check.h"
#include "Init.h"
#include "getFirst.h"
#include "getFollow.h"
#include "Display.h"
#include "getI.h"
#include "getTable.h"
#include "analyse.h"
int main()
{
ifstream file;
file.open("test/input3.txt");
string str;
while(getline(file, str)){ //輸入一行,即一個非終結符的候選式
cout<<str<<endl;
init(str); //初始化,將終結符和非終結符等進行編號等
}
getFIRST(); //獲取FIRST集
getFollow(); //獲取FOLLOW集
dispalyFirst(); //輸出FIRST集
dispalyFollow(); //輸出FOLLOW集
//displayPro2();
displayPro(); //輸出產生式
getI(); //獲取項目集(I)
getActionGotoTable(); //獲取Action和GOTO表
ifstream in;
in.open("test/inputa3.txt"); //輸入串
string inStr;
while(getline(in,inStr)){
getAns(inStr);
}
return 0;
}
#ifndef DEFINITION_H_INCLUDED
#define DEFINITION_H_INCLUDED
#define SIZE 100
int idVt = 0; //終結符編號
int idVn = 1; //非終結符編號,0號爲擴展文法開始符
int idPro = 1; //產生式編號,0號爲擴展文法開始符
int JING; //# 號
int EMPTY = 5*SIZE; //空串
int startVt = -1; //判斷是否處理了開始符,只處理一次
int ERROR = 4*SIZE; //出錯標誌
int ACC = 5*SIZE; //成功標誌
map<string,int>mpVn,mpVt; //編號(字符,編號)
map<int,string>rmpVn,rmpVt; //雙向映射(編號,字符)
//存儲分開編號的產生式,下標爲編號
struct Pro {
int Vn; //產生式左部 1 <=> A
vector<int>candy; //產生式右部{1,2,-1} 代表 A -> ABa
Pro(){
Vn =0 ;
candy.clear();
}
}pro[SIZE];
//項目集I
struct Ix{
set<pair<int,int> >pro; //記錄項目集擁有的產生式編號以及對應的‘.’ 號的位置 {idPro,dot} 例如: { {0,0} , {1,1} } <=> { S`->.XX, E -> X.XX }
set<int>v; //記錄項目集的邊的符號的編號如:a編號1。GOTO(a,I)、GOTO(b,I) 的a, b
set<pair<int,int> >go; //(idVt/idVn, numI) 對應的邊以及其GOTO到的項目集
void Clear(){
pro.clear();
v.clear();
go.clear();
}
}I[SIZE];
//每個非終結符對應一個結構體
struct NoTml
{
vector<vector<int> > pro; //候選式:例如 {{1,2},{-1,2},{0} } => AB | aB | &
set<int> FIRST, FOLLOW; //FIRST集,FOLLOW集
int proNum; //處理FIRST集時使用,判斷以及完成的候選式
bool FirstFinish; //處理FIRST集時使用,判斷是否全部候選式都完成
NoTml(){
FirstFinish = false;
int proNum = 0 ;
FIRST.clear();
FOLLOW.clear();
pro.clear();
}
}notml[SIZE]; //每個下標對應一個非終結符
#endif // DEFINITION_H_INCLUDED
#ifndef INIT_H_INCLUDED
#define INIT_H_INCLUDED
void init(string str){
int len = str.length();
int pos = 0;
int idLeft = 0;
string word="";
vector<int>vec;
//獲取產生式左部
while(pos<len){
if(str[pos]==' '){ //過濾空格
pos++;
}
else if(str[pos]>='A'&&str[pos]<='Z'){ //判斷是否爲大寫字母開始,即是否爲非終結符
word="";
word+=str[pos];
pos++;
while(pos<len&&str[pos]=='`') word+=str[pos],pos++;
if(mpVn.count(word)==0){
mpVn[word]=idVn++; //雙向映射(編號,字符),(字符,編號)
rmpVn[idVn-1]=word;
}
}
else if(str[pos]=='-'&&str[pos+1]=='>') {
idLeft = mpVn[word];
pos+=2;
break;
}
else {
errorG(); //文法輸入錯誤
return ;
}
}
//擴展文法開始符
if(startVt == -1){
rmpVt[EMPTY]="&"; //& 代表空串
mpVt["&"] = EMPTY;
JING = idVt++; //對 # 號進行編號
rmpVt[JING]="#";
mpVt["#"] = JING;
ERROR = SIZE+1;
startVt = idLeft;
mpVn["S`"] = 0;
rmpVn[0] = "S`";
pro[0].candy.push_back(idLeft);
pro[0].Vn = 0;
notml[0].pro.push_back({idLeft});
}
//獲取產生式右部
while(pos<len){
if(str[pos]==' '){
pos++;
}
else if(str[pos]=='&'){ //空串
vec.push_back(EMPTY);
pos++;
}
else if(str[pos]=='|'){ //得到了一個候選式,
if(!vec.empty()) {
pro[idPro].candy.assign(vec.begin(),vec.end());
pro[idPro++].Vn=idLeft;
notml[idLeft].pro.push_back(vec);
}
vec.clear();
pos++;
}
else if(str[pos]>='A'&&str[pos]<='Z') { //對非終結符編號
word="";
word+=str[pos];
pos++;
while(pos<len&&str[pos]=='`') word+=str[pos],pos++;
if(mpVn.count(word)==0){
mpVn[word]=idVn++;
rmpVn[idVn-1]=word;
}
vec.push_back(mpVn[word]);
}
else if(!(str[pos]>='A'&&str[pos]<='Z')){ //對終結符編號
word="";
word+=str[pos];
pos++;
while(pos<len&&str[pos]=='`') word+=str[pos],pos++;
if(mpVt.count(word)==0){
mpVt[word]=idVt++;
rmpVt[idVt-1]=word;
}
vec.push_back(-mpVt[word]); //終結符在候選式內使用負數,防止和非終結符衝突
}
else {
errorG();
}
}
if(!vec.empty()) {
pro[idPro].candy.assign(vec.begin(),vec.end()); //處理最後的候選式
pro[idPro++].Vn = idLeft;
notml[idLeft].pro.push_back(vec); //處理最後的候選式
}
vec.clear();
if(idVt>=SIZE||idVn>=SIZE) { //終結符或,非終結符超出範圍,錯誤
errorG();
return ;
}
}
#endif // INIT_H_INCLUDED
#ifndef GETFIRST_H_INCLUDED
#define GETFIRST_H_INCLUDED
//輸出FIRST集合
void dispalyFirst(){
cout<<"---------------FIRST start---------------------"<<endl;
for(int i=0;i<idVn;i++){
cout<<rmpVn[i]<<": ";
for(set<int>::iterator it=notml[i].FIRST.begin();it!=notml[i].FIRST.end();it++){
cout<<rmpVt[abs(*it)]<<" ";
}
cout<<endl;
}
cout<<"---------------FIRST end---------------------"<<endl;
}
//獲取FIRST集,和實驗二LL分析器一樣
void getFIRST(){
//規則(1) 即將候選式的首字符是非終結符的加入FIRST集合
for(int i=0;i<idVn;i++){
for(int j=0;j< notml[i].pro.size();j++){
if(notml[i].pro[j][0]<=0){
notml[i].FIRST.insert(notml[i].pro[j][0]);
notml[i].proNum++;
}
//判斷是否全部候選式都處理完
if(notml[i].proNum == notml[i].pro.size()) notml[i].FirstFinish = true;
}
}
//規則(2)的第一步,將X -> Y...的FIRST(Y)/{&}加入到FIRST(X)
for(int i=0;i<idVn;i++){
for(int j=0;j< notml[i].pro.size();j++){
if(notml[i].pro[j][0]>0){ //判斷首字符是否爲非終結符
set<int>tmp;
int idk=notml[i].pro[j][0]; //獲取首字符的編號
tmp.insert(notml[idk].FIRST.begin(),notml[idk].FIRST.end());
if(tmp.count(EMPTY)) tmp.erase(EMPTY);
notml[i].FIRST.insert(tmp.begin(),tmp.end());
}
}
}
//規則(2)第二步,每次有變化都要進行更新
bool hasChange = true;
int Empty=0;
while(hasChange){
hasChange = false;
for(int i=0;i<idVn;i++){ //遍歷非終結符,對還有候選式沒有處理的進行處理
if(!notml[i].FirstFinish){
for(int j=0;j<notml[i].pro.size();j++){ //遍歷每個候選式
Empty=0; //記錄空串,判斷是否整個字符串都有空串
bool ok = true;
for(int k=0;k<notml[i].pro[j].size();k++){ //遍歷每個候選的每個字符
int id = notml[i].pro[j][k];
if(id>0&&!notml[id].FirstFinish){ //必須是已經處理完成的非終結符才能更新現在的非終結符
ok=false;
break;
}
}
if(ok){ //對非終結符進行更新
for(int k=0;k<notml[i].pro[j].size();k++){
int id = notml[i].pro[j][k];
if(id>0&¬ml[id].FirstFinish){
set<int> tmp;
tmp.insert(notml[id].FIRST.begin(),notml[id].FIRST.end()); //將FIRST(Y)加入到FIRST(X)
if(notml[id].FIRST.count(EMPTY)){ //判斷空串
Empty++;
tmp.erase(EMPTY);
notml[i].FIRST.insert(tmp.begin(),tmp.end());
hasChange = true;
}
else {
notml[i].FIRST.insert(tmp.begin(),tmp.end());
hasChange = true;
break; //沒有空串則停止
}
}
}
if(Empty == notml[i].pro[j].size()){ //如果全部字符都有空串,則加入空串到FIRST(X)
notml[i].FIRST.insert(EMPTY);
}
notml[i].proNum++; //記錄已經處理候選式
if(notml[i].proNum == notml[i].pro.size()) notml[i].FirstFinish = true; //全部候選式處理完則該非終結符處理完
}
}
}
}
}
}
#endif // GETFIRST_H_INCLUDED
#ifndef GETFOLLOW_H_INCLUDED
#define GETFOLLOW_H_INCLUDED
//輸出FOLLOW集合
void dispalyFollow(){
cout<<"---------------FOLLOW start---------------------"<<endl;
for(int i=0;i<idVn;i++){
cout<<rmpVn[i]<<": ";
for(set<int>::iterator it=notml[i].FOLLOW.begin();it!=notml[i].FOLLOW.end();it++){
cout<<rmpVt[abs(*it)]<<" ";
}
cout<<endl;
}
cout<<"---------------FOLLOW end---------------------"<<endl;
}
//獲取FOLLOW集,和實驗二LL分析器一樣
void getFollow(){
//規則(1)將 # 加入到文法開始符的FOLLOW集合
notml[0].FOLLOW.insert(JING);
//規則(2)A -> aBP 將FIRST(P)/{&} 加入到FOLLOW(B)
for(int id=0;id<idVn;id++){ //遍歷每個非終結符,獲取位置進行處理
for(int i=0;i<idVn;i++){ //三個for遍歷每個非終結符的每個候選式的每個字符
for(int j=0;j<notml[i].pro.size();j++){
for(int k=0;k<notml[i].pro[j].size();k++){
if((notml[i].pro[j][k]==id)&&(k+1<notml[i].pro[j].size())&&(notml[i].pro[j][k+1]<0)){
notml[id].FOLLOW.insert(notml[i].pro[j][k+1]); //P不是終結符,終結符的FIRST集合是它本身,直接加入
}
else if((notml[i].pro[j][k]==id)&&(k+1<notml[i].pro[j].size())&&(notml[i].pro[j][k+1]>0)){
set<int>tmp;
int idk = notml[i].pro[j][k+1];
tmp.insert(notml[idk].FIRST.begin(),notml[idk].FIRST.end());
if(tmp.count(EMPTY))
tmp.erase(EMPTY);
notml[id].FOLLOW.insert(tmp.begin(),tmp.end()); //FIRST(P)/{&}加入FOLLOW(A)
}
}
}
}
}
//規則(3)A -> aB 或 A-> aBP
queue<int>que; //記錄需要進行處理的非終結符
for(int i=1;i<idVn;i++){
que.push(i);
}
int id;
while(!que.empty()){
id=que.front(); //處理B
que.pop();
for(int i=0;i<idVn;i++){ //遍歷A
for(int j=0;j<notml[i].pro.size();j++){
for(int k=0;k<notml[i].pro[j].size();k++){
if((notml[i].pro[j][k]==id)&&(k+1==notml[i].pro[j].size())){ //候選式爲 A -> aB
if(notml[i].FOLLOW.size()==0) que.push(id);
else notml[id].FOLLOW.insert(notml[i].FOLLOW.begin(),notml[i].FOLLOW.end());
}
else if((notml[i].pro[j][k]==id)&&(k+1<notml[i].pro[j].size())&&(notml[i].pro[j][k+1]>0)&&(notml[notml[i].pro[j][k+1]].FIRST.count(0)>0)){
//候選式爲 A -> aBP
if(notml[i].FOLLOW.size()==0) que.push(id);
else notml[id].FOLLOW.insert(notml[i].FOLLOW.begin(),notml[i].FOLLOW.end());
}
}
}
}
}
}
#endif // GETFOLLOW_H_INCLUDED
#ifndef GETI_H_INCLUDED
#define GETI_H_INCLUDED
//處理項目集
stack<int>st; //記錄需要增長的項目集
bool vis[SIZE]; //標誌每次擴展一個項目集的產生式,判斷是否重複
int numI = 0; //項目集的數量
Ix tmpI; //項目集的臨時變量
//顯示每個項目集
void displayByIdI(int id){
cout<<"-----------------start---------------------"<<endl;
bool flag = false;
cout<<"I["<<id<<"]:"<<endl;
//cout<<id<<":"<<I[id].pro.size()<<endl;
for(pair<int,int> x : I[id].pro){
int idV = x.first;
int dot = x.second;
int idV2 = pro[idV].Vn;
flag = false;
cout<<rmpVn[idV2]<<"->";
for(int j=0;j<pro[idV].candy.size();j++){
if(j==dot){
flag = true;
cout<<".";
}
int value = pro[idV].candy[j];
if(value>0){
cout<<rmpVn[value];
}else {
cout<<rmpVt[-value];
}
}
if(!flag) cout<<".";
cout<<endl;
}
for(pair<int,int> x:I[id].go){
cout<<"GOTO(";
if(x.first>0){
cout<<rmpVn[x.first];
}else {
cout<<rmpVt[-x.first];
}
cout<<", I["<<x.second<<"] )\n";
}
cout<<"-----------------end---------------------"<<endl;
}
//void displayI(){
// cout<<"--------------------I start-----------------------"<<endl;
// for(int i=0;i<=numI;i++){
// cout<<"------------"<<i<<"--------------"<<endl;
// cout<<"pro:"<<endl;
// for(pair<int,int> p:I[i].pro){
// cout<<p.first<<":"<<p.second<<endl;
// }
// cout<<"go"<<endl;
// for(pair<int,int> p:I[i].go){
// cout<<p.first<<":"<<p.second<<endl;
// }
// cout<<"------------"<<i<<"--------------"<<endl;
// }
// cout<<"--------------------I end-----------------------"<<endl;
//}
//DFS求項目集的閉包
void Closure(int idV){
for(int i=0;i<idPro;i++){
if(vis[i]) continue; //已經有的產生式跳過
if(pro[i].Vn == idV){ //判斷是否是相同的產生式左部
vis[i] = true; //標誌該產生式
tmpI.pro.insert({i,0}); //存儲產生式
tmpI.v.insert(pro[i].candy[0]); //存儲產生式右部第一個字符,作爲一條邊
if(pro[i].candy[0]>0){
Closure(pro[i].candy[0]); //根據第一個字符繼續搜索
}
}
}
}
//求項目集
void GOTO(int idV,int dot){
memset(vis, false, sizeof(vis)); //每次處理一個項目集要將產生式標誌清零
tmpI.pro.insert({idV, dot+1}); //存儲產生式以及它的點‘.’位置
if(dot+1<pro[idV].candy.size()){
int idV2 = pro[idV].candy[dot+1]; //獲取一條邊
tmpI.v.insert(idV2);
Closure(idV2); //求閉包
}
}
//判斷求得的項目集是否出現過,沒則創建新的
int getNext(){
for(int i=0;i<=numI;i++){
if(I[i].pro==tmpI.pro){
return i;
}
}
++numI;
I[numI].pro=tmpI.pro;
I[numI].v=tmpI.v;
I[numI].go=tmpI.go;
st.push(numI);
return numI;
}
//求項目集
void getI(){
memset(vis, false, sizeof(vis));
tmpI.Clear();
tmpI.pro.insert({0,0});
Closure(1); //求初始項目集
I[0].pro=tmpI.pro;
I[0].v=tmpI.v;
I[0].go=tmpI.go;
//求初始項目集的邊
for(pair<int,int> x:I[0].pro){
int idV = x.first;
int dot = x.second;
int Vn = pro[idV].candy[dot];
I[0].v.insert(Vn);
}
//使用棧存儲需要增長的項目集,從0號項目集開始
st.push(0);
while(!st.empty()){
int idI = st.top(); //獲取項目集編號
st.pop();
for(int x:I[idI].v){ //遍歷項目集的出度邊
tmpI.Clear(); //初始化臨時遍歷,用來指定下一個擴展的節點
for(pair<int,int> p:I[idI].pro){ //遍歷項目集的產生式
int idV = p.first;
int dot = p.second;
int v = pro[idV].candy[dot];
if(x == v){ //產生式的點‘.’後面的字符是出度的邊的字符則邊指向另一個項目集
GOTO(idV, dot);
}
}
I[idI].go.insert({x,getNext()}); //增加一條邊
}
}
//輸出項目集
for(int i=0;i<=numI;i++){
displayByIdI(i);
cout<<endl;
}
//displayI();
}
#endif // GETI_H_INCLUDED
#ifndef GETACTION_H_INCLUDED
#define GETACTION_H_INCLUDED
//求ACTION和GOTO表
int Action[SIZE][SIZE]; //第一維表示項目集編號,第二維表示終結符或非終結符
int Goto[SIZE][SIZE];
//顯示錶內容
void displayTable(){
cout<<"------------------------------LR Table-----------------------------"<<endl;
cout<<"\t";
for(int i=0;i<idVt;i++){
cout<<rmpVt[i]<<"\t";
}
for(int i=0;i<idVn;i++){
cout<<rmpVn[i]<<"\t";
}
cout<<endl;
for(int i=0;i<=numI;i++){
cout<<i<<"\t";
for(int j=0;j<idVt;j++){
if(Action[i][j] == ERROR){
cout<<"error\t";
}else {
//cout<<Action[i][j]<<"\t";
if(Action[i][j]==ACC){
cout<<"acc\t";
}else if(Action[i][j]>=2*SIZE){
cout<<"r"<<Action[i][j]-2*SIZE<<"\t";
}else {
cout<<"S"<<Action[i][j]<<"\t";
}
}
}
for(int j=0;j<idVn;j++){
if(Goto[i][j] == ERROR){
cout<<"error\t";
}else {
cout<<Goto[i][j]<<"\t";
}
}
cout<<endl;
}
cout<<"------------------------------LR Table-----------------------------"<<endl<<endl;
}
//求ACTION和GOTO表
void getActionGotoTable(){
//初始化
for(int i=0;i<SIZE;i++){
for(int j=0;j<SIZE;j++){
Action[i][j]= ERROR;
Goto[i][j] = ERROR;
}
}
for(int i=0;i<=numI;i++){ //遍歷全部項目集
int idP, dot;
for(pair<int,int>p:I[i].pro){ //遍歷其全部產生式
idP = p.first;
dot = p.second;
if(pro[idP].candy.size()==dot&&idP==0){ //規則(3) 處理文法開始符,如S` -> S
Action[i][JING]=ACC;
}
else if(pro[idP].candy.size()==dot){ //規則(2) 處理點‘.’在產生式最右邊 如A -> a .
for(int j=0;j<idVt;j++){//非終結符 a
int idV = pro[idP].Vn; //產生式左部 A
if(notml[idV].FOLLOW.count(-j)){ //歸約
Action[i][j] = idP+2*SIZE; //產生式編號加兩倍SIZE,和移進操作區分
}
}
}else { //規則(1)(4)
for(pair<int,int> x:I[i].go){ //遍歷每條邊
int idt = x.first; //邊的字符 a
int idI = x.second; //邊的指向項目集 I
if(idt>0){ //點‘.’後面是非終結符 如A -> a . Bp
Goto[i][idt] = idI;
}
else if(pro[idP].candy.size()>dot&&(pro[idP].candy[dot]==idt)){ //點‘.’後面是終結符 如A -> c . ap
Action[i][-idt] = idI;
}
}
}
}
}
displayTable();
}
#endif // GETACTION_H_INCLUDED
#ifndef ANALYSE_H_INCLUDED
#define ANALYSE_H_INCLUDED
//輸出ACTION動作
void displayS(int inNum,int stzNum,int stfNum,int tableNum){
cout<<"ACTION["<<stzNum<<","<<rmpVt[-inNum]<<"]=S"<<tableNum<<":";
cout<<"將狀態"<<tableNum<<"入棧"<<endl;
}
//輸出歸約動作
void displayR(int stzT,int tableNum,int idP,int stznew){
cout<<"r"<<tableNum-2*SIZE<<":"<<"用";
cout<<rmpVn[pro[idP].Vn]<<"->";
for(int i=0;i<pro[idP].candy.size();i++){
int x=pro[idP].candy[i];
if(x>0) cout<<rmpVn[x];
else cout<<rmpVt[-x];
}
cout<<"歸約且GOTO(";
cout<<stzT<<","<<rmpVn[pro[idP].Vn]<<")=";
cout<<stznew<<"入棧"<<endl;
}
//輸出分析成功
void displaySuccess(){
cout<<"Acc:分析成功"<<endl;
}
//輸出狀態棧情況
void displayStz(stack<int>st){
vector<int>vec;
while(!st.empty()){
vec.push_back(st.top());
st.pop();
}
for(int i=vec.size()-1;i>=0;i--){
if(i==0) cout.width(20-2*vec.size());
cout<<vec[i]<<" ";
}
}
//輸出符號棧情況
void displayStf(stack<int>st){
vector<int>vec;
while(!st.empty()){
vec.push_back(st.top());
st.pop();
}
for(int i=vec.size()-1;i>=0;i--){
if(i==0) cout.width(20-2*vec.size());
if(vec[i]>0) cout<<rmpVn[vec[i]]<<" ";
else cout<<rmpVt[-vec[i]]<<" ";
}
}
//輸出輸入串情況
void displayInput(int pos,vector<int> vec){
for(int i=pos;i<vec.size();i++){
if(i==vec.size()-1) cout.width(20-2*(vec.size()-pos));
if(vec[i]>0) cout<<rmpVn[vec[i]]<<" ";
else cout<<rmpVt[-vec[i]]<<" ";
}
}
//分析輸入串
void getAns(string str){
cout.setf(std::ios::left);
cout<<"輸入串:"<<str<<endl;
cout<<"------------------------analyse start-----------------------"<<endl;
cout<<"步驟\t狀態棧\t\t符號棧\t\t\t輸入串\t\t動作說明\n";
int len = str.length();
vector<int>input;
for(int i=0;i<len;i++){ //將輸入串轉換成編號
string tmp="";
tmp+=str[i];
input.push_back(-mpVt[tmp]);
}
input.push_back(-JING); //增加‘#’號
stack<int>stz, stf; //狀態棧和符號棧
stz.push(0);
stf.push(-JING);
int pos = 0;
int step = 1;
while(1){
cout.width(8);
cout<<step++; //輸出第幾步
displayStz(stz); //輸出狀態棧
displayStf(stf); //輸出符號棧
displayInput(pos,input); //輸出輸入串
int inNum = input[pos];
if(stf.size()==0||stz.size()==0){ //狀態棧或符號棧爲空分析失敗
errorA();
return ;
}
int stzNum = stz.top();
int stfNum = stf.top();
int tableNum;
tableNum = Action[stzNum][-inNum]; //取Action表對應值
//cout<<stzNum<<":"<<inNum<<":"<<tableNum<<":"<<stfNum<<endl;
if(tableNum == ACC) break;
if(tableNum == ERROR){
errorA();
return ;
}
if(tableNum>=2*SIZE){ //歸約
int idP = tableNum - 2*SIZE;
for(int i=pro[idP].candy.size()-1;i>=0;i--){ //根據產生式右部進行出棧
if(pro[idP].candy[i]!=stf.top()) errorA();
if(stf.size()==0||stz.size()==0){
errorA();
return ;
}
stf.pop();
stz.pop();
}
stf.push(pro[idP].Vn); //將產生式左部加進符號棧
if(stf.size()==0||stz.size()==0){
errorA();
return ;
}
int stzT = stz.top();
int stznew = Goto[stzT][pro[idP].Vn]; //取得對應的GOTO表值
stz.push(stznew); //將GOTO表的值加入狀態棧
displayR(stzT,tableNum,idP,stznew); //輸出歸約動作
}else{ //移進
stz.push(tableNum);
stf.push(inNum);
pos++;
displayS(inNum,stzNum,stfNum,tableNum);
}
cout<<endl;
}
displaySuccess();
cout<<"------------------------analyse end-----------------------"<<endl;
}
#endif // ANALYSE_H_INCLUDED
#ifndef CHECK_H_INCLUDED
#define CHECK_H_INCLUDED
void errorG()
{
cout<<"輸入的文法有誤"<<endl;
exit(0);
}
void errorA()
{
cout<<"分析錯誤"<<endl;
cout<<"------------------------error start-----------------------"<<endl;
}
#endif // CHECK_H_INCLUDED