3232# -----------------------------------------------------------------------------
3333
3434import sys
35+ import os
3536import inspect
37+ import pickle
3638from collections import OrderedDict , defaultdict , Counter
3739
3840__all__ = [ 'Parser' ]
@@ -935,12 +937,10 @@ class LALRError(YaccError):
935937# -----------------------------------------------------------------------------
936938
937939class LRTable (object ):
938- def __init__ (self , grammar ):
940+ def __init__ (self , grammar , lr_vars = None ):
939941 self .grammar = grammar
940942
941943 # Internal attributes
942- self .lr_action = {} # Action table
943- self .lr_goto = {} # Goto table
944944 self .lr_productions = grammar .Productions # Copy of grammar Production array
945945
946946 # Cache of computed gotos
@@ -962,7 +962,13 @@ def __init__(self, grammar):
962962 self .grammar .build_lritems ()
963963 self .grammar .compute_first ()
964964 self .grammar .compute_follow ()
965- self .lr_parse_table ()
965+
966+ if lr_vars is not None :
967+ self .lr_action , self .lr_goto = lr_vars
968+ else :
969+ self .lr_action = {} # Action table
970+ self .lr_goto = {} # Goto table
971+ self .lr_parse_table ()
966972
967973 # Build default states
968974 # This identifies parser states where there is only one possible reduction action.
@@ -1985,12 +1991,36 @@ def __build_grammar(cls, rules):
19851991 if errors :
19861992 raise YaccError ('Unable to build grammar.\n ' + errors )
19871993
1994+ @classmethod
1995+ def _get_build_file (cls ):
1996+ path = inspect .getfile (cls )
1997+ return path [: path .rfind ('.' )] + '.pkl'
1998+
1999+ @classmethod
2000+ def build_to_file (self ):
2001+ path = self ._get_build_file ()
2002+
2003+ lr_table = self ._lrtable
2004+ lr_vars = (lr_table .lr_action , lr_table .lr_goto )
2005+ pickle .dump (lr_vars , open (path , 'wb' ))
2006+ print ('Built to' , path )
2007+
19882008 @classmethod
19892009 def __build_lrtables (cls ):
19902010 '''
19912011 Build the LR Parsing tables from the grammar
19922012 '''
1993- lrtable = LRTable (cls ._grammar )
2013+ # use cache
2014+ build_file = cls ._get_build_file ()
2015+ lr_vars = None
2016+ if os .path .exists (build_file ):
2017+ try :
2018+ lr_vars = pickle .load (open (build_file , 'rb' ))
2019+ assert len (lr_vars ) == 2
2020+ except Exception :
2021+ pass
2022+
2023+ lrtable = LRTable (cls ._grammar , lr_vars = lr_vars )
19942024 num_sr = len (lrtable .sr_conflicts )
19952025
19962026 # Report shift/reduce and reduce/reduce conflicts
0 commit comments