This is to help mak epsilon productions work with kernel items and to compute goto transitions from kernel.
269: #line 422 "lalr1_parser.ipk" 270: def calc_ntfirstmap(self): 271: res = {} 272: for p in self.productions: 273: if p.RHS and p.RHS[0] in self.nonterms: 274: fos = self.firstofstring(p.RHS[1:]) 275: fos.sort() 276: if not res.has_key(p.LHS): 277: res[p.LHS] = {} 278: if not res[p.LHS].has_key(p.RHS[0]): 279: res[p.LHS][p.RHS[0]] = [] 280: for i in fos: 281: if i not in res[p.LHS].get(p.RHS[0], []): 282: res[p.LHS][p.RHS[0]] = fos 283: 284: while 1: 285: foundmore = 0 286: reskeys = res.keys() 287: for nt in reskeys: 288: rhsdict = res[nt] 289: for rnt in rhsdict.keys(): 290: if rnt in reskeys: 291: d = res[rnt] 292: for k in d.keys(): 293: if not res[nt].has_key(k): 294: fos = self.firstofstring(d[k]+ res[nt][rnt]) 295: foundmore = 1 296: fos.sort() 297: res[nt][k] = fos 298: else: 299: fos = self.firstofstring(d[k] + res[nt][rnt]) 300: fos.sort() 301: if fos != res[nt][k]: # then res[nt][k] is contained in fos 302: foundmore = 1 303: res[nt][k] = fos 304: if not foundmore: break 305: # 306: # this part accounts for the fact that a nonterminal will 307: # produce exactly itself in zero steps 308: # 309: for p in self.productions: 310: if res.has_key(p.LHS): 311: res[p.LHS][p.LHS] = [EPS] 312: else: 313: res[p.LHS] = {p.LHS: [EPS]} 314: self.ntfirstmap = res 315:
6.9.3.1. newmkntfirstmap
6.9.3.2. mktfirstmap
6.9.3.3. goto
6.9.3.4. lookaheads
6.9.3.5. kernelsoflalr1items
6.9.3.6. Calculate LALR1items
6.9.3.7. Calculate Action Table
6.9.3.8. Calculate goto table
6.9.3.9. Parser