软件构造——LL语法分析
Posted smartisn
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了软件构造——LL语法分析相关的知识,希望对你有一定的参考价值。
【实验目的】
通过完成预测分析法的语法分析程序,了解预测分析法和递归子程序法的区别和联系。使了解语法分析的功能,掌握语法分析程序设计的原理和构造方法,训练掌握开发应用程序的基本方法。
【实验内容】
u 根据某一文法编制调试 LL ( 1 )分析程序,以便对任意输入的符号串进行分析。
u 构造预测分析表,并利用分析表和一个栈来实现对上述程序设计语言的分析程序。
u 分析法的功能是利用LL(1)控制程序根据显示栈顶内容、向前看符号以及LL(1)分析表,对输入符号串自上而下的分析过程。
【设计思想】
(1)定义部分:定义常量、变量、数据结构。
(2)初始化:设立LL(1)分析表、初始化变量空间(包括堆栈、结构体、数组、临时变量等);
(3)控制部分:从键盘输入一个表达式符号串;
(4)利用LL(1)分析算法进行表达式处理:根据LL(1)分析表对表达式符号串进行堆栈(或其他)操作,输出分析结果,如果遇到错误则显示错误信息。
【实验要求】
(1)编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
(2)如果遇到错误的表达式,应输出错误提示信息。
(3)画出流程图
实验截图:
代码:
1 Base.sh 2 #ifndef _BASE_H_ 3 #define _BASE_H_ 4 #include <iostream> 5 #include <iomanip> 6 #include <string> 7 #include <vector> 8 #include <set> 9 10 #define maxsize 100 11 12 using namespace std; 13 14 struct node { // 产生式的数据结构 15 char left; 16 string right; 17 }; 18 19 class Base { 20 protected: 21 int T; 22 node production[maxsize]; // 产生式集 23 24 set<char> firstSet[maxsize]; // First集 25 set<char> followSet[maxsize]; // Follow集 26 vector<char> terminalNoEmpty; // 去$(空)的终结符 27 vector<char> terminal; // 终结符 28 vector<char> nonterminal; // 非终结符 29 30 bool isNonterminal(char c); 31 int getIndex(char target); // 获得target在终结符集合中的下标 32 int getNIndex(char target); // 获得target在非终结符集合中的下标 33 void getFirst(char target); // 得到First(target) 34 void getFollow(char target); // 得到Follow(target) 35 36 public: 37 Base() {}; 38 39 void inputAndSolve(); // 处理和求出First和Follow集 40 void displayFirstAndFollow(); // 输出First和Follow集 41 42 }; 43 #endif 44 45 Base.cpp 46 #include "Base.h" 47 48 bool Base::isNonterminal(char c) { // 判断c是否为非终结符 49 if (c >= ‘A‘ && c <= ‘Z‘) 50 return true; 51 return false; 52 } 53 int Base::getNIndex(char target) { // 获得target在非终结符集合中的下标 54 for (int i = 0; i<nonterminal.size(); i++) { 55 if (target == nonterminal[i]) 56 return i; 57 } 58 return -1; 59 } 60 int Base::getIndex(char target) { // 获得target在终结符集合中的下标 61 for (int i = 0; i<terminalNoEmpty.size(); i++) { 62 if (target == terminalNoEmpty[i]) 63 return i; 64 } 65 return -1; 66 } 67 68 void Base::getFirst(char target) { // 求FIRST(target) 69 int countEmpty = 0; // 用于最后判断是否有空 70 int isEmpty = 0; 71 int targetIndex = getNIndex(target); 72 for (int i = 0; i < T; i++) { 73 if (production[i].left == target) { // 匹配产生式左部 74 if (!isNonterminal(production[i].right[0])) { // 对于终结符,直接加入first 75 firstSet[targetIndex].insert(production[i].right[0]); 76 } 77 else { 78 for (int j = 0; j < production[i].right.length(); j++) { // X->Y1..Yj..Yk是一个产生式 79 char Yj = production[i].right[j]; 80 if (!isNonterminal(Yj)) { // Yj是终结符(不能产生空),FIRST(Yj)=Yj加入FIRST(X),不能继续迭代,结束 81 firstSet[targetIndex].insert(Yj); 82 break; 83 } 84 getFirst(Yj);// Yj是非终结符,递归 先求出FIRST(Yj) 85 86 set<char>::iterator it; 87 int YjIndex = getNIndex(Yj); 88 for (it = firstSet[YjIndex].begin(); it != firstSet[YjIndex].end(); it++) { 89 if (*it == ‘$‘) // 遍历查看FIRST(Yj)中是否含有‘$‘(能产生空) 90 isEmpty = 1; 91 else 92 firstSet[targetIndex].insert(*it);//将FIRST(Yj)中的非$就加入FIRST(X) 93 } 94 if (isEmpty == 0) // Yj不能产生空, 迭代结束 95 break; 96 else { // Yj能产生空 97 countEmpty += isEmpty; 98 isEmpty = 0; 99 } 100 } 101 if (countEmpty == production[i].right.length())//所有右部first(Y)都有$(空),将$加入FIRST(X)中 102 firstSet[getNIndex(target)].insert(‘$‘); 103 } 104 } 105 } 106 } 107 108 void Base::getFollow(char target) { // 求FOLLOW(target) 109 int targetIndex = getNIndex(target); 110 for (int i = 0; i<T; i++) { 111 int index = -1; 112 int len = production[i].right.length(); 113 for (int j = 0; j < len; j++) { // 寻找target在产生式中的位置index 114 if (production[i].right[j] == target) { 115 index = j; 116 break; 117 } 118 } 119 if (index != -1 && index < len - 1) { // 找到target在产生式中的位置index 120 // 存在A->αBβ, 将FIRST(β)中除了空$之外的所有放入FOLLOW(B)中 121 // 这里B对应target, β对应nxt 122 char nxt = production[i].right[index + 1]; 123 if (!isNonterminal(nxt)) { // β是终结符 FIRST(β)=β,直接插入β 124 followSet[targetIndex].insert(nxt); 125 } 126 else { // β是非终结符 127 int hasEmpty = 0; 128 set<char>::iterator it; 129 int nxtIndex = getNIndex(nxt); // 插入FIRST(β)中除了空$之外的所有 130 for (it = firstSet[nxtIndex].begin(); it != firstSet[nxtIndex].end(); it++) { 131 if (*it == ‘$‘) 132 hasEmpty = 1; 133 else 134 followSet[targetIndex].insert(*it); 135 } 136 137 if (hasEmpty && production[i].left != target) { // 存在A->αBβ且FIRST(β)->$ 138 // FOLLOW(A)放在FOLLOW(B)中 139 getFollow(production[i].left); 140 set<char>::iterator it; 141 char tmp = production[i].left; 142 int tmpIndex = getNIndex(tmp); 143 for (it = followSet[tmpIndex].begin(); it != followSet[tmpIndex].end(); it++) 144 followSet[targetIndex].insert(*it); 145 } 146 } 147 } 148 else if (index != -1 && index == len - 1 && target != production[i].left) { // 存在A->αB ,FOLLOW(A)放在FOLLOW(B)中 149 getFollow(production[i].left); 150 set<char>::iterator it; 151 char tmp = production[i].left; 152 int tmpIndex = getNIndex(tmp); 153 for (it = followSet[tmpIndex].begin(); it != followSet[tmpIndex].end(); it++) 154 followSet[targetIndex].insert(*it); 155 } 156 } 157 } 158 159 void Base::inputAndSolve() { // 处理和求出First和Follow集 160 string s; 161 cout << "输入的产生式的个数:" << endl; 162 cin >> T; 163 cout << "输入的产生式:" << endl; 164 for (int index = 0; index < T; index++) { // 处理每一个产生式 165 cin >> s; 166 string temp = ""; // 存储去掉空格的产生式 167 for (int i = 0; i < s.length(); i++) { // 去掉产生式中的‘ ‘ 168 if (s[i] != ‘ ‘) 169 temp += s[i]; 170 } 171 production[index].left = temp[0]; // 产生式的左部 172 for (int i = 3; i<temp.length(); i++) // 产生式的右部 173 production[index].right += temp[i]; 174 175 for (int i = 0; i < temp.length(); i++) { // 存储所有终结符和非终结符 176 if (i == 1 || i == 2) continue; // 跳过产生符号-> 177 if (isNonterminal(temp[i])) { //插入一个非终结符 178 int flag = 0; 179 for (int j = 0; j < nonterminal.size(); j++) { 180 if (nonterminal[j] == temp[i]) { 181 flag = 1; 182 break; 183 } 184 } 185 if (!flag) nonterminal.push_back(temp[i]); 186 } 187 else { //插入一个终结符 188 int flag = 0; 189 for (int j = 0; j < terminal.size(); j++) { 190 if (terminal[j] == temp[i]) { 191 flag = 1; 192 break; 193 } 194 } 195 if (!flag) terminal.push_back(temp[i]); 196 } 197 } 198 } 199 terminal.push_back(‘#‘); 200 201 for (int i = 0; i < terminal.size(); i++) { // 存储没有$符号的终结符 202 if (terminal[i] != ‘$‘) 203 terminalNoEmpty.push_back(terminal[i]); 204 } 205 206 // 获得first集 207 for (int i = 0; i < nonterminal.size(); i++) { 208 getFirst(nonterminal[i]); 209 } 210 211 // 获得follow集 212 for (int i = 0; i < nonterminal.size(); i++) { 213 if (i == 0) // 开始符号, 先加入结束符号 214 followSet[0].insert(‘#‘); 215 getFollow(nonterminal[i]); 216 } 217 } 218 219 void Base::displayFirstAndFollow() { // 输出First和Follow集 220 for (int aa = 0; aa < 10; aa++) 221 { 222 cout << "*********"; 223 } 224 cout << " 欢迎使用周博 20173599 LL1语法分析器(以下是First集合和Follow集合)" << endl; 225 cout << "FIRST集合" << endl; 226 for (int i = 0; i<nonterminal.size(); i++) { 227 cout << nonterminal[i] << ": "; 228 set<char>::iterator it; 229 for (it = firstSet[i].begin(); it != firstSet[i].end(); it++) 230 cout << *it << " "; 231 cout << endl; 232 } 233 cout << endl; 234 235 cout << "FOLLOW集合" << endl; 236 for (int i = 0; i<nonterminal.size(); i++) { 237 cout << nonterminal[i] << ": "; 238 set<char>::iterator it; 239 for (it = followSet[i].begin(); it != followSet[i].end(); it++) 240 cout << *it << " "; 241 cout << endl; 242 } 243 cout << endl; 244 } 245 LL1.h 246 247 #include"Base.h" 248 249 #define maxsize 100 250 #ifndef _LL1_H_ 251 #define _LL1_H_ 252 using namespace std; 253 254 class LL1 : public Base { 255 private: 256 vector<char> analyStack; // 分析栈 257 vector<char> leftExpr; // 剩余输入串 258 int tableMap[100][100]; // 预测表 259 260 public: 261 LL1(); 262 263 void getTable(); // 生成预测表 264 void analyExpression(string s); // 分析输入语句s 265 void printPredictTable(); // 输出预测表 266 void getResult(); // 综合处理 267 }; 268 #endif 269 LL1.cpp 270 #include"LL1.h" 271 272 LL1::LL1() { 273 memset(tableMap, -1, sizeof(tableMap)); 274 } 275 276 void LL1::getTable() { 277 for (int index = 0; index < T; index++) { // 对于每个产生式(编号index):A->α 278 int row = getNIndex(production[index].left); 279 int emptyCount = 0; 280 for (int i = 0; i < production[index].right.size(); i++) { // 1) 对FIRST(α)中的每个终结符号a,将index加入(A, a)中 281 char tmp = production[index].right[i]; 282 if (!isNonterminal(tmp)) { // tmp是终结符 283 if (tmp != ‘$‘) 284 tableMap[row][getIndex(tmp)] = index; 285 if (tmp == ‘$‘) { 286 emptyCount++; 287 } 288 break; 289 } 290 else { // tmp是非终结符 291 set<char>::iterator it; 292 int tmpIndex = getNIndex(tmp); 293 // 对FIRST(tmp)中的每个终结符号a,将i加入(A, a)中 294 for (it = firstSet[tmpIndex].begin(); it != firstSet[tmpIndex].end(); it++) { 295 tableMap[row][getIndex(*it)] = index; 296 } 297 if (firstSet[tmpIndex].count(‘$‘) != 0) { // 2) 如果空$在FIRST(tmp)中,继续看α中的下一个符号 298 emptyCount++; 299 } 300 else { 301 break; 302 } 303 } 304 } 305 306 // 2) 如果空$在FIRST(α)中,对FOLLOW(A)中的每个终结符或结束符b,将i加入(A,b)中 307 if (emptyCount == production[index].right.size()) { 308 set<char>::iterator it; 309 for (it = followSet[row].begin(); it != followSet[row].end(); it++) { 310 tableMap[row][getIndex(*it)] = index; 311 } 312 } 313 } 314 } 315 316 void LL1::analyExpression(string s) { 317 318 for (int i = 0; i < s.size(); i++) 319 leftExpr.push_back(s[i]); 320 leftExpr.push_back(‘#‘); 321 322 analyStack.push_back(‘#‘); 323 analyStack.push_back(nonterminal[0]); // 加入开始符号 324 325 while (analyStack.size() > 0) { 326 //cout<<"分析栈:"; 327 string outs = ""; 328 for (int i = 0; i < analyStack.size(); i++) 329 outs += analyStack[i]; 330 cout << setw(15) << outs; 331 332 //cout<<"剩余输入串:"; 333 outs = ""; 334 for (int i = 0; i < leftExpr.size(); i++) 335 outs += leftExpr[i]; 336 cout << setw(15) << outs; 337 338 // 匹配 339 char char1 = analyStack.back(); 340 char char2 = leftExpr.front(); 341 if (char1 == char2 && char1 == ‘#‘) { 342 cout << setw(15) << "Accepted!" << endl; 343 return; 344 } 345 if (char1 == char2) { 346 analyStack.pop_back(); 347 leftExpr.erase(leftExpr.begin()); 348 cout << setw(15) << "匹配:" << char1 << endl; 349 } 350 else if (tableMap[getNIndex(char1)][getIndex(char2)] != -1) { // 预测表中有推倒项,可进行推导 351 int tg = tableMap[getNIndex(char1)][getIndex(char2)]; 352 analyStack.pop_back(); 353 354 if (production[tg].right != "$") { 355 for (int i = production[tg].right.length() - 1; i >= 0; i--) // 注意这里是反向的 356 analyStack.push_back(production[tg].right[i]); 357 } 358 359 cout << setw(15) << "推导:" << production[tg].left << "->" << production[tg].right << endl; 360 } 361 else { // 错误 362 cout << setw(15) << "error!" << endl; 363 return; 364 } 365 } 366 } 367 368 void LL1::printPredictTable() { 369 // 表头 370 for (int aa = 0; aa < 10; aa++) 371 { 372 cout << "*********"; 373 } 374 cout << " 以下是预测分析表" << endl; 375 for (int i = 0; i < terminalNoEmpty.size(); i++) { 376 cout << setw(10) << terminalNoEmpty[i]; 377 } 378 cout << endl; 379 for (int i = 0; i < nonterminal.size(); i++) { 380 cout << nonterminal[i] << ": "; 381 for (int j = 0; j < terminalNoEmpty.size(); j++) { 382 if (tableMap[i][j] == -1) 383 cout << setw(10) << " "; 384 else 385 cout << setw(10) << production[tableMap[i][j]].right; 386 } 387 cout << endl; 388 } 389 cout << endl; 390 } 391 392 void LL1::getResult() { 393 inputAndSolve(); 394 displayFirstAndFollow(); 395 getTable(); 396 printPredictTable(); 397 //栈匹配 398 string ss; 399 cout << "请输入符号串:" << endl; 400 cin >> ss; 401 for (int aa = 0; aa < 10; aa++) 402 { 403 cout << "*********"; 404 } 405 cout << " 句子" << ss << "分析过程" << endl; 406 cout << setw(15) << "分析栈" << setw(15) << "剩余输入串" << setw(15) << "推导式" << endl; 407 analyExpression(ss); 408 409 } 410 411 412 Main.cpp 413 #include "LL1.h" 414 #include<stdlib.h> 415 416 int main() { 417 // $表示空, #表示终止 418 LL1 res; 419 res.getResult(); 420 system("pause"); 421 return 0; 422 }
以上是关于软件构造——LL语法分析的主要内容,如果未能解决你的问题,请参考以下文章