编译器构造中自底向上的LALR语法分析的语法分析表生成的实现
Posted wskit
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了编译器构造中自底向上的LALR语法分析的语法分析表生成的实现相关的知识,希望对你有一定的参考价值。
提示:阅读本文需掌握编译原理的相关基础知识
本文中使用C++语言系统地实现了龙书中LALR(1)语法分析表的构造算法,首先计算增广文法的LR(0)项集族,每一个项集只包含内核项,计算过程中自动生成了LR(0)自动机,该自动机使用基于十字链表存储结构的有向图表示。然后通过确定自发生成和传播的向前看符号算法计算各LR(0)内核项集自发生成的向前看符号(增广文法新增产生式的向前看符号不包括在内)并确定LR(0)内核项集之间向前看符号的传播关系。最后一遍扫描前将为增广文法新增产生式添加向前看符号即输入结束符$,然后传播向前看符号直到不能传播为止,扫描结束后就生成了LALR(1)内核项集族。随后调用函数计算各LALR(1)项集的非内核项集确定LALR(1)项集族,并得到LALR(1)自动机。最后根据LALR(1)自动机填写LALR(1)语法分析表完成语法分析表的生成工作。
程序测试用例为博主自行编写的正则表达式文法(文法部分地方写得较别扭,而且并非反映正则表达式全部特性的文法,对正反向预查的支持存在一些问题,请读者见谅),由于文法保存在文本中,需要由计算机读入分析,为了便于计算机理解需要将书写格式标准化,博主自行设计了书写格式,具体如下:
#1b 非终结符 非终结符 ---- #1e (非终结符号集合)
#2b 终结符 终结符 ---- #2e (终结符号集合)
#3b 增广文法开始符号 原文法开始符号 #3e
#4b
#b 非终结符(产生式头) $1($2) 非终结符或终结符 $1($2) 非终结符或终结符 ---- #e (产生式体) ($1标志非终结符,$2标志终结符,第一个产生式必须为增广产生式,第二个产生式必须为原文法以原文法开始符号为头的产生式)
----
#4e
其中省略号表示相同格式子项的重复出现,按照以上格式书写的文法(该文法修改了无数遍,说多了都是泪)为:
#1b S‘ S preSurvey E T M F G outSquare B V C B‘ inSquare inSquareRange #1e
#2b \ SPECTRANMETA POSITIVE-SURE-PRE POSITIVE-NEGA-PRE NEGATIVE-SURE-PRE NEGATIVE-NEGA-PRE ) | CLOSURE ? GIVEN LBOUND ULBOUND CLOSURE-NONGREEDY LBOUND-NONGREEDY ULBOUND-NONGREEDY CAP NONPRECAP SPECTRAN TRANMETA UPPERALPHA LOWERALPHA DIGIT SPECMETA REVERSEREF ^ [ ] - OTHERMETA $ #2e
#3b S‘ S #3e
#4b
#b S‘ $1 S #e
#b S $1 E #e
#b S $1 preSurvey #e
#b preSurvey $1 E $2 POSITIVE-SURE-PRE $1 E $2 ) #e
#b preSurvey $1 E $2 POSITIVE-NEGA-PRE $1 E $2 ) #e
#b preSurvey $2 NEGATIVE-SURE-PRE $1 E $2 ) $1 E #e
#b preSurvey $2 NEGATIVE-NEGA-PRE $1 E $2 ) $1 E #e
#b E $1 E $2 | $1 T #e
#b E $1 T #e
#b T $1 T $1 M #e
#b T $1 M #e
#b M $1 M $2 CLOSURE #e
#b M $1 M $2 ? #e
#b M $1 M $2 GIVEN #e
#b M $1 M $2 LBOUND #e
#b M $1 M $2 ULBOUND #e
#b M $1 M $2 CLOSURE-NONGREEDY #e
#b M $1 M $2 LBOUND-NONGREEDY #e
#b M $1 M $2 ULBOUND-NONGREEDY #e
#b M $1 F #e
#b F $2 CAP $1 E $2 ) #e
#b F $1 G #e
#b F $2 NONPRECAP $1 E $2 ) #e
#b F $1 outSquare #e
#b outSquare $2 SPECTRAN #e
#b outSquare $2 TRANMETA #e
#b outSquare $2 \ #e
#b outSquare $2 SPECTRANMETA #e
#b outSquare $2 UPPERALPHA #e
#b outSquare $2 LOWERALPHA #e
#b outSquare $2 DIGIT #e
#b outSquare $2 SPECMETA #e
#b outSquare $2 REVERSEREF #e
#b outSquare $2 ^ #e
#b G $2 [ $1 B $1 V $1 C $2 ] #e
#b V $2 ^ #e
#b V #e
#b B $1 B $1 B‘ #e
#b B $1 B‘ #e
#b B‘ $1 V $1 inSquareRange $2 - $1 inSquareRange #e
#b inSquareRange $2 SPECTRAN #e
#b inSquareRange $2 SPECMETA #e
#b inSquareRange $2 OTHERMETA #e
#b inSquareRange $2 UPPERALPHA #e
#b inSquareRange $2 LOWERALPHA #e
#b inSquareRange $2 DIGIT #e
#b inSquareRange $2 CLOSURE #e
#b inSquareRange $2 \ #e
#b inSquareRange $2 SPECTRANMETA #e
#b inSquareRange $2 ? #e
#b inSquareRange $2 CAP #e
#b inSquareRange $2 | #e
#b inSquareRange $2 ) #e
#b C $1 C $1 inSquare #e
#b C $1 inSquare #e
#b inSquare $1 inSquareRange #e
#b inSquare $2 NONPRECAP #e
#b inSquare $2 POSITIVE-SURE-PRE #e
#b inSquare $2 POSITIVE-NEGA-PRE #e
#b inSquare $2 NEGATIVE-SURE-PRE #e
#b inSquare $2 NEGATIVE-NEGA-PRE #e
#b inSquare $2 ULBOUND #e
#b inSquare $2 LBOUND #e
#b inSquare $2 ULBOUND-NONGREEDY #e
#b inSquare $2 LBOUND-NONGREEDY #e
#b inSquare $2 CLOSURE-NONGREEDY #e
#b inSquare $2 GIVEN #e
#b G $2 [ $1 B $2 ] #e
#b G $2 [ $1 V $1 C $2 ] #e
#4e
#1b和#1e之间的部分为文法非终结符,#2b和#2e之间的部分为文法终结符,S‘为增广文法开始符,S为原文法开始符
#4b和#4e之间的部分为产生式,紧跟于#b之后的是产生式头,随后为产生式体, $2表示紧跟其后的文法符号为终结符,$1表示紧跟其后的文法符号为非终结符,所有这些构成了对上下文无关文法的完整描述。这里非终结符、终结符以及产生式的含义博主会在将来发布的有关构建正则表达式引擎的文章中详解,现在只需着眼于文法本身,不必关心它们的具体含义。
需要另外说明的是,文法设计不当会导致一些异常现象的发生,例如如果把以上文法第三道产生式的产生式头的非终结符S改为F(这样就允许了预查表达式任意的自嵌套),程序会在计算follow集时陷入死循环,原因是修改过的文法第6,7道产生式直接导致程序在计算出非终结符E的follow集前必须先计算出E的follow集,导致循环计算,这样计算follow集时会陷入死循环。可以验证,如果去掉产生式6、7程序就可以正常运行并输出结果(但是存在语法分析动作冲突)。
下面贴出代码,代码只有1500多行不算多,称不上严格意义的项目,没有放在github上的必要,就在博客园上分享吧。
代码清单(C++):
1 #include "pch.h" 2 #include <iostream> 3 #include <string> 4 #include <vector> 5 #include <map> 6 #include <set> 7 #include <tuple> 8 #include <memory> 9 #include <functional> 10 #include <deque> 11 #include <fstream> 12 #include <cctype> 13 #include <stack> 14 #include <algorithm> 15 #include <list> 16 #include "Priority_Queue.h" 17 #include "assistfunction.h" 18 using namespace std; //注意.被定义为匹配任意字符,实际上应为除/r,/n以外的任意字符,单词被定义为大小写字母序列,实际上应为字母、数字和下划线组成的序列,行结束符被定义为/r/n,只适合windows系统 19 20 template <typename V, typename E> //V,E必须定义拷贝构造函数和复制赋值运算符以及析构函数 21 class Graph //有向图类,存储结构为十字链表 22 { 23 friend class RELALRParsing; 24 public: 25 class GraphVertexNode; 26 struct GraphEdgeNode //边节点类 27 { 28 typename vector<GraphVertexNode *>::size_type head = 0; //弧头对应顶点 29 typename vector<GraphVertexNode *>::size_type tail = 0; //弧尾对应顶点 30 E *Edgedatafield = nullptr; //指向边节点数据域的指针 31 GraphEdgeNode *sameheadptr = nullptr; //指向弧头相同的下一个边节点 32 GraphEdgeNode *sametailptr = nullptr; //指向弧尾相同的下一个边节点 33 34 GraphEdgeNode() = default; 35 GraphEdgeNode(typename vector<GraphVertexNode *>::size_type sh, typename vector<GraphVertexNode *>::size_type st, E *Edge) :head(sh), tail(st), Edgedatafield(Edge) {} 36 ~GraphEdgeNode() { delete Edgedatafield; } 37 }; 38 39 struct GraphVertexNode 40 { 41 typename vector<GraphVertexNode *>::size_type number = 0; //顶点序号 42 V *Vertexdatafield = nullptr; //指向顶点数据域的指针 43 GraphEdgeNode *firstheadptr = nullptr; //指向以顶点为弧头的第一个边节点 44 GraphEdgeNode *firsttailptr = nullptr; //指向以顶点为弧尾的第一个边节点 45 GraphVertexNode *seilring = nullptr; //如果顶点上有自环,该指针指向顶点本身,否则为空 46 E *Edgeseilring = nullptr; //指向附着在顶点上的自环边数据域的指针 47 48 GraphVertexNode() = default; 49 GraphVertexNode(typename vector<GraphVertexNode *>::size_type num, V *Ver) :Vertexdatafield(Ver), number(num) {} 50 ~GraphVertexNode() { delete Vertexdatafield; delete Edgeseilring; } 51 }; 52 53 Graph() = default; 54 Graph(typename vector<GraphVertexNode *>::size_type n) :SetOfVertex(n, nullptr) {} //将SetOfVertex初始化为大小为n的顶点数组,数组元素中指向顶点的指针为空 55 virtual ~Graph(); 56 Graph<V, E> *Copy(); //拷被作为目的对象的有向图对象,返回指向拷贝得到的有向图的指针 57 typename vector<typename Graph<V, E>::GraphVertexNode *>::size_type addVertex(V *vertex); //向有向图中新增一个顶点,该顶点数据域为vertex指向内容,返回新增的顶点序号 58 bool addEdge(typename vector<GraphVertexNode *>::size_type vertex1, typename vector<GraphVertexNode *>::size_type vertex2, E *edge); //向有向图中添加以vertex1为弧尾,vertex2为弧头的边,vertex1,vertex2必须存在,可以相等,添加成功返回true,否则返回false 59 Graph<V, E> *merge(Graph<V, E>& Bemerged, bool copyOrNot); //将作为目的对象的有向图和Bemerged合并,copyOrNot=true则拷贝目的对象并将Bemerged副本和目的对象副本合并,返回合并后新图指针,否则将Bemerged副本直接合并至目的对象,返回nullptr 60 typename vector<GraphVertexNode *>::size_type getVertexNum() { return SetOfVertex.size(); } //返回图中顶点个数 61 void ReversalGraph(); //将作为目的对象的有向图的每条边翻转方向,即调换弧头和弧尾 62 63 protected: 64 vector<GraphVertexNode *> SetOfVertex; //有向图顶点构成的集合 65 }; 66 67 template <typename V, typename E> 68 void Graph<V, E>::ReversalGraph() 69 { 70 for (typename vector<GraphVertexNode *>::size_type scan = 0; scan < SetOfVertex.size(); ++scan) 71 { 72 for (GraphEdgeNode *q = SetOfVertex[scan]->firsttailptr; q != nullptr; ) 73 { 74 swap(q->head, q->tail); 75 GraphEdgeNode * temp = q->sametailptr; 76 swap(q->sameheadptr, q->sametailptr); 77 q = temp; 78 } 79 swap(SetOfVertex[scan]->firstheadptr, SetOfVertex[scan]->firsttailptr); 80 } 81 } 82 83 template <typename V, typename E> 84 Graph<V, E> *Graph<V, E>::Copy() 85 { 86 Graph<V, E> *temp = new Graph<V, E>(SetOfVertex.size()); 87 for (typename vector<GraphVertexNode *>::size_type scan = 0; scan < SetOfVertex.size(); ++scan) 88 { 89 temp->SetOfVertex[scan] = new GraphVertexNode(SetOfVertex[scan]->number, new V(*(SetOfVertex[scan]->Vertexdatafield))); 90 if (SetOfVertex[scan]->seilring != nullptr) 91 { 92 temp->SetOfVertex[scan]->seilring = temp->SetOfVertex[scan]; 93 temp->SetOfVertex[scan]->Edgeseilring = new E(*(SetOfVertex[scan]->Edgeseilring)); 94 } 95 GraphEdgeNode *p = nullptr; 96 for (GraphEdgeNode *q = SetOfVertex[scan]->firsttailptr; q != nullptr; q = q->sametailptr) 97 { 98 if (p == nullptr) 99 { 100 p = temp->SetOfVertex[scan]->firsttailptr = new GraphEdgeNode(q->head, q->tail, new E(*(q->Edgedatafield))); 101 } 102 else 103 { 104 p = p->sametailptr = new GraphEdgeNode(q->head, q->tail, new E(*(q->Edgedatafield))); 105 } 106 } 107 } 108 109 for (typename vector<GraphVertexNode *>::size_type scan = 0; scan < SetOfVertex.size(); ++scan) 110 { 111 GraphEdgeNode *p = nullptr; 112 for (GraphEdgeNode *q = SetOfVertex[scan]->firstheadptr; q != nullptr; q = q->sameheadptr) 113 { 114 GraphEdgeNode *m = temp->SetOfVertex[q->tail]->firsttailptr; 115 for (; ; m = m->sametailptr) 116 { 117 if (m->head == scan) 118 break; 119 } 120 121 if (p == nullptr) 122 { 123 p = temp->SetOfVertex[scan]->firstheadptr = m; 124 } 125 else 126 { 127 p = p->sameheadptr = m; 128 } 129 } 130 } 131 return temp; 132 } 133 134 template <typename V, typename E> 135 Graph<V, E>::~Graph() 136 { 137 for (typename vector<GraphVertexNode *>::size_type scan = 0; scan < SetOfVertex.size(); ++scan) 138 { 139 GraphEdgeNode *ptr = nullptr; 140 while (SetOfVertex[scan]->firsttailptr != nullptr) 141 { 142 ptr = SetOfVertex[scan]->firsttailptr; 143 SetOfVertex[scan]->firsttailptr = ptr->sametailptr; 144 SetOfVertex[ptr->head]->firstheadptr = ptr->sameheadptr; 145 delete ptr; 146 } 147 } 148 149 while (SetOfVertex.empty() == false) 150 { 151 delete SetOfVertex.back(); 152 SetOfVertex.pop_back(); 153 } 154 } 155 156 template <typename V, typename E> 157 typename vector<typename Graph<V, E>::GraphVertexNode *>::size_type Graph<V, E>::addVertex(V *vertex) 158 { 159 SetOfVertex.push_back(new GraphVertexNode(SetOfVertex.size(), vertex)); 160 return SetOfVertex.size() - 1; 161 } 162 163 template <typename V, typename E> 164 bool Graph<V, E>::addEdge(typename vector<GraphVertexNode *>::size_type vertex1, typename vector<GraphVertexNode *>::size_type vertex2, E *edge) //vertex1为弧尾,vertex2为弧头 165 { 166 if (vertex1 == vertex2) 167 { 168 SetOfVertex[vertex1]->seilring = SetOfVertex[vertex1]; 169 SetOfVertex[vertex1]->Edgeseilring = new E(*edge); 170 return true; 171 } 172 173 GraphEdgeNode *start = SetOfVertex[vertex1]->firsttailptr; 174 GraphEdgeNode *pre = nullptr; 175 if (start == nullptr) 176 { 177 SetOfVertex[vertex1]->firsttailptr = new GraphEdgeNode(vertex2, vertex1, edge); 178 if (SetOfVertex[vertex2]->firstheadptr == nullptr) 179 { 180 SetOfVertex[vertex2]->firstheadptr = SetOfVertex[vertex1]->firsttailptr; 181 return true; 182 } 183 } 184 else 185 { 186 for (; start != nullptr; ) 187 { 188 if (start->head == vertex2) 189 return false; 190 else if (start->head < vertex2) 191 { 192 pre = start; 193 start = start->sametailptr; 194 } 195 else 196 { 197 if (pre == nullptr) 198 { 199 pre = SetOfVertex[vertex1]->firsttailptr; 200 SetOfVertex[vertex1]->firsttailptr = new GraphEdgeNode(vertex2, vertex1, edge); 201 SetOfVertex[vertex1]->firsttailptr->sametailptr = pre; 202 if (SetOfVertex[vertex2]->firstheadptr == nullptr) 203 { 204 SetOfVertex[vertex2]->firstheadptr = SetOfVertex[vertex1]->firsttailptr; 205 return true; 206 } 207 pre = SetOfVertex[vertex1]->firsttailptr; 208 } 209 else 210 { 211 pre->sametailptr = new GraphEdgeNode(vertex2, vertex1, edge); 212 pre->sametailptr->sametailptr = start; 213 if (SetOfVertex[vertex2]->firstheadptr == nullptr) 214 { 215 SetOfVertex[vertex2]->firstheadptr = pre->sametailptr; 216 return true; 217 } 218 pre = pre->sametailptr; 219 } 220 break; 221 } 222 } 223 if (start == nullptr) 224 { 225 if (pre->head == vertex2) 226 return false; 227 pre->sametailptr = new GraphEdgeNode(vertex2, vertex1, edge); 228 if (SetOfVertex[vertex2]->firstheadptr == nullptr) 229 { 230 SetOfVertex[vertex2]->firstheadptr = pre->sametailptr; 231 return true; 232 } 233 pre = pre->sametailptr; 234 } 235 } 236 237 if (pre == nullptr) 238 { 239 pre = SetOfVertex[vertex1]->firsttailptr; 240 } 241 242 GraphEdgeNode *p = nullptr; 243 for (GraphEdgeNode *start = SetOfVertex[vertex2]->firstheadptr; start != nullptr; ) 244 { 245 if (start->tail < vertex1) 246 { 247 p = start; 248 start = start->sameheadptr; 249 } 250 else 251 { 252 if (p == nullptr) 253 { 254 p = SetOfVertex[vertex2]->firstheadptr; 255 SetOfVertex[vertex2]->firstheadptr = pre; 256 pre->sameheadptr = p; 257 } 258 else 259 { 260 p->sameheadptr = pre; 261 pre->sameheadptr = start; 262 } 263 return true; 264 } 265 } 266 p->sameheadptr = pre; 267 return true; 268 } 269 270 template <typename V, typename E> 271 Graph<V, E> *Graph<V, E>::merge(Graph<V, E>& Bemerged, bool copyOrNot/*true拷贝目的对象,fasle不拷贝,直接合并至目的对象*/) 272 { 273 Graph<V, E> *temp1 = nullptr; 274 typename vector<GraphVertexNode *>::size_type Ca1 = 0; 275 if (copyOrNot) 276 { 277 temp1 = Copy(); 278 Ca1 = temp1->SetOfVertex.size(); 279 } 280 else 281 { 282 Ca1 = SetOfVertex.size(); 283 } 284 285 { 286 Graph<V, E> *temp2 = Bemerged.Copy(); 287 for (typename vector<GraphVertexNode *>::size_type p = 0; p < temp2->SetOfVertex.size(); ++p) 288 { 289 if (copyOrNot) 290 { 291 temp1->SetOfVertex.push_back(temp2->SetOfVertex[p]); 292 } 293 else 294 { 295 SetOfVertex.push_back(temp2->SetOfVertex[p]); 296 } 297 } 298 while (temp2->SetOfVertex.empty() == false) 299 { 300 temp2->SetOfVertex.pop_back(); 301 } 302 delete temp2; 303 } 304 305 for (typename vector<GraphVertexNode *>::size_type p = Ca1; ; ++p) 306 { 307 Graph<V, E>::GraphEdgeNode *q = nullptr; 308 if (copyOrNot) 309 { 310 if (p >= temp1->SetOfVertex.size()) 311 break; 312 temp1->SetOfVertex[p]->number = p; 313 q = temp1->SetOfVertex[p]->firsttailptr; 314 } 315 else 316 { 317 if (p >= SetOfVertex.size()) 318 break; 319 SetOfVertex[p]->number = p; 320 q = SetOfVertex[p]->firsttailptr; 321 } 322 323 for (; q != nullptr; q = q->sametailptr) 324 { 325 q->head = q->head + Ca1; 326 q->tail = q->tail + Ca1; 327 } 328 } 329 330 if (copyOrNot) 331 return temp1; 332 else 333 return nullptr; 334 } 335 336 struct LALRState //LALR状态 337 { 338 struct attribute 339 { 340 int dotposition; //每一个产生式点号位置 341 set<string> ForwardLookingSign; //产生式向前看符号集合 342 attribute() = default; 343 attribute(int dot) : dotposition(dot) {} 344 }; 345 346 map<long, map<int, set<string>>> kernel; //内核项集合,键为产生式编号,值键点号位置,值向前看符号集合 347 map<long, attribute> nonkernel; //非内核项集合, 键为产生式编号 348 }; 349 350 struct LALRTableItem //LALR语法分析表项 351 { 352 enum action { MOVE, REDUCTION, ACCEPT, ERROR } ActionType; //该项的语法分析动作 353 union 354 { 355 vector<Graph<LALRState, string>::GraphVertexNode *>::size_type LALRStateNumber; //该项为移入时应移入的LALR状态 356 long production; //该项为归约时应选则的产生式编号 357 string NULLLable; //该项为报错时表示错误消息的字符串,语法分析程序中为预留,没有填写具体内容 358 }; 359 LALRTableItem() :ActionType(action::ERROR), NULLLable("") {} 360 LALRTableItem(action A, long p) :ActionType(A), production(p) {} 361 LALRTableItem(action A, vector<Graph<LALRState, string>::GraphVertexNode *>::size_type L) :ActionType(A), LALRStateNumber(L) {} 362 LALRTableItem(action A) :NULLLable("") {} 363 LALRTableItem(const LALRTableItem ©); 364 ~LALRTableItem() 365 { 366 if (NULLLable != "") 367 NULLLable.~string(); 368 } 369 }; 370 371 LALRTableItem::LALRTableItem(const LALRTableItem ©) 372 { 373 ActionType = copy.ActionType; 374 switch (copy.ActionType) 375 { 376 case ACCEPT: 377 case ERROR: new (&NULLLable) string(copy.NULLLable); break; 378 case MOVE: LALRStateNumber = copy.LALRStateNumber; break; 379 case REDUCTION: production = copy.production; break; 380 381 } 382 } 383 384 class LALRAutomata : public Graph<LALRState, string> //LALR(1)自动机类,自动机用有向图表示,该有向图来自Graph类 385 { 386 friend class RELALRParsing; 387 friend void output(LALRAutomata &test, ofstream &output); 388 public: 389 struct ProductionBodySymbol //产生式体中的文法符号 390 { 391 string symbol; //终结符或非终结符 392 bool TerminalOrNot; //true终结符,false非终结符 393 ProductionBodySymbol() = default; 394 ProductionBodySymbol(string s, bool T) :symbol(s), TerminalOrNot(T) {} 395 }; 396 LALRAutomata(ifstream &input); 397 static bool isSubSet(const map<string, set<string>> &left, const set<string> &right); //判断right是否为left键集的子集,返回true是返回false不是 398 private: 399 shared_ptr<map<string, set<string>>> calculateFirst(); //构造各非终结符及其first集的映射表 400 shared_ptr<set<string>> calculateFirst(const vector<ProductionBodySymbol> &Pro, vector<ProductionBodySymbol>::size_type left, vector<ProductionBodySymbol>::size_type right); //返回给定文法符号串的first集 401 shared_ptr<map<string, set<string>>> calculateFollow(); //构造各非终结符及其follow集的映射表 402 void calculateClosureLALR(map<long, map<int, set<string>>> &kernelset, map<long, LALRState::attribute> &nonkernelset); //第一个参数内核项集,由内核项集生成非内核项构成的闭包存放至第二个参数,函数功能为计算LALR内核项集闭包,计算开始前nonkernelset会被清空 403 void calculateClosureLR(map<long, map<int, set<string>>> &kernelset, map<long, LALRState::attribute> &nonkernelset); //计算LR(0)内核项集(存放于kernelset)闭包(只包括非内核项),计算结果存放至nonkernelset,计算开始前nonkernelset会被清空 404 void constructLRKernel(); //构造LR(0)项集族,每个项集只包含LR(0)内核项 405 pair<shared_ptr<map<string, int>>, shared_ptr<vector<vector<LALRTableItem>>>> constructLALR(); //构造LALR(1)项集族,返回的pair第一分量为文法符号和LALR语法分析表列表映射关系的智能指针,第二分量为指向LALR语法分析表的智能指针 406 void initgrammar(ifstream &input); //初始化文法各组成要素 407 set<string> Nonterminal; //非终结符号集合(增广文法) 408 set<string> terminnal; //终结符号集合 409 string StartSymbol; //原文法开始符号 410 string AugGraSS; //增广文法开始符号 411 map<long, tuple<string, vector<ProductionBodySymbol>, set<string>>> productionSet; //产生式集合(增广文法),键为产生式编号,值tuple第一分量为非终结符号,第二分量为产生式代表的终结符号和非终结符号的序列,增广文法新增唯一产生式编号必须为1,第三分量为产生式体中非终结符号的集合 412 map<string, set<long>> TerToPro; //键为非终结符,值为对应产生式编号集 413 vector<Graph<LALRState, string>::GraphVertexNode>::size_type start; //LALR(1)自动机开始状态 414 vector<Graph<LALRState, string>::GraphVertexNode>::size_type accept; //读入向前看符号$后结束语法分析的接受态 415 shared_ptr<map<string, set<string>>> first; //指向各非终结符及其first集的映射表 416 shared_ptr<map<string, set<string>>> follow; //指向各非终结符及其follow集的映射表 417 pair<shared_ptr<map<string, int>>, shared_ptr<vector<vector<LALRTableItem>>>> LALRTable; //LALR(1)语法分析动作表 418 419 }; 420 421 void LALRAutomata::initgrammar(ifstream &input) //根据从input读入的文法信息初始化Nonterminal、terminnal、StartSymbol、AugGraSS、productionSet以及TerToPro 422 { 423 enum T { TERMINAL, NONTERMINAL } flag; 424 string current; 425 stack<string> stackforparse; 426 bool TF = true; 427 map<long, tuple<string, vector<ProductionBodySymbol>, set<string>>> ::iterator itp; 428 map<string, set<long>>::iterator itT; 429 while (input >> current) 430 { 431 if (current == "#1b" || current == "#2b" || current == "#3b" || current == "#4b") 432 { 433 stackforparse.push(current); 434 if (current == "#3b") 435 { 436 TF = true; 437 } 438 } 439 else if (current == "#1e" || current == "#2e" || current == "#3e" || current == "#4e") 440 { 441 stackforparse.pop(); 442 } 443 else if (current == "#b" || current == "$1") 444 { 445 if (current == "#b") 446 TF = true; 447 flag = NONTERMINAL; 448 } 449 else if (current == "#e") 450 { 451 continue; 452 } 453 else if (current == "$2") 454 { 455 flag = TERMINAL; 456 } 457 else 458 { 459 if (stackforparse.top() == "#4b") 460 { 461 if (flag == NONTERMINAL) 462 { 463 if (TF == true) 464 { 465 TF = false; 466 if (productionSet.empty()) 467 { 468 itp = productionSet.insert(make_pair(1, tuple<string, vector<ProductionBodySymbol>, set<string>>(current, vector<ProductionBodySymbol>(), set<string>()))).first; 469 TerToPro.insert(make_pair(current, set<long>())).first->second.insert(1); 470 } 471 else 472 { 473 itp = productionSet.insert(make_pair(itp->first + 1, tuple<string, vector<ProductionBodySymbol>, set<string>>(current, vector<ProductionBodySymbol>(), set<string>()))).first; 474 itT = TerToPro.find(current); 475 if (itT == TerToPro.end()) 476 { 477 TerToPro.insert(make_pair(current, set<long>())).first->second.insert(itp->first); 478 } 479 else 480 { 481 itT->second.insert(itp->first); 482 } 483 } 484 } 485 else 486 { 487 get<1>(itp->second).push_back(ProductionBodySymbol(current, false)); 488 get<2>(itp->second).insert(current); 489 } 490 } 491 else 492 { 493 get<1>(itp->second).push_back(ProductionBodySymbol(current, true)); 494 } 495 } 496 else if (stackforparse.top() == "#3b") 497 { 498 if (TF) 499 { 500 TF = false; 501 AugGraSS = current; 502 } 503 else 504 { 505 StartSymbol = current; 506 } 507 } 508 else if (stackforparse.top() == "#2b") 509 { 510 terminnal.insert(current); 511 } 512 else 513 { 514 Nonterminal.insert(current); 515 } 516 } 517 } 518 } 519 520 LALRAutomata::LALRAutomata(ifstream &input) 521 { 522 initgrammar(input); 523 first = calculateFirst(); //计算first集 524 follow = calculateFollow(); //计算follow集 525 constructLRKernel(); 526 LALRTable = constructLALR(); //构造LALR(1)语法分析表 527 } 528 529 pair<shared_ptr<map<string, int>>, shared_ptr<vector<vector<LALRTableItem>>>> LALRAutomata::constructLALR() 530 { 531 shared_ptr<map<string, int>> symbolToIndex = make_shared<map<string, int>>(); 532 { 533 int count = 0; 534 setToMap(terminnal, *symbolToIndex, count); //建立文法符号到语法分析表第二维的映射 535 setToMap(Nonterminal, *symbolToIndex, count); 536 } 537 shared_ptr<vector<vector<LALRTableItem>>>LALRTablePtr = make_shared<vector<vector<LALRTableItem>>>(SetOfVertex.size(), vector<LALRTableItem>((*symbolToIndex).size())); 538 for (vector<Graph<LALRState, string>::GraphVertexNode *>::size_type i = 0; i < SetOfVertex.size(); ++i) //根据LR(0)项集族向语法分析表中填入移入动作 539 { 540 if (SetOfVertex[i]->seilring != nullptr) 541 { 542 map<string, int>::iterator temp = symbolToIndex->find(*(SetOfVertex[i]->Edgeseilring)); 543 (*LALRTablePtr)[i][temp->second].ActionType = LALRTableItem::action::MOVE; 544 (*LALRTablePtr)[i][temp->second].LALRStateNumber = i; 545 } 546 for (Graph<LALRState, string>::GraphEdgeNode *p = SetOfVertex[i]->firsttailptr; p != nullptr; p = p->sametailptr) 547 { 548 map<string, int>::iterator temp = symbolToIndex->find(*(p->Edgedatafield)); 549 (*LALRTablePtr)[i][temp->second].ActionType = LALRTableItem::action::MOVE; 550 (*LALRTablePtr)[i][temp->second].LALRStateNumber = p->head; 551 } 552 } 553 vector<map<long, map<int, map<vector<Graph<LALRState, string>::GraphVertexNode *>::size_type, map<long, set<int>>>>>> FLKSymbolTran; 554 for (vector<Graph<LALRState, string>::GraphVertexNode *>::size_type i = 0; i < SetOfVertex.size(); ++i) //计算各LR(0)内核项自发生成的向前看符号并确定LR(0)内核项集之间向前看符号的传播关系 555 { 556 FLKSymbolTran.push_back(map<long, map<int, map<vector<Graph<LALRState, string>::GraphVertexNode *>::size_type, map<long, set<int>>>>>()); 557 for (map<long, map<int, set<string>>>::iterator p = SetOfVertex[i]->Vertexdatafield->kernel.begin(); p != SetOfVertex[i]->Vertexdatafield->kernel.end(); ++p) 558 { 559 auto x1 = FLKSymbolTran.back().insert(make_pair(p->first, map<int, map<vector<Graph<LALRState, string>::GraphVertexNode *>::size_type, map<long, set<int>>>>())).first; 560 for (map<int, set<string>>::iterator q = p->second.begin(); q != p->second.end(); ++q) 561 { 562 if (q->first != get<1>(productionSet[p->first]).size()) 563 { 564 auto x2 = x1->second.insert(make_pair(q->first, map<vector<Graph<LALRState, string>::GraphVertexNode *>::size_type, map<long, set<int>>>())).first; 565 vector<Graph<LALRState, string>::GraphVertexNode *>::size_type index = (*LALRTablePtr)[i][(*symbolToIndex)[get<1>(productionSet[p->first])[q->first].symbol]].LALRStateNumber; 566 if (get<1>(productionSet[p->first])[q->first].TerminalOrNot == false) 567 { 568 map<long, map<int, set<string>>> kernelitem; 569 kernelitem.insert(make_pair(p->first, map<int, set<string>>())).first->second.insert(make_pair(q->first, set<string>())).first->second.insert("#"); 570 map<long, LALRState::attribute> nonkernelitem; 571 calculateClosureLALR(kernelitem, nonkernelitem); 572 for (map<long, LALRState::attribute>::iterator m = nonkernelitem.begin(); m != nonkernelitem.end(); ++m) 573 { 574 if (m->second.dotposition != get<1>(productionSet[m->first]).size()) 575 { 576 vector<Graph<LALRState, string>::GraphVertexNode *>::size_type index = (*LALRTablePtr)[i][(*symbolToIndex)[get<1>(productionSet[m->first])[m->second.dotposition].symbol]].LALRStateNumber; 577 set<string>::const_iterator temp = m->second.ForwardLookingSign.find("#"); 578 if (temp != m->second.ForwardLookingSign.cend()) 579 { 580 ((SetOfVertex[index]->Vertexdatafield->kernel)[m->first])[m->second.dotposition + 1].insert(m->second.ForwardLookingSign.cbegin(), temp); 581 ((SetOfVertex[index]->Vertexdatafield->kernel)[m->first])[m->second.dotposition + 1].insert(++temp, m->second.ForwardLookingSign.cend()); 582 auto x3 = x2->second.find(index); 583 if (x3 != x2->second.end()) 584 { 585 auto x4 = x3->second.find(m->first); 586 if (x4 != x3->second.end()) 587 { 588 x4->second.insert(m->second.dotposition + 1); 589 } 590 else 591 { 592 x3->second.insert(make_pair(m->first, set<int>())).first->second.insert(m->second.dotposition + 1); 593 } 594 } 595 else 596 { 597 x2->second.insert(make_pair(index, map<long, set<int>>())).first->second.insert(make_pair(m->first, set<int>())).first->second.insert(m->second.dotposition + 1); 598 } 599 } 600 else 601 { 602 ((SetOfVertex[index]->Vertexdatafield->kernel)[m->first])[m->second.dotposition + 1].insert(m->second.ForwardLookingSign.cbegin(), m->second.ForwardLookingSign.cend()); 603 } 604 } 605 } 606 auto x3 = x2->second.find(index); 607 if (x3 != x2->second.end()) 608 { 609 auto x4 = x3->second.find(p->first); 610 if (x4 != x3->second.end()) 611 { 612 x4->second.insert(q->first + 1); 613 } 614 else 615 { 616 x3->second.insert(make_pair(p->first, set<int>())).first->second.insert(q->first + 1); 617 } 618 } 619 else 620 { 621 x2->second.insert(make_pair(index, map<long, set<int>>())).first->second.insert(make_pair(p->first, set<int>())).first->second.insert(q->first + 1); 622 } 623 } 624 else 625 { 626 (x2->second)[index] = map<long, set<int>>(); 627 ((x2->second)[index])[p->first] = set<int>(); 628 ((x2->second)[index])[p->first].insert(q->first + 1); 629 } 630 } 631 } 632 if (x1->second.empty()) 633 { 634 FLKSymbolTran.back().erase(x1); 635 } 636 } 637 } 638 639 (SetOfVertex[start]->Vertexdatafield->kernel[*(TerToPro[AugGraSS].begin())])[0].insert("$"); //为增广文法新增的产生式填写向前看符号输入结束符$,它是自发生成的 640 while (true) //不断扫描所有LR(0)项集传播向前看符号,直到某一轮再也没有向前看符号被传播为止 641 { 642 bool continueTran = false; // 643 for (vector<Graph<LALRState, string>::GraphVertexNode *>::size_type i = 0; i < SetOfVertex.size(); ++i) 644 { 645 if (FLKSymbolTran[i].empty() == false) 646 { 647 map<long, map<int, map<vector<Graph<LALRState, string>::GraphVertexNode *>::size_type, map<long, set<int>>>>>::iterator p1 = FLKSymbolTran[i].begin(); 648 map<long, map<int, set<string>>>::iterator p2 = SetOfVertex[i]->Vertexdatafield->kernel.begin(); 649 while (p1 != FLKSymbolTran[i].end() && p2 != SetOfVertex[i]->Vertexdatafield->kernel.end()) 650 { 651 if (p1->first == p2->first) 652 { 653 map<int, map<vector<Graph<LALRState, string>::GraphVertexNode *>::size_type, map<long, set<int>>>>::iterator q1 = p1->second.begin(); 654 map<int, set<string>>::iterator q2 = p2->second.begin(); 655 while (q1 != p1->second.end() && q2 != p2->second.end()) 656 { 657 if (q1->first == q2->first) 658 { 659 if (q2->second.empty() == false) 660 { 661 for (map<vector<Graph<LALRState, string>::GraphVertexNode *>::size_type, map<long, set<int>>>::iterator w1 = q1->second.begin(); w1 != q1->second.end(); ++w1) 662 { 663 map<long, set<int>>::iterator m1 = w1->second.begin(); 664 map<long, map<int, set<string>>>::iterator m2 = SetOfVertex[w1->first]->Vertexdatafield->kernel.begin(); 665 while (m1 != w1->second.end() && m2 != SetOfVertex[w1->first]->Vertexdatafield->kernel.end()) 666 { 667 if (m1->first == m2->first) 668 { 669 set<int>::const_iterator v1 = m1->second.cbegin(); 670 map<int, set<string>>::iterator v2 = m2->second.begin(); 671 while (v1 != m1->second.cend() && v2 != m2->second.end()) 672 { 673 if (*v1 == v2->first) 674 { 675 set<string>::size_type temp = v2->second.size(); 676 v2->second.insert(q2->second.cbegin(), q2->second.cend()); 677 if (temp != v2->second.size()) 678 { 679 continueTran = true; 680 } 681 ++v1; 682 ++v2; 683 } 684 else if (*v1 < v2->first) 685 { 686 ++v1; 687 } 688 else 689 { 690 ++v2; 691 } 692 } 693 ++m1; 694 ++m2; 695 } 696 else if (m1->first < m2->first) 697 { 698 ++m1; 699 } 700 else 701 { 702 ++m2; 703 } 704 } 705 706 } 707 } 708 ++q1; 709 ++q2; 710 } 711 else if (q1->first < q2->first) 712 { 713 ++q1; 714 } 715 else 716 { 717 ++q2; 718 } 719 } 720 ++p1; 721 ++p2; 722 } 723 else if (p1->first < p2->first) 724 { 725 ++p1; 726 } 727 else 728 { 729 ++p2; 730 } 731 } 732 } 733 } 734 if (continueTran == false) 735 break; 736 } 737 738 for (vector<Graph<LALRState, string>::GraphVertexNode *>::size_type i = 0; i < SetOfVertex.size(); ++i) 739 { 740 calculateClosureLALR(SetOfVertex[i]->Vertexdatafield->kernel, SetOfVertex[i]->Vertexdatafield->nonkernel); //为每个LALR(1)内核项集计算闭包得到LALR(1)项集 741 for (map<long, map<int, set<string>>>::iterator p = SetOfVertex[i]->Vertexdatafield->kernel.begin(); p != SetOfVertex[i]->Vertexdatafield->kernel.end(); ++p) //为LALR(1)语法分析表填入归约动作 742 { 743 for (map<int, set<string>>::iterator q = p->second.begin(); q != p->second.end(); ++q) 744 { 745 if (q->first == get<1>(productionSet[p->first]).size()) 746 { 747 for (set<string>::const_iterator m = q->second.cbegin(); m != q->second.cend(); ++m) 748 { 749 map<string, int>::iterator temp = symbolToIndex->find(*m); 750 if ((*LALRTablePtr)[i][temp->second].ActionType == LALRTableItem::action::MOVE) 751 { 752 cout << "ERROR:移入归约冲突" << endl; 753 cout << "状态" << i << "要求在文法符号" << temp->first << "下移入状态" << (*LALRTablePtr)[i][temp->second].LALRStateNumber; 754 cout << "同时状态" << i << "要求在文法符号" << temp->first << "下用产生式" << p->first << "归约" << endl; 755 continue; 756 } 757 else if ((*LALRTablePtr)[i][temp->second].ActionType == LALRTableItem::action::REDUCTION) 758 { 759 cout << "ERROR:归约归约冲突" << endl; 760 cout << "状态" << i << "要求在文法符号" << temp->first << "下用产生式" << (*LALRTablePtr)[i][temp->second].production << "归约" << endl; 761 cout << "同时状态" << i << "要求在文法符号" << temp->first << "下用产生式" << p->first << "归约" << endl; 762 continue; 763 } 764 (*LALRTablePtr)[i][temp->second].ActionType = LALRTableItem::action::REDUCTION; //移入归约,归约归约冲突处理 765 (*LALRTablePtr)[i][temp->second].production = p->first; 766 } 767 } 768 } 769 } 770 771 for (map<long, LALRState::attribute>::iterator temp = SetOfVertex[i]->Vertexdatafield->nonkernel.begin(); temp != SetOfVertex[i]->Vertexdatafield->nonkernel.end(); ++temp) 772 { 773 if (temp->second.dotposition == 0 && get<1>(productionSet[temp->first]).empty() == true) 774 { 775 for (set<string>::const_iterator m = temp->second.ForwardLookingSign.cbegin(); m != temp->second.ForwardLookingSign.cend(); ++m) 776 { 777 map<string, int>::iterator temp1 = symbolToIndex->find(*m); 778 if ((*LALRTablePtr)[i][temp1->second].ActionType == LALRTableItem::action::MOVE) 779 { 780 cout << "ERROR:移入归约冲突" << endl; 781 cout << "状态" << i << "要求在文法符号" << temp1->first << "下移入状态" << (*LALRTablePtr)[i][temp1->second].LALRStateNumber; 782 cout << "同时状态" << i << "要求在文法符号" << temp1->first << "下用产生式" << temp->first << "归约" << endl; 783 continue; 784 } 785 else if ((*LALRTablePtr)[i][temp1->second].ActionType == LALRTableItem::action::REDUCTION) 786 { 787 cout << "ERROR:归约归约冲突" << endl; 788 cout << "状态" << i << "要求在文法符号" << temp1->first << "下用产生式" << (*LALRTablePtr)[i][temp1->second].production << "归约" << endl; 789 cout << "同时状态" << i << "要求在文法符号" << temp1->first << "下用产生式" << temp->first << "归约" << endl; 790 continue; 791 } 792 (*LALRTablePtr)[i][temp1->second].ActionType = LALRTableItem::action::REDUCTION; //移入归约,归约归约冲突处理 793 (*LALRTablePtr)[i][temp1->second].production = temp->first; 794 } 795 } 796 } 797 } 798 (*LALRTablePtr)[((*LALRTablePtr)[start][(*symbolToIndex)[StartSymbol]].LALRStateNumber)][(*symbolToIndex)["$"]].ActionType = LALRTableItem::action::ACCEPT; //向语法分析表中填入接受项 799 accept = (*LALRTablePtr)[start][(*symbolToIndex)[StartSymbol]].LALRStateNumber; 800 (*LALRTablePtr)[((*LALRTablePtr)[start][(*symbolToIndex)[StartSymbol]].LALRStateNumber)][(*symbolToIndex)["$"]].NULLLable = ""; 801 return { symbolToIndex, LALRTablePtr }; //返回LALR(1)语法分析表 802 } 803 804 void LALRAutomata::constructLRKernel() //计算出的LR(0)项集族保存在继承而来的有向图中 805 { 806 struct Vertex 807 { 808 LALRState *state = new LALRState(); 809 vector<Graph<LALRState, string>::GraphVertexNode *>::size_type index = 0; //LALR状态及其对应序号 810 Vertex(LALRState *s, vector<Graph<LALRState, string>::GraphVertexNode *>::size_type i) :state(s), index(i) {} 811 Vertex(const Vertex ©) 812 { 813 state = new LALRState(*(copy.state)); 814 index = copy.index; 815 } 816 Vertex() = default; 817 ~Vertex() { delete state; } 818 }; 819 deque<Vertex> workqueue; 820 workqueue.push_back(Vertex()); 821 workqueue.back().state->kernel.insert(make_pair(*(TerToPro[AugGraSS].begin()), map<int, set<string>>())).first->second.insert(make_pair(0, set<string>())); 822 start = addVertex(new LALRState(*(workqueue.back().state))); 823 824 while (workqueue.empty() == false) 825 { 826 calculateClosureLR(workqueue.front().state->kernel, workqueue.front().state->nonkernel); 827 map<string, LALRState *> temp; 828 for (map<long, map<int, set<string>>>::iterator p = workqueue.front().state->kernel.begin(); p != workqueue.front().state->kernel.end(); ++p) 829 { 830 for (map<int, set<string>>::iterator p2 = p->second.begin(); p2 != p->second.end(); ++p2) 831 { 832 if (static_cast<vector<ProductionBodySymbol>::size_type>(p2->first) < get<1>(productionSet[p->first]).size()) 833 { 834 map<string, LALRState *>::iterator q = temp.find(get<1>(productionSet[p->first])[p2->first].symbol); 835 if (q == temp.end()) 836 { 837 q = temp.insert(make_pair(get<1>(productionSet[p->first])[p2->first].symbol, new LALRState())).first; 838 } 839 q->second->kernel.insert(make_pair(p->first, map<int, set<string>>())).first->second.insert(make_pair(p2->first + 1, set<string>())); 840 } 841 } 842 } 843 844 for (map<long, LALRState::attribute>::iterator p = workqueue.front().state->nonkernel.begin(); p != workqueue.front().state->nonkernel.end(); ++p) 845 { 846 if (static_cast<vector<ProductionBodySymbol>::size_type>(p->second.dotposition) < get<1>(productionSet[p->first]).size()) 847 { 848 map<string, LALRState *>::iterator q = temp.find(get<1>(productionSet[p->first])[p->second.dotposition].symbol); 849 if (q == temp.end()) 850 { 851 q = temp.insert(make_pair(get<1>(productionSet[p->first])[p->second.dotposition].symbol, new LALRState())).first; 852 } 853 q->second->kernel.insert(make_pair(p->first, map<int, set<string>>())).first->second.insert(make_pair(p->second.dotposition + 1, set<string>())); 854 } 855 } 856 857 858 for (map<string, LALRState *>::iterator p = temp.begin(); p != temp.end(); ) 859 { 860 vector<Graph<LALRState, string>::GraphVertexNode *>::size_type i = 0; 861 for (; i < SetOfVertex.size(); ++i) 862 { 863 map<long, map<int, set<string>>>::iterator left = p->second->kernel.begin(); 864 map<long, map<int, set<string>>>::iterator right = SetOfVertex[i]->Vertexdatafield->kernel.begin(); 865 while (left != p->second->kernel.end() && right != SetOfVertex[i]->Vertexdatafield->kernel.end()) 866 { 867 if (left->first == right->first) 868 { 869 map<int, set<string>>::iterator inleft = left->second.begin(); 870 map<int, set<string>>::iterator inright = right->second.begin(); 871 while (inleft != left->second.end() && inright != right->second.end()) 872 { 873 if (inleft->first == inright->first) 874 { 875 ++inleft; 876 ++inright; 877 } 878 else 879 { 880 break; 881 } 882 } 883 if (inleft != left->second.end() || inright != right->second.end()) 884 break; 885 ++left; 886 ++right; 887 } 888 else 889 { 890 break; 891 } 892 } 893 if (left == p->second->kernel.end() && right == SetOfVertex[i]->Vertexdatafield->kernel.end()) 894 { 895 addEdge(workqueue.front().index, i, new string(p->first)); 896 break; 897 } 898 } 899 if (i == SetOfVertex.size()) 900 { 901 vector<Graph<LALRState, string>::GraphVertexNode *>::size_type s = addVertex(new LALRState(*(p->second))); 902 addEdge(workqueue.front().index, s, new string(p->first)); 903 workqueue.push_back(Vertex(p->second, s)); 904 } 905 p = temp.erase(p); 906 } 907 workqueue.pop_front(); 908 } 909 } 910 911 void LALRAutomata::calculateClosureLR(map<long, map<int, set<string>>> &kernelset, map<long, LALRState::attribute> &nonkernelset) //kernelset的arrtribute属性的ForwardLookingSign为空,nonkernelset同样,由内核项算出的闭包项保存在nonkernelset中 912 { 913 nonkernelset.clear(); 914 deque<pair<long, LALRState::attribute>> workqueue; 915 for (map<long, map<int, set<string>>>::iterator m = kernelset.begin(); m != kernelset.end(); ++m) 916 { 917 for (map<int, set<string>>::iterator m2 = m->second.begin(); m2 != m->second.end(); ++m2) 918 { 919 workqueue.push_back(make_pair(m->first, LALRState::attribute(m2->first))); 920 } 921 } 922 923 while (workqueue.empty() == false) 924 { 925 if (static_cast<vector<ProductionBodySymbol>::size_type>(workqueue.front().second.dotposition) < get<1>(productionSet[workqueue.front().first]).size()) 926 { 927 if (get<1>(productionSet[workqueue.front().first])[workqueue.front().second.dotposition].TerminalOrNot == false) 928 { 929 pair<long, LALRState::attribute> maxp = workqueue.front(); 930 workqueue.pop_front(); 931 for (set<long>::iterator m = TerToPro[get<1>(productionSet[maxp.first])[maxp.second.dotposition].symbol].begin(); m != TerToPro[get<1>(productionSet[maxp.first])[maxp.second.dotposition].symbol].end(); ++m) 932 { 933 map<long, LALRState::attribute>::iterator temp2 = nonkernelset.find(*m); 934 if (temp2 == nonkernelset.end()) 935 { 936 temp2 = nonkernelset.insert(make_pair(*m, LALRState::attribute(0))).first; 937 workqueue.push_back(*temp2); 938 } 939 } 940 continue; 941 } 942 } 943 workqueue.pop_front(); 944 } 945 } 946 947 void LALRAutomata::calculateClosureLALR(map<long, map<int, set<string>>> &kernelset, map<long, LALRState::attribute> &nonkernelset) 948 { 949 nonkernelset.clear(); 950 Priority_Queue<pair<long, LALRState::attribute>> workqueue(function<bool(const pair<long, LALRState::attribute>&, const pair<long, LALRState::attribute>&)>([](const pair<long, LALRState::attribute> &left, const pair<long, LALRState::attribute> &right)->bool {return left.first < right.first; })); //使用lambda表达式根据产生式编号维护优先级队列 951 for (map<long, map<int, set<string>>>::iterator m = kernelset.begin(); m != kernelset.end(); ++m) 952 { 953 for (map<int, set<string>>::iterator m2 = m->second.begin(); m2 != m->second.end(); ++m2) 954 { 955 workqueue.Insert(make_pair(m->first, LALRState::attribute(m2->first))).second->second.ForwardLookingSign.insert(m2->second.cbegin(), m2->second.cend()); 956 } 957 } 958 959 while (workqueue.isEmpty() == false) 960 { 961 if (static_cast<vector<ProductionBodySymbol>::size_type>(workqueue.begin()->second.dotposition) < get<1>(productionSet[workqueue.begin()->first]).size()) 962 { 963 if (get<1>(productionSet[workqueue.begin()->first])[workqueue.begin()->second.dotposition].TerminalOrNot == false) 964 { 965 shared_ptr<set<string>> temp = calculateFirst(get<1>(productionSet[workqueue.begin()->first]), workqueue.begin()->second.dotposition + 1, get<1>(productionSet[workqueue.begin()->first]).size() - 1); 966 if (temp->empty() == true) 967 { 968 temp->insert(workqueue.begin()->second.ForwardLookingSign.cbegin(), workqueue.begin()->second.ForwardLookingSign.cend()); 969 } 970 else 971 { 972 if (*(temp->begin()) == "") 973 { 974 temp->erase(temp->begin()); 975 temp->insert(workqueue.begin()->second.ForwardLookingSign.cbegin(), workqueue.begin()->second.ForwardLookingSign.cend()); 976 } 977 } 978 979 pair<long, LALRState::attribute> maxp = *(workqueue.begin()); 980 workqueue.erase(workqueue.begin()); 981 for (set<long>::iterator m = TerToPro[get<1>(productionSet[maxp.first])[maxp.second.dotposition].symbol].begin(); m != TerToPro[get<1>(productionSet[maxp.first])[maxp.second.dotposition].symbol].end(); ++m) 982 { 983 map<long, LALRState::attribute>::iterator temp2 = nonkernelset.find(*m); 984 if (temp2 == nonkernelset.end()) 985 { 986 temp2 = nonkernelset.insert(make_pair(*m, LALRState::attribute(0))).first; 987 temp2->second.ForwardLookingSign.insert(temp->cbegin(), temp->cend()); 988 workqueue.Insert(*temp2); 989 } 990 else 991 { 992 set<string>::size_type q = temp2->second.ForwardLookingSign.size(); 993 temp2->second.ForwardLookingSign.insert(temp->cbegin(), temp->cend()); 994 if (temp2->second.ForwardLookingSign.size() != q) 995 { 996 Priority_Queue<pair<long, LALRState::attribute>>::iterator q2 = workqueue.Insert(*temp2).second; 997 if (q2 != workqueue.begin()) 998 { 999 --q2; 1000 if (q2->first == temp2->first) 1001 { 1002 if (q2->second.dotposition == 0 && q2->first != *(TerToPro[AugGraSS].begin())) 1003 { 1004 workqueue.erase(q2); 1005 } 1006 } 1007 } 1008 } 1009 } 1010 } 1011 continue; 1012 } 1013 } 1014 workqueue.erase(workqueue.begin()); 1015 } 1016 } 1017 1018 bool LALRAutomata::isSubSet(const map<string, set<string>> &left, const set<string> &right) 1019 { 1020 map<string, set<string>>::const_iterator leftit = left.cbegin(); 1021 set<string>::const_iterator rightit = right.cbegin(); 1022 1023 while (leftit != left.cend() && rightit != right.cend()) 1024 { 1025 if (*rightit < leftit->first) 1026 return false; 1027 else if (*rightit > leftit->first) 1028 { 1029 ++leftit; 1030 } 1031 else 1032 { 1033 ++leftit; 1034 ++rightit; 1035 } 1036 } 1037 1038 if (rightit != right.cend()) 1039 return false; 1040 return true; 1041 1042 } 1043 1044 shared_ptr<map<string, set<string>>> LALRAutomata::calculateFollow() 1045 { 1046 shared_ptr<map<string, set<string>>> result = make_shared<map<string, set<string>>>(); 1047 map<string, pair<set<string>, set<string>>> temp; 1048 { 1049 auto h = temp.insert(make_pair(AugGraSS, pair<set<string>, set<string>>())).first; 1050 h->second.first.insert("$"); 1051 } 1052 1053 for (map<long, tuple<string, vector<ProductionBodySymbol>, set<string>>>::iterator p = productionSet.begin(); p != productionSet.end(); ++p) 1054 { 1055 for (vector<ProductionBodySymbol>::size_type i = 0; i < get<1>(p->second).size(); ++i) 1056 { 1057 if (get<1>(p->second)[i].TerminalOrNot == false) 1058 { 1059 if (i == get<1>(p->second).size() - 1) 1060 { 1061 map<string, pair<set<string>, set<string>>>::iterator it = temp.find(get<1>(p->second)[i].symbol); 1062 if (it == temp.end()) 1063 { 1064 temp.insert(make_pair(get<1>(p->second)[i].symbol, make_pair(set<string>(), set<string>()))).first->second.second.insert(get<0>(p->second)); 1065 } 1066 else 1067 { 1068 it->second.second.insert(get<0>(p->second)); 1069 } 1070 } 1071 else 1072 { 1073 shared_ptr<set<string>> q = calculateFirst(get<1>(p->second), i + 1, get<1>(p->second).size() - 1); 1074 set<string>::iterator w = q->find(""); 1075 map<string, pair<set<string>, set<string>>>::iterator it = temp.find(get<1>(p->second)[i].symbol); 1076 if (w != q->end()) 1077 { 1078 if (it == temp.end()) 1079 { 1080 (it = temp.insert(make_pair(get<1>(p->second)[i].symbol, make_pair(set<string>(), set<string>()))).first)->second.second.insert(get<0>(p->second)); 1081 } 1082 else 1083 { 1084 it->second.second.insert(get<0>(p->second)); 1085 } 1086 it->second.first.insert(q->cbegin(), w); 1087 it->second.first.insert(++w, q->end()); 1088 } 1089 else 1090 { 1091 if (it == temp.end()) 1092 { 1093 temp.insert(make_pair(get<1>(p->second)[i].symbol, make_pair(set<string>(), set<string>()))).first->second.first.insert(q->begin(), q->end()); 1094 } 1095 else 1096 { 1097 it->second.first.insert(q->begin(), q->end()); 1098 } 1099 } 1100 } 1101 } 1102 } 1103 } 1104 1105 for (map<string, pair<set<string>, set<string>>>::iterator p = temp.begin(); p != temp.end(); ) 1106 { 1107 if (p->second.second.empty() == true) 1108 { 1109 result->insert(make_pair(p->first, p->second.first)); 1110 p = temp.erase(p); 1111 } 1112 else 1113 { 1114 if (p->second.second.find(p->first) != p->second.second.end()) 1115 { 1116 p->second.second.erase(p->first); 1117 if (p->second.second.empty() == true) 1118 { 1119 result->insert(make_pair(p->first, p->second.first)); 1120 p = temp.erase(p); 1121 continue; 1122 } 1123 } 1124 ++p; 1125 } 1126 } 1127 1128 while (temp.empty() == false) 1129 { 1130 for (map<string, pair<set<string>, set<string>>>::iterator p = temp.begin(); p != temp.end();) 1131 { 1132 if (isSubSet(*(result), p->second.second)) 1133 { 1134 map<string, set<string>>::iterator m = result->insert(make_pair(p->first, set<string>())).first; 1135 map<string, set<string>>::iterator itleft = result->begin(); 1136 set<string>::const_iterator itright = p->second.second.cbegin(); 1137 while (itleft != result->end() && itright != p->second.second.cend()) 1138 { 1139 if (itleft->first == *itright) 1140 { 1141 m->second.insert(itleft->second.cbegin(), itleft->second.cend()); 1142 ++itleft; 1143 ++itright; 1144 } 1145 else if (itleft->first < *itright) 1146 { 1147 ++itleft; 1148 } 1149 else 1150 { 1151 ++itright; 1152 } 1153 } 1154 m->second.insert(p->second.first.cbegin(), p->second.first.cend()); 1155 p = temp.erase(p); 1156 } 1157 else 1158 { 1159 ++p; 1160 } 1161 } 1162 } 1163 return result; 1164 } 1165 1166 shared_ptr<map<string, set<string>>> LALRAutomata::calculateFirst() 1167 { 1168 shared_ptr<map<long, tuple<string, vector<ProductionBodySymbol>, set<string>>>> temp = make_shared<map<long, tuple<string, vector<ProductionBodySymbol>, set<string>>>>(productionSet); 1169 shared_ptr<map<string, set<string>>> result = make_shared<map<string, set<string>>>(); 1170 1171 for (map<long, tuple<string, vector<ProductionBodySymbol>, set<string>>>::iterator p = temp->begin(); p != temp->end(); ) 1172 { 1173 if (get<2>(p->second).empty() == true) 1174 { 1175 map<string, set<string>>::iterator q = result->find(get<0>(p->second)); 1176 if (q == result->end()) 1177 { 1178 if (get<1>(p->second).empty()) 1179 { 1180 result->insert(make_pair(get<0>(p->second), set<string>())).first->second.insert(""); 1181 } 1182 else 1183 { 1184 result->insert(make_pair(get<0>(p->second), set<string>())).first->second.insert(get<1>(p->second)[0].symbol); 1185 } 1186 } 1187 else 1188 { 1189 if (get<1>(p->second).empty()) 1190 { 1191 q->second.insert(""); 1192 } 1193 else 1194 { 1195 q->second.insert(get<1>(p->second)[0].symbol); 1196 } 1197 } 1198 p = temp->erase(p); 1199 } 1200 else 1201 { 1202 ++p; 1203 } 1204 } 1205 while (true) 1206 { 1207 bool stopOrNot = true; 1208 for (map<long, tuple<string, vector<ProductionBodySymbol>, set<string>>>::iterator p = temp->begin(); p != temp->end(); ++p) 1209 { 1210 if (isSubSet(*result, get<2>(p->second)) == true) 1211 { 1212 for (vector<ProductionBodySymbol>::size_type q = 0; q < get<1>(p->second).size(); ++q) 1213 { 1214 if (get<1>(p->second)[q].TerminalOrNot == true) 1215 { 1216 map<string, set<string>>::iterator v = result->find(get<0>(p->second)); 1217 if (v == result->end()) 1218 { 1219 result->insert(make_pair(get<0>(p->second), set<string>())).first->second.insert(get<1>(p->second)[q].symbol); 1220 stopOrNot = false; 1221 } 1222 else 1223 { 1224 if (v->second.insert(get<1>(p->second)[q].symbol).second == true) 1225 stopOrNot = false; 1226 } 1227 break; 1228 } 1229 else 1230 { 1231 set<string>::const_iterator m; 1232 if ((m = (*result)[get<1>(p->second)[q].symbol].find("")) == (*result)[get<1>(p->second)[q].symbol].cend()) 1233 { 1234 map<string, set<string>>::iterator v = result->find(get<0>(p->second)); 1235 if (v == result->end()) 1236 { 1237 result->insert(make_pair(get<0>(p->second), set<string>())).first->second.insert((*result)[get<1>(p->second)[q].symbol].cbegin(), (*result)[get<1>(p->second)[q].symbol].cend()); 1238 stopOrNot = false; 1239 } 1240 else 1241 { 1242 if (get<0>(p->second) != get<1>(p->second)[q].symbol) 1243 { 1244 for (const string &item : (*result)[get<1>(p->second)[q].symbol]) 1245 { 1246 if (v->second.insert(item).second == true) 1247 { 1248 stopOrNot = false; 1249 } 1250 } 1251 } 1252 } 1253 break; 1254 } 1255 else 1256 { 1257 map<string, set<string>>::iterator v = result->find(get<0>(p->second)); 1258 if (v == result->end()) 1259 { 1260 (v = result->insert(make_pair(get<0>(p->second), set<string>())).first)->second.insert((*result)[get<1>(p->second)[q].symbol].cbegin(), m); 1261 v->second.insert(++m, (*result)[get<1>(p->second)[q].symbol].cend()); 1262 stopOrNot = false; 1263 } 1264 else 1265 { 1266 if (get<0>(p->second) != get<1>(p->second)[q].symbol) 1267 { 1268 set<string>::iterator item = (*result)[get<1>(p->second)[q].symbol].cbegin(); 1269 for (; item != m; ++item) 1270 { 1271 if (v->second.insert(*item).second == true) 1272 { 1273 stopOrNot = false; 1274 } 1275 } 1276 1277 for (++item; item != (*result)[get<1>(p->second)[q].symbol].cend(); ++item) 1278 { 1279 if (v->second.insert(*item).second == true) 1280 { 1281 stopOrNot = false; 1282 } 1283 } 1284 } 1285 } 1286 } 1287 } 1288 } 1289 } 1290 else 1291 { 1292 stopOrNot = false; 1293 } 1294 } 1295 if (stopOrNot == true) 1296 break; 1297 } 1298 return result; 1299 1300 } 1301 1302 shared_ptr<set<string>> LALRAutomata::calculateFirst(const vector<ProductionBodySymbol> &Pro, vector<ProductionBodySymbol>::size_type left, vector<ProductionBodySymbol>::size_type right) 1303 { 1304 shared_ptr<set<string>> result = make_shared<set<string>>(); 1305 if (left <= right) 1306 { 1307 for (vector<ProductionBodySymbol>::size_type temp = left; temp <= right; ++temp) 1308 { 1309 if (Pro[temp].TerminalOrNot == true) 1310 { 1311 result->insert(Pro[temp].symbol); 1312 return result; 1313 } 1314 else 1315 { 1316 set<string>::const_iterator p; 1317 if ((p = (*first)[Pro[temp].symbol].find("")) == (*first)[Pro[temp].symbol].cend()) 1318 { 1319 result->insert((*first)[Pro[temp].symbol].cbegin(), (*first)[Pro[temp].symbol].cend()); 1320 return result; 1321 } 1322 else 1323 { 1324 result->insert((*first)[Pro[temp].symbol].cbegin(), p); 1325 result->insert(++p, (*first)[Pro[temp].symbol].cend()); 1326 } 1327 } 1328 } 1329 result->insert(""); 1330 } 1331 return result; 1332 } 1333 1334 void output(LALRAutomata &test, ofstream &output) //将语法分析表,LALR自动机状态和其他文法信息输出至文件 1335 { 1336 cout << "非终结符:"; 1337 output << "非终结符:,"; 1338 for (set<string>::iterator temp = test.Nonterminal.begin(); temp != test.Nonterminal.end(); ++temp) 1339 { 1340 cout << *temp << " "; 1341 output << *temp << ","; 1342 } 1343 cout << endl; 1344 output << endl; 1345 cout << "终结符:"; 1346 output << "终结符:,"; 1347 for (set<string>::iterator temp = test.terminnal.begin(); temp != test.terminnal.end(); ++temp) 1348 { 1349 cout << *temp << " "; 1350 output << *temp << ","; 1351 } 1352 cout << endl; 1353 output << endl; 1354 cout << "原文法开始符号:" << test.StartSymbol << endl; 1355 output << "原文法开始符号:," << test.StartSymbol << endl; 1356 cout << "增广文法开始符号:" << test.AugGraSS << endl; 1357 output << "增广文法开始符号:," << test.AugGraSS << endl; 1358 cout << endl; 1359 output << endl; 1360 cout << "产生式:" << endl; 1361 output << "产生式:" << endl; 1362 for (map<long, tuple<string, vector<LALRAutomata::ProductionBodySymbol>, set<string>>>::iterator temp = test.productionSet.begin(); temp != test.productionSet.end(); ++temp) 1363 { 1364 cout << "产生式" << temp->first << ":"; 1365 output << "产生式" << temp->first << ":,"; 1366 cout << get<0>(temp->second) << "->"; 1367 output << get<0>(temp->second) << ",->,"; 1368 for (auto p = get<1>(temp->second).begin(); p != get<1>(temp->second).end(); ++p) 1369 { 1370 cout << p->symbol; 1371 output << p->symbol << ","; 1372 } 1373 cout << "非终结符号集合:"; 1374 output << ",非终结符号集合:,"; 1375 if (get<2>(temp->second).begin() == get<2>(temp->second).end()) 1376 { 1377 cout << "无"; 1378 output << "无,"; 1379 } 1380 for (set<string>::iterator p = get<2>(temp->second).begin(); p != get<2>(temp->second).end(); ++p) 1381 { 1382 cout << *p << " "; 1383 output << *p << ","; 1384 } 1385 cout << endl; 1386 output << endl; 1387 } 1388 1389 cout << endl; 1390 output << endl; 1391 cout << "非终结符号对应的产生式编号:" << endl; 1392 output << "非终结符号对应的产生式编号:" << endl; 1393 for (map<string, set<long>>::iterator temp = test.TerToPro.begin(); temp != test.TerToPro.end(); ++temp) 1394 { 1395 cout << "非终结符号:" << temp->first << " "; 1396 output << "非终结符号:" << temp->first << ","; 1397 for (set<long>::iterator p = temp->second.begin(); p != temp->second.end(); ++p) 1398 { 1399 cout << *p << " "; 1400 output << *p << ","; 1401 } 1402 cout << endl; 1403 output << endl; 1404 } 1405 1406 cout << endl; 1407 output << endl; 1408 cout << "各非终结符first集:" << endl; 1409 output << "各非终结符first集:" << endl; 1410 for (map<string, set<string>>::iterator temp = test.first->begin(); temp != test.first->end(); ++temp) 1411 { 1412 cout << "非终结符" << temp->first << ":"; 1413 output << "非终结符" << temp->first << ":,"; 1414 for (set<string>::iterator p = temp->second.begin(); p != temp->second.end(); ++p) 1415 { 1416 cout << *p << " "; 1417 output << *p << ","; 1418 } 1419 cout << endl; 1420 output << endl; 1421 } 1422 1423 cout << endl; 1424 output << endl; 1425 cout << "各非终结符follow集:" << endl; 1426 output << "各非终结符follow集:" << endl; 1427 for (map<string, set<string>>::iterator temp = test.follow->begin(); temp != test.follow->end(); ++temp) 1428 { 1429 cout << "非终结符" << temp->first << ":"; 1430 output << "非终结符" << temp->first << ":,"; 1431 for (set<string>::iterator p = temp->second.begin(); p != temp->second.end(); ++p) 1432 { 1433 cout << *p << " "; 1434 output << *p << ","; 1435 } 1436 cout << endl; 1437 output << endl; 1438 } 1439 1440 cout << endl; 1441 output << endl; 1442 cout << "LALR自动机状态:" << endl; 1443 output << "LALR自动机状态:" << endl; 1444 for (vector<Graph<LALRState, string>::GraphVertexNode *>::size_type i = 0; i < test.SetOfVertex.size(); ++i) 1445 { 1446 cout << "状态" << i << ":" << endl; 1447 output << "状态" << i << ":" << endl; 1448 for (auto p = test.SetOfVertex[i]->Vertexdatafield->kernel.begin(); p != test.SetOfVertex[i]->Vertexdatafield->kernel.end(); ++p) 1449 { 1450 cout << "产生式" << p->first << ":" << get<0>(test.productionSet[p->first]) << "->"; 1451 output << "产生式" << p->first << ":," << get<0>(test.productionSet[p->first]) << ",->,"; 1452 for (auto m = get<1>(test.productionSet[p->first]).begin(); m != get<1>(test.productionSet[p->first]).end(); ++m) 1453 { 1454 cout << m->symbol; 1455 output << m->symbol << ","; 1456 } 1457 cout << endl; 1458 output << endl; 1459 for (auto m = p->second.begin(); m != p->second.end(); ++m) 1460 { 1461 cout << "点号位置" << m->first << " "; 1462 output << "点号位置" << m->first << ","; 1463 cout << "向前看符号集合 "; 1464 output << "向前看符号集合,"; 1465 for (auto v = m->second.begin(); v != m->second.end(); ++v) 1466 { 1467 cout << *v << " "; 1468 output << *v << ","; 1469 } 1470 cout << endl; 1471 output << endl; 1472 } 1473 } 1474 1475 for (auto p = test.SetOfVertex[i]->Vertexdatafield->nonkernel.begin(); p != test.SetOfVertex[i]->Vertexdatafield->nonkernel.end(); ++p) 1476 { 1477 cout << "产生式" << p->first << ":" << get<0>(test.productionSet[p->first]) << "->"; 1478 output << "产生式" << p->first << ":," << get<0>(test.productionSet[p->first]) << ",->,"; 1479 for (auto m = get<1>(test.productionSet[p->first]).begin(); m != get<1>(test.productionSet[p->first]).end(); ++m) 1480 { 1481 cout << m->symbol; 1482 output << m->symbol << ","; 1483 } 1484 cout << endl; 1485 output << endl; 1486 cout << "点号位置" << p->second.dotposition << " "; 1487 output << "点号位置" << p->second.dotposition << ","; 1488 cout << "向前看符号集合 "; 1489 output << "向前看符号集合,"; 1490 for (auto v = p->second.ForwardLookingSign.begin(); v != p->second.ForwardLookingSign.end(); ++v) 1491 { 1492 cout << *v << " "; 1493 output << *v << ","; 1494 } 1495 cout << endl; 1496 output << endl; 1497 } 1498 } 1499 1500 cout << endl; 1501 output << endl; 1502 cout << "LALR语法分析表:" << endl; 1503 output << "LALR语法分析表:" << endl; 1504 vector<string> temp(test.LALRTable.first->size()); 1505 for (auto p = test.LALRTable.first->begin(); p != test.LALRTable.first->end(); ++p) 1506 { 1507 temp[p->second] = p->first; 1508 } 1509 output << " ,"; 1510 for (const auto &m : temp) 1511 { 1512 cout << m << " "; 1513 output << m << ","; 1514 } 1515 cout << endl; 1516 output << endl; 1517 for (vector<vector<LALRTableItem>>::size_type i = 0; i < test.LALRTable.second->size(); ++i) 1518 { 1519 cout << "状态" << i << " "; 1520 output << "状态" << i << ","; 1521 for (const auto &m : (*(test.LALRTable.second))[i]) 1522 { 1523 if (m.ActionType == m.MOVE) 1524 { 1525 cout << "m" << m.LALRStateNumber << " "; 1526 output << "m" << m.LALRStateNumber << ","; 1527 } 1528 else if (m.ActionType == m.REDUCTION) 1529 { 1530 cout << "r" << m.production << " "; 1531 output << "r" << m.production << ","; 1532 } 1533 else if (m.ActionType == m.ACCEPT) 1534 { 1535 cout << "A "; 1536 output << "A,"; 1537 } 1538 else 1539 { 1540 cout << "ERR "; 1541 output << "ERR,"; 1542 } 1543 } 1544 cout << endl; 1545 output << endl; 1546 } 1547 } 1548 int main() 1549 { 1550 ifstream input("inputexample1.txt"); //文法描述 1551 ofstream dataoutput("output.txt"); //输出结果 1552 LALRAutomata test(input); //根据和input绑定的文法描述生成LALR(1)语法分析信息 1553 output(test, dataoutput); //将语法分析信息输出至和dataoutput绑定的文件 1554 return 0; 1555 }
注意,这里有两个头文件Priority_Queue.h和assistfunction.h。Priority_Queue.h存放的是博主自己实现的优先级队列类,之所以没有使用标准库提供的容器适配器是因为适配器实现的优先级队列缺少一些操作队列成员的必要方法,如以下代码中的begin(),end()且容器适配器提供的接口的调用约定和返回值不符号程序编写要求,此外优先级队列是用堆实现的,但计算LALR闭包的算法要求优先队列必须用数组实现,其成员按优先级从小到大排序,故楼主自行实现了优先级队列。Priority_Queue.h代码如下:
1 #include <iostream> 2 #include <list> 3 #include <functional> 4 using namespace std; 5 6 template <typename T> 7 class Priority_Queue //设备等待队列类(优先级队列),队列数据元素为t 8 { 9 public: 10 typedef typename list<T>::iterator iterator; 11 Priority_Queue() = default; 12 Priority_Queue(const function<bool(const T&,const T&)> &com) :comparator(com) {} 13 ~Priority_Queue() = default; 14 pair<bool, typename Priority_Queue<T>::iterator> Insert(const T &x); //插入操作,返回的pair的first指示插入是否成功,second为指向插入元素的迭代器 15 bool RemoveTop(T &x); //删除最高优先级元素并用x将其返回 16 bool GetTop(T &x) const; //获取最高优先级元素并用x将其返回 17 void MakeEmpty() { Queue.clear(); } //清空队列 18 bool isEmpty() const { return Queue.empty(); } //判断队列是否为空 19 bool isFull() const { return Queue.size() == Queue.max_size(); } //判断队列是否已满 20 typename Priority_Queue<T>::iterator erase(const typename Priority_Queue<T>::iterator &p) { return Queue.erase(p); } //删除队列中p所指元素返回被删元素的下一元素 21 typename Priority_Queue<T>::iterator insert(const typename Priority_Queue<T>::iterator &p, const T &c) { return Queue.insert(p, c); } //将c插入至p所指位置,返回指向插入元素的迭代器 22 typename list<T>::size_type GetSize() const { return Queue.size(); } //获取队列实际大小 23 iterator begin() { return Queue.begin(); } //获取指向队列最高优先级元素的迭代器 24 iterator end() { return Queue.end(); } //获取队列尾后迭代器 25 26 private: 27 function<bool(const T&, const T&)> comparator; //比较T类型的可调用对象,左操作数小于右操作数返回true 28 typename list<T>::iterator adjust(); //新元素加入队列后调整元素位置,使队列中各元素保持优先级关系 29 list<T> Queue; 30 }; 31 32 template <typename T> 33 typename list<T>::iterator Priority_Queue<T>::adjust() 34 { 35 T temp = Queue.back(); 36 auto p = Queue.end(); 37 --p; 38 p = Queue.erase(p); 39 40 if (Queue.begin() != p) 41 --p; 42 else 43 { 44 return Queue.insert(p, temp); 45 } 46 47 while (true) 48 { 49 if (comparator(temp, (*p))) 50 { 51 if (p != Queue.begin()) 52 { 53 --p; 54 if (p == Queue.begin()) 55 continue; 56 } 57 } 58 else 59 { 60 ++p; 61 return Queue.insert(p, temp); 62 } 63 64 if (p == Queue.begin()) 65 break; 66 } 67 return Queue.insert(p, temp); 68 } 69 70 template <typename T> 71 pair<bool, typename Priority_Queue<T>::iterator> Priority_Queue<T>::Insert(const T &x) 72 { 73 if (isFull()) 74 return { false, end() }; 75 else 76 { 77 Queue.push_back(x); 78 return { true, adjust() }; 79 } 80 } 81 82 template <typename T> 83 bool Priority_Queue<T>::RemoveTop(T &x) 84 { 85 if (isEmpty()) 86 return false; 87 else 88 { 89 x = Queue.front(); 90 Queue.pop_front(); 91 return true; 92 } 93 } 94 95 template <typename T> 96 bool Priority_Queue<T>::GetTop(T &x) const 97 { 98 if (isEmpty()) 99 return false; 100 else 101 { 102 x = Queue.front(); 103 return true; 104 } 105 }
头文件assistfunction.h中定义了一些算法需要使用的辅助例程(只有第一个函数和算法有关,其他例程用于正则表达式引擎,后续会解读),由于代码简洁易懂,不是很重要,这里就不详细解说了。
1 #include<set> 2 #include<map> 3 #include<string> 4 void setToMap(const set<string> &source, map<string, int> &goal, int &count) 5 { 6 for (set<string>::iterator p = source.cbegin(); p != source.cend(); ++p) 7 { 8 goal.insert(make_pair(*p, count++)); 9 } 10 } 11 12 char strToChar(const string &m) 13 { 14 if (m.size() == 1) 15 return m[0]; 16 else if (m.size() == 2) 17 { 18 switch (m[1]) 19 { 20 case‘f‘: return ‘f‘; 21 case‘n‘: return ‘ ‘; 22 case‘r‘: return ‘ ‘; 23 case‘t‘: return‘ ‘; 24 case‘v‘: return‘v‘; 25 case‘^‘: return‘^‘; 26 case‘-‘: return‘-‘; 27 case‘\‘: return‘\‘; 28 case‘*‘: return‘*‘; 29 case‘+‘: return‘+‘; 30 case‘?‘: return‘?‘; 31 case‘$‘: return‘$‘; 32 case‘.‘: return‘.‘; 33 case‘(‘: return‘(‘; 34 case‘)‘: return‘)‘; 35 case‘:‘: return‘:‘; 36 case‘=‘: return‘=‘; 37 case‘!‘: return‘!‘; 38 case‘<‘: return‘<‘; 39 case‘|‘: return‘|‘; 40 case‘[‘: return‘[‘; 41 case‘]‘: return‘]‘; 42 case‘{‘: return‘{‘; 43 case‘}‘: return‘}‘; 44 } 45 } 46 } 47 48 void insertIntoSet(map<size_t, set<size_t>> &beinserted, const size_t &source, const size_t &goal) 49 { 50 map<size_t, set<size_t>>::iterator it = beinserted.find(goal); 51 if (it == beinserted.end()) 52 { 53 beinserted.insert(make_pair(goal, set<size_t>())).first->second.insert(source); 54 } 55 else 56 { 57 it->second.insert(source); 58 } 59 } 60 61 void insertIntoMap(map<size_t, set<size_t>> &beinserted, map<size_t, map<size_t, set<size_t>>> &from) 62 { 63 for (map<size_t, map<size_t, set<size_t>>>::iterator p = from.begin(); p != from.end(); ++p) 64 { 65 for (map<size_t, set<size_t>>::iterator q = p->second.begin(); q != p->second.end(); ++q) 66 { 67 map<size_t, set<size_t>>::iterator m = beinserted.find(q->first); 68 if (m == beinserted.end()) 69 { 70 beinserted.insert(make_pair(q->first, set<size_t>(q->second))); 71 } 72 else 73 { 74 m->second.insert(q->second.begin(), q->second.end()); 75 } 76 } 77 } 78 } 79 80 void insertIntoMap(map<size_t, map<size_t, map<size_t, size_t>>> &end, size_t substart, size_t subend, size_t sub_start_stackindex, size_t sub_end_stackindex) 81 { 82 map<size_t, map<size_t, map<size_t, size_t>>>::iterator p = end.find(subend); 83 if (p == end.end()) 84 { 85 end.insert(make_pair(subend, map<size_t, map<size_t, size_t>>())).first->second.insert(make_pair(substart, map<size_t, size_t>())).first->second.insert(make_pair(sub_start_stackindex, sub_end_stackindex)); 86 } 87 else 88 { 89 map<size_t, map<size_t, size_t>>::iterator q = p->second.find(substart); 90 if (q == p->second.end()) 91 { 92 p->second.insert(make_pair(substart, map<size_t, size_t>())).first->second.insert(make_pair(sub_start_stackindex, sub_end_stackindex)); 93 } 94 else 95 { 96 q->second[sub_start_stackindex] = sub_end_stackindex; 97 } 98 } 99 }
程序的使用方法请参看main函数中的注释,分析结果会输出至指定文件,文件中加入了必要的逗号分隔符,将其扩展名改为csv用excel打开即可看到经整理的分析结果,如果文法不是LALR(1)的,程序运行时在命令行窗口上会打印语法分析动作冲突的相关信息。注意如果自定义文法进行测试文法需设计合理,避免存在逻辑错误,否则程序可能会陷入死循环或抛出异常。博主给出的示例文法可以得到分析结果且无语法分析冲突,可以把示例文法拷贝至输入文件中测试。
PS:本人微信号memoryundersun,欢迎各位同仁主动联系我,大家一起学习一起进步
以上是关于编译器构造中自底向上的LALR语法分析的语法分析表生成的实现的主要内容,如果未能解决你的问题,请参考以下文章