c++实现LL1文法

港控/mmm° 2023-06-12 11:25 79阅读 0赞

c++实现LL1文法

      • 简介
      • 参考代码
      • 测试
        • 输入数据
        • 截屏

简介

利用c++计算文法的firsr,follow,select 集合,然后判断文法是否为LL1文法,并构造预测分析表,对输入字符串进行分析

参考代码

  1. #include <iostream>
  2. #include <map>
  3. #include <vector>
  4. #include <set>
  5. #include <list>
  6. #include <cstdio>
  7. #include <iomanip>
  8. using namespace std;
  9. typedef char grammarType;
  10. grammarType start, S; //开始符号,S用来作为输入
  11. map<grammarType, int> ter; //终结符集合
  12. vector<grammarType> terInx; //通过索引查找终结符
  13. map<grammarType, int> nonter; //非终结符集合
  14. vector<grammarType> nontInx; //通过索引查找非终结符
  15. vector<grammarType> language; //需要进行分析的语言,即输入字符串
  16. int terNum, nontNum, proSize, Lsize; //终结符数目,非终结符数目,产生式数目,语言的长度
  17. struct Production
  18. {
  19. int leftPart; //左部非终结符的索引
  20. vector<int> rightPart; // 右边产生式索引
  21. vector<bool> flag; //标记右边相关产生式是终结符(false),非终结符(false)
  22. };
  23. vector<Production> pro; //产生式
  24. vector<int> *nontPro; // 各个非终结符的产生式的集合
  25. vector<bool> proEmpty; //记录各个产生式能否推出空 true能,false不能
  26. set<int> *First; //各个非终结符的First集合
  27. #define FirstIt(x) for (itSet = First[(x)].begin(); itSet != First[(x)].end(); ++itSet)
  28. set<int> *Follow; // 各个非终结符的Follow集合
  29. #define FollowIt(x) for (itSet = Follow[(x)].begin(); itSet != Follow[(x)].end(); ++itSet)
  30. set<int> *Select; //各个产生式的Select的集合
  31. #define SelectIt(x) for (itSet = Select[(x)].begin(); itSet != Select[(x)].end(); ++itSet)
  32. set<int>::iterator itSet; // set迭代集合
  33. struct edge
  34. {
  35. int v, s; //u->v一条边 s代表状态,1 终结符,
  36. edge(int v, int s) : v(v), s(s) { }
  37. }; //利用关系图法求解First
  38. vector<int> *graph; //图
  39. int *inDe; //计算入度
  40. vector<int> top; //定义出栈顺序,即计算顺序
  41. vector<int> nontEmpty; //能否推出空,0未定,1代表是,2代表否
  42. vector<int> *analyzeTable; //构造LL1文法的预测分析表
  43. struct Sign
  44. {
  45. int Inx;
  46. bool flag; //符合索引 表示文法分析栈中的字符是否为非终结符 true 非终结符
  47. Sign(int a, bool b) : Inx(a), flag(b) { }
  48. Sign() { }
  49. };
  50. vector<Sign> analysisStack; //用数组模拟LL1文法分析栈
  51. #define out(width, str) cout << setw((width)) << setiosflags(ios::left) << ((str))
  52. void getEmpty(); //求非终结符能否推出空集
  53. void geFirst(); //计算文法First集合
  54. void getFollow(); //计算文法Follow集合
  55. void getSelect(); //计算产生式的Select集合
  56. bool judegLL1(); //判断是否为LL1文法
  57. void getAnalyzeTable(); //得到LL1文法的预测分析表
  58. void analysis(); //对所得语言进行分析
  59. int main()
  60. {
  61. cout << "请输入文法开始符合:";
  62. cin >> start;
  63. cout << "请输入非终结符的数目:";
  64. cin >> nontNum;
  65. First = new set<int>[nontNum];
  66. Follow = new set<int>[nontNum];
  67. nontPro = new vector<int>[nontNum];
  68. cout << "请依次输入非终结符:";
  69. for (int i = 0; i < nontNum; ++i)
  70. {
  71. cin >> S;
  72. nonter[S] = i;
  73. nontInx.push_back(S);
  74. }
  75. cout << "请输入终结符的数目:";
  76. cin >> terNum;
  77. cout << "请依次输入终结符:(用二个符合表示空和结束符并放在末尾)";
  78. for (int i = 0; i < terNum; ++i)
  79. {
  80. cin >> S;
  81. ter[S] = i;
  82. terInx.push_back(S);
  83. }
  84. cout << "请依次输入产生式的数目:";
  85. cin >> proSize;
  86. Select = new set<int>[proSize];
  87. proEmpty.insert(proEmpty.begin(), proSize, false);
  88. cout << "请依次输入产生式:";
  89. int t;
  90. Production p;
  91. for (int i = 0; i < proSize; ++i)
  92. {
  93. cin >> S >> t;
  94. p.leftPart = nonter[S];
  95. nontPro[p.leftPart].push_back(i);
  96. for (int j = 0; j < t; ++j)
  97. {
  98. cin >> S;
  99. if (nonter.find(S) != nonter.end())
  100. {
  101. p.rightPart.push_back(nonter[S]);
  102. p.flag.push_back(true);
  103. }
  104. else
  105. {
  106. p.rightPart.push_back(ter[S]);
  107. p.flag.push_back(false);
  108. }
  109. }
  110. pro.push_back(p);
  111. p.rightPart.clear();
  112. p.flag.clear();
  113. }
  114. getEmpty();
  115. geFirst();
  116. getFollow();
  117. getSelect();
  118. if (judegLL1() == false)
  119. return 0;
  120. getAnalyzeTable();
  121. cout << "请输入要分析的语言的长度: ";
  122. cin >> Lsize;
  123. cout << "请输入要分析的语言(带输入结束符):";
  124. for (int i = 0; i < Lsize; ++i)
  125. {
  126. cin >> S;
  127. language.push_back(S);
  128. }
  129. analysis();
  130. }
  131. void getEmpty()
  132. {
  133. nontEmpty.clear();
  134. nontEmpty.insert(nontEmpty.begin(), nontNum, 0); //初始化
  135. vector<int> nonProNum(nontNum, 0);
  136. list<int> wait;
  137. int nul = terNum - 2, j, i, ltmp;
  138. for (int i = 0; i < proSize; ++i)
  139. {
  140. for (j = 0, ltmp = pro[i].leftPart; j < pro[i].flag.size(); ++j)
  141. {
  142. if (pro[i].flag[j] == false && pro[i].rightPart[j] == nul)
  143. nontEmpty[ltmp] = 1;
  144. if (pro[i].flag[j] == false)
  145. break;
  146. }
  147. if (j == pro[i].flag.size())
  148. {
  149. wait.push_front(i);
  150. nonProNum[ltmp]++;
  151. }
  152. }
  153. for (int i = 0; i < nontNum; ++i)
  154. {
  155. if (nontEmpty[i] == 0 && nonProNum[i] == 0)
  156. nontEmpty[i] = 2;
  157. }
  158. list<int>::iterator itlist = wait.begin();
  159. while (itlist != wait.end())
  160. {
  161. ltmp = pro[*itlist].leftPart;
  162. if (nontEmpty[ltmp])
  163. itlist = wait.erase(itlist), nonProNum[ltmp]--;
  164. else
  165. ++itlist;
  166. }
  167. itlist = wait.begin();
  168. while (!wait.empty())
  169. {
  170. if (itlist == wait.end())
  171. itlist = wait.begin();
  172. ltmp = pro[*itlist].leftPart;
  173. if (nontEmpty[ltmp])
  174. {
  175. itlist = wait.erase(itlist);
  176. continue;
  177. }
  178. for (j = 0, i = *itlist; j < pro[i].flag.size(); ++j)
  179. {
  180. if (nontEmpty[pro[i].rightPart[j]] == 2)
  181. {
  182. itlist = wait.erase(itlist);
  183. nonProNum[ltmp]--;
  184. if (nonProNum[ltmp] == 0)
  185. nontEmpty[ltmp] = 2;
  186. break;
  187. }
  188. else if (nontEmpty[pro[i].rightPart[j]] == 0)
  189. {
  190. itlist++;
  191. break;
  192. }
  193. }
  194. if (j == pro[i].flag.size())
  195. {
  196. nontEmpty[ltmp] = 1;
  197. itlist = wait.erase(itlist);
  198. }
  199. }
  200. }
  201. void topSort()
  202. {
  203. int *sta = new int[nontNum];
  204. int p = 0, v, u;
  205. top.clear();
  206. for (int i = 0; i < nontNum; ++i)
  207. if (inDe[i] == 0)
  208. sta[p++] = i;
  209. while (p)
  210. {
  211. v = sta[--p];
  212. top.push_back(v);
  213. for (int i = 0; i < graph[v].size(); ++i)
  214. {
  215. u = graph[v][i];
  216. inDe[u]--;
  217. if (!inDe[u])
  218. sta[p++] = u;
  219. }
  220. }
  221. }
  222. void geFirst()
  223. {
  224. int i, j, ltmp, rtmp;
  225. delete[] graph;
  226. graph = new vector<int>[nontNum];
  227. delete[] inDe;
  228. inDe = new int[nontNum];
  229. for (i = 0; i < nontNum; ++i)
  230. inDe[i] = 0;
  231. for (i = 0; i < proSize; ++i)
  232. {
  233. for (j = 0, ltmp = pro[i].leftPart; j < pro[i].flag.size(); ++j)
  234. {
  235. rtmp = pro[i].rightPart[j];
  236. if (pro[i].flag[j])
  237. {
  238. graph[rtmp].push_back(ltmp);
  239. inDe[ltmp]++;
  240. if (nontEmpty[rtmp] == 2)
  241. break;
  242. }
  243. else if (rtmp != terNum - 2)
  244. {
  245. First[ltmp].insert(rtmp);
  246. break;
  247. }
  248. }
  249. }
  250. topSort();
  251. for (i = 0; i < top.size(); ++i)
  252. {
  253. for (ltmp = top[i], itSet = First[ltmp].begin(); itSet != First[ltmp].end(); ++itSet)
  254. {
  255. for (j = 0; j < graph[ltmp].size(); ++j)
  256. First[graph[ltmp][j]].insert(*itSet);
  257. }
  258. }
  259. for (int i = 0; i < nontNum; ++i)
  260. if (nontEmpty[i] == 1)
  261. First[i].insert(terNum - 2);
  262. cout << "各个非终结符的First集为: " << endl;
  263. for (int i = 0; i < nontNum; ++i)
  264. {
  265. cout << "First( " << nontInx[i] << " ) = { ";
  266. FirstIt(i) cout << terInx[*itSet] << " ";
  267. cout << "}\n";
  268. }
  269. }
  270. void getFollow()
  271. {
  272. int i, j, ltmp, rtmp, folFlag;
  273. delete[] graph;
  274. graph = new vector<int>[nontNum];
  275. delete[] inDe;
  276. inDe = new int[nontNum];
  277. for (i = 0; i < nontNum; ++i)
  278. inDe[i] = 0;
  279. Follow[nonter[start]].insert(terNum - 1);
  280. for (i = 0; i < proSize; ++i)
  281. {
  282. folFlag = true;
  283. ltmp = pro[i].leftPart;
  284. for (j = pro[i].flag.size() - 1; j > 0; --j)
  285. {
  286. rtmp = pro[i].rightPart[j];
  287. if (pro[i].flag[j - 1])
  288. {
  289. if (pro[i].flag[j])
  290. {
  291. FirstIt(rtmp) if (*itSet != terNum - 2) Follow[pro[i].rightPart[j - 1]].insert(*itSet);
  292. }
  293. else
  294. Follow[pro[i].rightPart[j - 1]].insert(rtmp), folFlag = false;
  295. }
  296. if (folFlag)
  297. {
  298. graph[ltmp].push_back(rtmp);
  299. inDe[rtmp]++;
  300. if (nontEmpty[rtmp] == 2)
  301. folFlag = false;
  302. }
  303. }
  304. if (pro[i].flag[0] && folFlag)
  305. {
  306. graph[ltmp].push_back(pro[i].rightPart[0]);
  307. inDe[rtmp]++;
  308. }
  309. }
  310. inDe[nonter[start]] = 0;
  311. topSort();
  312. for (i = 0; i < top.size(); ++i)
  313. {
  314. for (ltmp = top[i], itSet = Follow[ltmp].begin(); itSet != Follow[ltmp].end(); ++itSet)
  315. {
  316. for (j = 0; j < graph[ltmp].size(); ++j)
  317. Follow[graph[ltmp][j]].insert(*itSet);
  318. }
  319. }
  320. cout << "各个非终结符的Follow集为: " << endl;
  321. for (i = 0; i < nontNum; ++i)
  322. {
  323. cout << "Follow( " << nontInx[i] << " ) = { ";
  324. FollowIt(i) cout << terInx[*itSet] << " ";
  325. cout << "}\n";
  326. }
  327. }
  328. void getSelect()
  329. {
  330. int i, j, ltmp, rtmp;
  331. for (i = 0; i < proSize; ++i)
  332. {
  333. for (j = 0, ltmp = pro[i].leftPart; j < pro[i].flag.size(); ++j)
  334. {
  335. if (pro[i].flag[j])
  336. {
  337. rtmp = pro[i].rightPart[j];
  338. FirstIt(rtmp) Select[i].insert(*itSet);
  339. if (nontEmpty[rtmp] == 2)
  340. break;
  341. }
  342. else
  343. {
  344. Select[i].insert(pro[i].rightPart[j]);
  345. break;
  346. }
  347. }
  348. if (pro[i].flag[0] == false && pro[i].rightPart[0] == terNum - 2)
  349. {
  350. FollowIt(ltmp) Select[i].insert(*itSet);
  351. proEmpty[i] = true;
  352. }
  353. if (j == pro[i].flag.size())
  354. {
  355. FollowIt(ltmp) Select[i].insert(*itSet);
  356. proEmpty[i] = true;
  357. }
  358. Select[i].erase(terNum - 2);
  359. }
  360. cout << "各个产生式的Select集为: " << endl;
  361. for (i = 0; i < proSize; ++i)
  362. {
  363. cout << "Select( " << nontInx[pro[i].leftPart] << "->";
  364. for (j = 0; j < pro[i].flag.size(); ++j)
  365. if (pro[i].flag[j])
  366. cout << nontInx[pro[i].rightPart[j]];
  367. else
  368. cout << terInx[pro[i].rightPart[j]];
  369. cout << ") = { ";
  370. SelectIt(i) cout << terInx[*itSet] << " ";
  371. cout << "}\n";
  372. }
  373. }
  374. bool judegLL1()
  375. {
  376. for (int i = 0; i < nontNum; ++i)
  377. {
  378. for (int j = 0; j < nontPro[i].size() - 1; ++j)
  379. {
  380. for (int t = j + 1; t < nontPro[i].size(); ++t)
  381. {
  382. if (proEmpty[j] && proEmpty[t])
  383. continue; //两个产生式都能产生空
  384. for (itSet = Select[nontPro[i][j]].begin(); itSet != Select[nontPro[i][j]].end(); ++itSet)
  385. {
  386. if (Select[nontPro[i][t]].find(*itSet) != Select[nontPro[i][t]].end())
  387. {
  388. cout << terInx[*itSet] << "是产生式" << nontPro[i][j] << "和" << nontPro[i][t] << "的Select集合的交集,不是LL1文法\n";
  389. return false;
  390. }
  391. }
  392. }
  393. }
  394. }
  395. return true;
  396. }
  397. void getAnalyzeTable()
  398. {
  399. analyzeTable = new vector<int>[nontNum]; //初始化-1,nontNum-1 表示#
  400. for (int i = 0; i < nontNum; ++i)
  401. analyzeTable[i].insert(analyzeTable[i].begin(), terNum, -1);
  402. for (int i = 0; i < proSize; ++i)
  403. {
  404. SelectIt(i) analyzeTable[pro[i].leftPart][*itSet] = i;
  405. }
  406. cout << "该文法的预测分析表为:\n";
  407. out(10, " ");
  408. string outStr;
  409. for (int i = 0; i < terNum; ++i)
  410. out(10, terInx[i]);
  411. cout << endl;
  412. for (int i = 0; i < nontNum; ++i)
  413. {
  414. out(10, nontInx[i]);
  415. for (int j = 0; j < terNum; ++j)
  416. if (analyzeTable[i][j] == -1)
  417. out(10, " ");
  418. else
  419. {
  420. outStr = "->";
  421. for (int t = analyzeTable[i][j], c = 0; c < pro[t].flag.size(); ++c)
  422. if (pro[t].flag[c])
  423. outStr += nontInx[pro[t].rightPart[c]];
  424. else
  425. outStr += terInx[pro[t].rightPart[c]];
  426. out(10, outStr);
  427. }
  428. cout << endl;
  429. }
  430. }
  431. void analysis()
  432. {
  433. int i = 0, ip = 0, outW = 30;
  434. Sign X;
  435. string outS = "";
  436. out(10, "步骤");
  437. out(outW, "分析栈");
  438. out(outW, "剩余输入串");
  439. out(outW, "所用产生式");
  440. cout << endl;
  441. analysisStack.clear();
  442. analysisStack.push_back(Sign(terNum - 1, false));
  443. analysisStack.push_back(Sign(nonter[start], true)); //对分析栈进行初始化
  444. while (++i)
  445. {
  446. X = analysisStack.back();
  447. analysisStack.pop_back();
  448. if (X.flag == false && X.Inx == terNum - 1)
  449. {
  450. if (terInx[X.Inx] == language[ip])
  451. {
  452. out(10, i);
  453. out(outW, terInx[terNum - 1]);
  454. out(outW, terInx[terNum - 1]);
  455. out(outW, "接受");
  456. cout << "\n";
  457. return;
  458. }
  459. else
  460. {
  461. cout << "你输入的语言该文法无法识别\n";
  462. return;
  463. }
  464. }
  465. else if (X.flag == false)
  466. {
  467. if (terInx[X.Inx] == language[ip])
  468. {
  469. outS = "";
  470. for (int t = 0; t < analysisStack.size(); ++t)
  471. if (analysisStack[t].flag)
  472. outS += nontInx[analysisStack[t].Inx];
  473. else
  474. terInx[analysisStack[t].Inx];
  475. outS += terInx[X.Inx];
  476. out(10, i);
  477. out(outW, outS);
  478. outS = "";
  479. for (int t = ip; t < language.size(); ++t)
  480. outS += language[t];
  481. out(outW, outS);
  482. outS = "";
  483. outS += language[ip];
  484. out(outW, outS + "匹配");
  485. cout << endl;
  486. ++ip;
  487. }
  488. else
  489. {
  490. cout << "你输入的语言该文法无法识别\n";
  491. return;
  492. }
  493. }
  494. else
  495. {
  496. int pos = analyzeTable[X.Inx][ter[language[ip]]];
  497. if (pos == -1)
  498. {
  499. cout << "你输入的语言该文法无法识别\n";
  500. return;
  501. }
  502. outS = "";
  503. for (int t = 0; t < analysisStack.size(); ++t)
  504. if (analysisStack[t].flag)
  505. outS += nontInx[analysisStack[t].Inx];
  506. else
  507. terInx[analysisStack[t].Inx];
  508. outS += terInx[X.Inx];
  509. out(10, i);
  510. out(outW, outS);
  511. outS = "";
  512. for (int t = ip; t < language.size(); ++t)
  513. outS += language[t];
  514. out(outW, outS);
  515. outS = "";
  516. outS += nontInx[X.Inx];
  517. outS += "->";
  518. for (int t = 0; t < pro[pos].flag.size(); ++t)
  519. if (pro[pos].flag[t])
  520. outS += nontInx[pro[pos].rightPart[t]];
  521. else
  522. outS += terInx[pro[pos].rightPart[t]];
  523. out(outW, outS);
  524. cout << endl;
  525. if (pro[pos].flag[0] == false && proEmpty[pos])
  526. continue;
  527. for (int t = pro[pos].flag.size() - 1; t >= 0; --t)
  528. if (pro[pos].flag[t])
  529. analysisStack.push_back(Sign(pro[pos].rightPart[t], true));
  530. else
  531. analysisStack.push_back(Sign(pro[pos].rightPart[t], false));
  532. }
  533. }
  534. }

测试

输入数据

  1. S
  2. 5 S A B C D
  3. 5 a b c @ #
  4. 10
  5. S 2 A B
  6. S 2 b C
  7. A 1 @
  8. A 1 b
  9. B 1 @
  10. B 2 a D
  11. C 2 A D
  12. C 1 b
  13. D 2 a S
  14. D 1 c

截屏

在这里插入图片描述
在这里插入图片描述

发表评论

表情:
评论列表 (有 0 条评论,79人围观)

还没有评论,来说两句吧...

相关阅读

    相关 LL1文法 JAVA

    E文法表达式类 G 定义文法类 LL 文法分析类 , 包含对First,Follow,Select集合的求解以及对表达式的分析函数  Main测试分析程序,并输出结果

    相关 LL(1)文法

    文章目录 预测分析法的工作过程 S\_文法(简单的确定性文法) 什么时候使用$\\epsilon$产生式? 非终结符的后继符号集 产生式的可