代码易懂,无需注释就能看懂。
#include<iostream>
#include<unordered_map>
#include<vector>
#include<fstream>
#include<sstream>
#include<unordered_set>
#include<map>
#include<iomanip>
using namespace std;
class OutPut{
public:
OutPut(string step,string symbolStack,string inputString,string production,string action):
step(std::move(step)),symbolStack(std::move(symbolStack)),inputString(std::move(inputString)),
production(std::move(production)),action(std::move(action)){};
void run(){
cout << setiosflags(ios::left) << setw(14) << step << setiosflags(ios::left) << setw(14) << symbolStack
<< setiosflags(ios::left) << setw(14) << inputString<< setiosflags(ios::left) << setw(14) << production
<< setiosflags(ios::left) << setw(14) << action<<endl;
}
private:
string step,symbolStack,inputString,production,action;
};
class LL1Analyzer{
public:
explicit LL1Analyzer(const string& path){
startchar='$';
ifstream readFile(path);
string grammar;
while(!readFile.eof()){
getline(readFile,grammar,'\n');
stringstream ss(grammar);
string left,right;
getline(ss,left,'>');
if(startchar=='$') startchar=left[0];
while(getline(ss,right,'|')){
production[left[0]].emplace_back(right);
for(char & ch:right)
if(!isupper(ch) && ch != '$') vt.insert(ch);
}
}
generateFirstSet();
generateFollowSet();
generateM();
}
void solve(const string& input){
vector<OutPut> outPutVec={OutPut("步骤","符号栈","输入串","所用产生式","动作")};
int step=0;
string inputstring=input+"#",symbolStack="#"+string(1,startchar),aproduciton,action="初始化";
outPutVec.emplace_back(OutPut(to_string(step),symbolStack,input,aproduciton,action));
int i=0;
while(i<inputstring.size()-1){
if(symbolStack.back()==inputstring[i]){
symbolStack.pop_back();
aproduciton="";
action="GETNEXT("+string(1,inputstring[i++])+")";
}else if(M.find({symbolStack.back(),inputstring[i]})==M.end()) break;
else{
aproduciton=M[{symbolStack.back(),inputstring[i]}];
action="pop";
symbolStack.pop_back();
if(aproduciton.back()!='$'){
int point=aproduciton.find('>')+1;
action+=",push("+aproduciton.substr(point)+")";
for(int j=aproduciton.size()-1;j>=point;--j) symbolStack.push_back(aproduciton[j]);
}
}
outPutVec.emplace_back(OutPut(to_string(++step),symbolStack,inputstring.substr(i),aproduciton,action));
}
for(OutPut aOutPut:outPutVec) aOutPut.run();
if(inputstring[i]!='#') cout<<"出错"<<endl;
}
private:
void generateFirstSet(){
int lastnum=-1,curnum=0;
while(lastnum!=curnum){
for(const pair<const char, vector<string>>& aProduction : production){
for(const string& candidate:aProduction.second){
for(char ch : candidate) if(!isupper(ch)) first[ch].insert(ch);
unordered_set<char> candidateFirst= FIRST(candidate);
for(char item:candidateFirst)
if(candidate=="$"||item!='$') first[aProduction.first].insert(item);
}
}
lastnum=curnum;
curnum= tableSize(first);
}
}
void generateFollowSet(){
follow[startchar]={'#'};
int lastnum=-1,curnum=0;
while(lastnum!=curnum){
for(const pair<const char, vector<string>>& aProduction : production){
for(const string& candidate:aProduction.second){
for(int i=0;i<candidate.size();++i){
unordered_set<char> tempFirst= FIRST(candidate.substr(i+1));
for(char item:tempFirst) follow[candidate[i]].insert(item);
if(tempFirst.find('$')!=tempFirst.end()||i==candidate.size()-1)
for(char item:follow[aProduction.first])
if(item!='$') follow[candidate[i]].insert(item);
}
}
}
lastnum=curnum;
curnum= tableSize(follow);
}
}
void generateM(){
for(const pair<const char, vector<string>>& aProduction : production){
for(const string& candidate:aProduction.second) {
string formula=string(1,aProduction.first)+"->"+candidate;
unordered_set<char> candidateFirst= FIRST(candidate);
for(char ftitem:candidateFirst)
if(ftitem != '$') M[{aProduction.first,ftitem}]=formula;
else for(char fwitem:follow[aProduction.first]) M[{aProduction.first, fwitem}]=formula;
}
}
}
unordered_set<char> FIRST(const string& txt){
unordered_set<char> res;
for(char ch : txt){
unordered_set<char> cur = first[ch];
for(char item : cur) res.insert(item);
if(cur.find('$')==cur.end()) return res;
}
return res;
}
static int tableSize(unordered_map<char,unordered_set<char>> & table){
int res=0;
for(const pair<const char, unordered_set<char>>& map:table) res+=map.second.size();
return res;
}
char startchar;
unordered_map<char,unordered_set<char>> first,follow;
unordered_map<char,vector<string>> production;
unordered_set<char> vt;
map<pair<char,char>,string> M; //pair不能作为无序表的key
};
int main(){
LL1Analyzer ll1Analyzer("D://2019215055LL(1)//grammar.txt");
ll1Analyzer.solve("i*i+i");
}
本文介绍了一次通过(LL(1))预测分析的原理,并提供了使用C++实现的清晰代码示例,无需额外注释即可理解。
&spm=1001.2101.3001.5002&articleId=122124979&d=1&t=3&u=cd78b5b1b8074b459fa1cd30a0c69779)
1万+

被折叠的 条评论
为什么被折叠?



