@@ -150,7 +150,7 @@ def end(self):
150150
151151 def __getattr__ (self , name ):
152152 if name in self ._namemap :
153- return self ._namemap [name ]( self . _slice )
153+ return self ._slice [ self . _namemap [name ]]. value
154154 else :
155155 nameset = '{' + ', ' .join (self ._namemap ) + '}'
156156 raise AttributeError (f'No symbol { name } . Must be one of { nameset } .' )
@@ -233,15 +233,16 @@ def __init__(self, number, name, prod, precedence=('right', 0), func=None, file=
233233 nameuse [key ] += 1
234234 else :
235235 k = key
236- namemap [k ] = lambda s , i = index : s [ i ]. value
236+ namemap [k ] = index
237237 if key in _name_aliases :
238238 for n , alias in enumerate (_name_aliases [key ]):
239239 if namecount [alias ] > 1 :
240240 k = f'{ alias } { nameuse [alias ]} '
241241 nameuse [alias ] += 1
242242 else :
243243 k = alias
244- # The value is either a list (for repetition) or a tuple for optional
244+ # The value is either a list (for repetition) or a tuple for optional
245+ raise RuntimeError ('Refactor the line below' ) # this code is not called
245246 namemap [k ] = lambda s ,i = index ,n = n : ([x [n ] for x in s [i ].value ]) if isinstance (s [i ].value , list ) else s [i ].value [n ]
246247
247248 self .namemap = namemap
@@ -686,7 +687,7 @@ def unused_precedence(self):
686687 def _first (self , beta ):
687688
688689 # We are computing First(x1,x2,x3,...,xn)
689- result = []
690+ result = set ()
690691 for x in beta :
691692 x_produces_empty = False
692693
@@ -695,8 +696,7 @@ def _first(self, beta):
695696 if f == '<empty>' :
696697 x_produces_empty = True
697698 else :
698- if f not in result :
699- result .append (f )
699+ result .add (f )
700700
701701 if x_produces_empty :
702702 # We have to consider the next x in beta,
@@ -709,7 +709,7 @@ def _first(self, beta):
709709 # There was no 'break' from the loop,
710710 # so x_produces_empty was true for all x in beta,
711711 # so beta produces empty as well.
712- result .append ('<empty>' )
712+ result .add ('<empty>' )
713713
714714 return result
715715
@@ -724,25 +724,24 @@ def compute_first(self):
724724
725725 # Terminals:
726726 for t in self .Terminals :
727- self .First [t ] = [ t ]
727+ self .First [t ] = { t }
728728
729- self .First ['$end' ] = [ '$end' ]
729+ self .First ['$end' ] = { '$end' }
730730
731731 # Nonterminals:
732732
733733 # Initialize to the empty set:
734734 for n in self .Nonterminals :
735- self .First [n ] = []
735+ self .First [n ] = set ()
736736
737737 # Then propagate symbols until no change:
738738 while True :
739739 some_change = False
740740 for n in self .Nonterminals :
741741 for p in self .Prodnames [n ]:
742- for f in self ._first (p .prod ):
743- if f not in self .First [n ]:
744- self .First [n ].append (f )
745- some_change = True
742+ length = len (self .First [n ])
743+ self .First [n ].update (self ._first (p .prod ))
744+ some_change = length != len (self .First [n ])
746745 if not some_change :
747746 break
748747
@@ -766,12 +765,12 @@ def compute_follow(self, start=None):
766765
767766 # Add '$end' to the follow list of the start symbol
768767 for k in self .Nonterminals :
769- self .Follow [k ] = []
768+ self .Follow [k ] = set ()
770769
771770 if not start :
772771 start = self .Productions [1 ].name
773772
774- self .Follow [start ] = [ '$end' ]
773+ self .Follow [start ] = { '$end' }
775774
776775 while True :
777776 didadd = False
@@ -784,16 +783,15 @@ def compute_follow(self, start=None):
784783 hasempty = False
785784 for f in fst :
786785 if f != '<empty>' and f not in self .Follow [B ]:
787- self .Follow [B ].append (f )
786+ self .Follow [B ].add (f )
788787 didadd = True
789788 if f == '<empty>' :
790789 hasempty = True
791790 if hasempty or i == (len (p .prod )- 1 ):
792791 # Add elements of follow(a) to follow(b)
793- for f in self .Follow [p .name ]:
794- if f not in self .Follow [B ]:
795- self .Follow [B ].append (f )
796- didadd = True
792+ length = len (self .Follow [B ])
793+ self .Follow [B ].update (self .Follow [p .name ])
794+ didadd = len (self .Follow [B ]) != length
797795 if not didadd :
798796 break
799797 return self .Follow
0 commit comments