2013-05-21 08:22:29Morris
[編譯器][作業] Predict Set
[程式作業三] 滿分100分 Input: (1) Grammar (2) First set (3) production rule S Output: predict set of S -------------------------------------------------- Input範例檔: [E,lambda] [E,+] [F,lambda] [F,=] G [id,(] H [-,lambda] [S,H,$] [S,E,F,G] ------------------- input.txt檔說明: [E,labmda] 代表"E→λ" [E,+] 代表"E→+" [F,lambda] 代表"F→λ" [F,=] 代表"F→=" G [(,id] 代表G之first set為id、( H [-,lambda] 代表H之first set為-、λ [S,H,$] 代表請求出"S→H$"的predict set [S,E,F,G] 代表請求出"S→EFG"的predict set Output範例檔1:Predict_set學號.txt S->H$ [-,$] S->EFG [+,=,(,id] ------------------- Output範例檔1檔說明: S->H$ [-,$] 代表S->H$這條production rule的Predict set為-、$ S->EFG [+,=,(,id] 代表S->EFG這條production rule的Predict set為+、=、(、id 範例二 input: [S,H,$] [H,A] A [(,id] [S,H,$] output: S->H$ [(,id] 範例三: input: [S,H,$] [H,A,B] [B,+] A [(,id,lambda] [S,H,$] output: S->H$ [(,id,+] p.s. 所有non-terminal我都會用一個大寫字母表示 要求出predict set的production不會有換出來是lambda的情況
在此不負責任
畢竟沒上課,就按照 ppt 隨便打了下,範測有過的 "屍體"。
基本流程是
1) 遞迴 First(*)
2a) 遇到首字母是 grammar 中,則嘗試所有 replace,並且求解 First Set
由於首字母的 replace 方法不只有一種,因此進行 union First Set 的操作。
2b) 如果遇到可以直接得到 First Set,則觀察其中有沒有 lambda
2b1) 若有則遞迴扣除 lambda 的結果,回朔回來時則進行 union
2c) 如果都找不到,則代表第一個字母一定是 terminal,直接納入 First Set
會不會有無限迴圈的可能?不曉得 grammar 中的定義,
如:
[S,A]
[A,A,B]
[B,$]
foo [(]
[S,A]
在 grammar 中 A->AB,那麼就會發生無限迴圈的問題,討論方式可能要忽略遞迴自己本身,
說到這了,明年修課時再來想吧。
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <map>
#include <set>
#include <vector>
using namespace std;
map<string, vector<vector<string> > > grammar;
map<string, set<string> > firstSet;
//First(alpha = A beta) = First(A), if lambda !belong First(A)
// First(A)-{lambda} then union First(beta), if lambda belong First(A)
set<string> findFirstSet(vector<string> right) {
set<string> ret, First;
if(right.size() == 0)
return ret;
map<string, vector<vector<string> > >::iterator it;
map<string, set<string> >::iterator jt;
it = grammar.find(right[0]);
// grammar process LL
if(it != grammar.end()) {
for(vector<vector<string> >::iterator kt = it->second.begin();
kt != it->second.end(); kt++) {// try each rule by [symbol]->[???]
// replace each one grammar by [symbol->???] + right[1...n]
vector<string> next;
for(vector<string>::iterator lt = (*kt).begin();
lt != (*kt).end(); lt++) {// concatenation [???]
if((*lt) != "lambda")
next.push_back(*lt);
}
for(int i = 1; i < right.size(); i++)// concatenation + right[1...n]
next.push_back(right[i]);
First = findFirstSet(next);
// make union
for(set<string>::iterator it = First.begin();
it != First.end(); it++)
ret.insert(*it);
}
return ret;
}
jt = firstSet.find(right[0]);
// process first set [terminal]
if(jt != firstSet.end()) {
ret = jt->second; // all first set
if(ret.find("lambda") != ret.end()) {// do -{lambda}
ret.erase("lambda");
right.erase(right.begin());// do find First(beta)
First = findFirstSet(right);
for(set<string>::iterator it = First.begin();
it != First.end(); it++)
ret.insert(*it); // union result
}
} else { // this is a terminal
ret.insert(right[0]);
}
return ret;
}
int main() {
char str[1024];
//grammar
while(gets(str)) {
if(str[0] == '\0') break;
int len = strlen(str);
string left = "";
vector<string> right;
for(int i = 1; i < len; i++) {
char buf[1024];
int bufIdx = 0;
while(str[i] != ',' && str[i] != ']')
buf[bufIdx++] = str[i++];
buf[bufIdx] = '\0';
if(left == "")
left = buf;
else {
right.push_back(buf);
//cout << left << "->" << right << endl;
}
}
grammar[left].push_back(right);
}
//first set
while(gets(str)) {
if(str[0] == '\0') break;
int len = strlen(str);
string left = "", right;
for(int i = 0; i < len; i++) {
char buf[1024];
int bufIdx = 0;
while(str[i] != ',' && str[i] != ']' && str[i] != ' ')
buf[bufIdx++] = str[i++];
buf[bufIdx] = '\0';
if(left == "") {
left = buf;
i++;
} else {
right = buf;
//cout << left << "->" << right << endl;
firstSet[left].insert(right);
}
}
}
// production rule of S
while(gets(str)) {
int len = strlen(str);
string left = "";
vector<string> right;
for(int i = 1; i < len; i++) {
char buf[1024];
int bufIdx = 0;
while(str[i] != ',' && str[i] != ']')
buf[bufIdx++] = str[i++];
buf[bufIdx] = '\0';
if(left == "")
left = buf;
else {
//cout << left << "->" << buf << endl;
right.push_back(buf);
}
}
cout << left << "->";
for(int i = 0; i < right.size(); i++)
cout << right[i];
cout << " [";
set<string> predictSet;
predictSet = findFirstSet(right);
for(set<string>::iterator it = predictSet.begin();
it != predictSet.end(); it++) {
if(it != predictSet.begin()) putchar(',');
cout << *it;
}
cout << "]" << endl;
}
return 0;
}
上一篇:[深度優先] 隨機迷宮生成