一、 問題描述
給定上下文無關文法,對其進行解析,得出first集和follow集。在有能力的情況下,可以求出ll(1)分析表。
二、 演算法設計
本程式主要分成三塊內容,第一是文法的讀入解析,第二是first集的求解,第三為follow集的求解。
文法的解析需要根據整行讀入的文法,生成rulelist 表,儲存文法的左部和右部,num為產生式的條數。start list表儲存非終結符,startnum為非終結符個數,endlist儲存終結符,endnum為終結符個數。
first集求解過程偽**:
first函式seq:
初始化flag表,記錄first集是否已求解
遍歷start list表,do
if (flag[n]==0) getfirst(n);
endfirst函式end
getfirst函式seq:
if (flag[n]1) return;
遍歷rulelist表,do:
若是非終結符為startlist[n]的產生式s:
if (s」#」) 將#加入first[n]
elif (以終結符開頭)
將終結符加入first[n]
else
遍歷s,do:
if (s[i]為非終結符)
getfirst(s[i]對應位置);//遞迴
將s[i]的first集加入first[n]
若s[i]的first集不包含#,則推出迴圈
elif (s[i]為終結符) 將終結符加入first集,退出迴圈
end if
若整個產生是遍歷完均含#,則first集加入#
getfirst函式end
follow集求解過程偽**:
follow函式 seq:
遍歷rulelist表,do:
str=rulist[i].tuidao
遍歷str,do
if (str[i]為非終結符)
while(str[x]是非終結符),do
follow[str[j]]+=first[str[x]]-#
若first[str[x]]不含# 則退出迴圈
若str[x]為空
f[n]記錄下該產生式的右部對應非終結符
若為終結符,將終結符壓入follow[str[j]]
else
若是終結符或#,則continue;
for(n屬於[0,startnum ))
getfirst(n);
follow函式end
getfollow函式seq:
if(flag[n]==2) return ;
while(f[n]不為空)
求出f[n]包含的所有非終結符的follow集//遞迴呼叫getfollow函式
將求得follow集加入follow[n]
flag[n]=2;
getfollow函式end
ll(1)分析偽**:
llanalyze函式seq:
遍歷rulelist表,do:
a=rulelist[i].ssymbol在startlist表的位置
str=rulelist[i].tuidao
if(str[0]為非終結符)
對所有a屬於first[str[0]],table[a][a]=i;
if(#屬於first[str[0]])
對所有a屬於follow[a],table[a][a]=i;
else if(為#)
對所有a屬於follow[a],table[a][a]=i;
else
a=終結符對應endlist位置
table[a][a]=i;
llanalyze函式end
三、 實驗**
#include
#include
#include
#include
#include
#include
#define maxnum 10
using
namespace std;
//定義文法結構體
struct rule
;vector> first;
vector> follow;
int flag[maxnum]
;stack<
int> f[maxnum]
;vector rulelist;
char startlist[maxnum]=;
string endlist[maxnum]=;
vector
int>> table;
int endnum =0;
int startnum =0;
//非終結符個數
int num =0;
intstrsearch
(string token)
return-1
;}intsearch
(char s)
return-1
;}intcheck
(string s)
}return location;
}void
getfirst
(int n)
else
else
else
}else
flag1 =1;
}}if(flag1==
0) first[n]
.push_back
("#");
}}}}
flag[n]=1
;}void
first()
}void
getfollow
(int n)
else
flag[n]=2
;}}void
follow()
else
x++;}
if(search
(str[x])!=
-1)continue
;else
if(str[x]
==null
)else
}else
if(str[j]
=='#'
)continue
;else}}
for(
int n =
0; n < startnum; n++
)getfollow
(n);
}void
llanalyze()
}else}}
else
if(str[0]
=='#')}
else}}
void
displayfirst()
cout <<
"}\n";}
}void
displayfollow()
cout <<
"}\n";}
}void
displayll()
cout << endl;
for(
int i =
0; i < startnum; i++)*/
} cout << endl;}}
intmain()
}//cout << num << " " << startnum;
for(
int i =
0; i < num; i++)}
if(!token.
empty()
&&strsearch
(token)==-
1)endlist[endnum++
]= token;
} endlist[endnum++]=
"$";
first.
resize
(startnum)
; follow.
resize
(startnum)
; table.
resize
(startnum)
;for
(int i =
0; i < startnum; i++
)first()
;follow()
;llanalyze()
;displayfirst()
;displayfollow()
;for
(int j =
0; j < num; j++
)displayll()
;}
四、 測試結果
輸入文法如下所示,得到的結果如圖1所示。
LL 1 文法判斷
ll 1 文法判斷 題型 1.判斷該文法是否是ll 1 文法?2.若是,給出它的ll 1 分析表,否則說明理由。概念 對於產生式 a 1.如果 均不能推導出 空語句 則 first first 2.和 至多有乙個能推導出 3.如果 經過0步或多步可以推導出 則 first follow a 關鍵 求...
編譯原理實驗 LL(1)文法
目標任務 實現 ll 1 分析中控制程式 表驅動程式 完成以下描述算術表示式的 ll 1 文法的 ll 1 分析程式。g e e te e ate t ft t mft f e i a m 說明 終結符號 i 為使用者定義的簡單變數,即識別符號的定義。compiler3.cpp 定義控制台應用程式的...
簡易c語言LL 1 文法
程式 宣告 函式 宣告 a 宣告 函式宣告 a 標頭檔案 巨集定義 宣告 宣告 null 標頭檔案 標頭檔案 標頭檔案 標頭檔案 標頭檔案 null 巨集定義 define b 巨集定義 null b 字串 c c 字串 數字 字串 變數名 函式宣告 返回值型別 函式名 形參 函式宣告 null 形...