ewa.ply.yacc

Package ewa :: Package ply :: Module yacc |
[hide private]
[frames] | no frames]

# Source Code for Module ewa.ply.yacc

       1  # -----------------------------------------------------------------------------
       2  # ply: yacc.py
       3  #
       4  # Copyright (C) 2001-2009,
       5  # David M. Beazley (Dabeaz LLC)
       6  # All rights reserved.
       7  #
       8  # Redistribution and use in source and binary forms, with or without
       9  # modification, are permitted provided that the following conditions are
      10  # met:
      11  #
      12  # * Redistributions of source code must retain the above copyright notice,
      13  #   this list of conditions and the following disclaimer.
      14  # * Redistributions in binary form must reproduce the above copyright notice,
      15  #   this list of conditions and the following disclaimer in the documentation
      16  #   and/or other materials provided with the distribution.
      17  # * Neither the name of the David Beazley or Dabeaz LLC may be used to
      18  #   endorse or promote products derived from this software without
      19  #  specific prior written permission.
      20  #
      21  # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
      22  # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
      23  # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
      24  # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
      25  # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
      26  # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
      27  # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
      28  # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
      29  # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
      30  # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
      31  # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
      32  # -----------------------------------------------------------------------------
      33  #
      34  # This implements an LR parser that is constructed from grammar rules defined
      35  # as Python functions. The grammer is specified by supplying the BNF inside
      36  # Python documentation strings.  The inspiration for this technique was borrowed
      37  # from John Aycock's Spark parsing system.  PLY might be viewed as cross between
      38  # Spark and the GNU bison utility.
      39  #
      40  # The current implementation is only somewhat object-oriented. The
      41  # LR parser itself is defined in terms of an object (which allows multiple
      42  # parsers to co-exist).  However, most of the variables used during table
      43  # construction are defined in terms of global variables.  Users shouldn't
      44  # notice unless they are trying to define multiple parsers at the same
      45  # time using threads (in which case they should have their head examined).
      46  #
      47  # This implementation supports both SLR and LALR(1) parsing.  LALR(1)
      48  # support was originally implemented by Elias Ioup (ezioup@alumni.uchicago.edu),
      49  # using the algorithm found in Aho, Sethi, and Ullman "Compilers: Principles,
      50  # Techniques, and Tools" (The Dragon Book).  LALR(1) has since been replaced
      51  # by the more efficient DeRemer and Pennello algorithm.
      52  #
      53  # :::::::: WARNING :::::::
      54  #
      55  # Construction of LR parsing tables is fairly complicated and expensive.
      56  # To make this module run fast, a *LOT* of work has been put into
      57  # optimization---often at the expensive of readability and what might
      58  # consider to be good Python "coding style."   Modify the code at your
      59  # own risk!
      60  # ----------------------------------------------------------------------------
      61
      62  __version__    = "3.3"
      63  __tabversion__ = "3.2"       # Table version
      64
      65  #-----------------------------------------------------------------------------
      66  #                     === User configurable parameters ===
      67  #
      68  # Change these to modify the default behavior of yacc (if you wish)
      69  #-----------------------------------------------------------------------------
      70
      71  yaccdebug   = 1                # Debugging mode.  If set, yacc generates a
      72                                 # a 'parser.out' file in the current directory
      73
      74  debug_file  = 'parser.out'     # Default name of the debugging file
      75  tab_module  = 'parsetab'       # Default name of the table module
      76  default_lr  = 'LALR'           # Default LR table generation method
      77
      78  error_count = 3                # Number of symbols that must be shifted to leave recovery mode
      79
      80  yaccdevel   = 0                # Set to True if developing yacc.  This turns off optimized
      81                                 # implementations of certain functions.
      82
      83  resultlimit = 40               # Size limit of results when running in debug mode.
      84
      85  pickle_protocol = 0            # Protocol to use when writing pickle files
      86
      87  import re, types, sys, os.path
      88
      89  # Compatibility function for python 2.6/3.0
      90  if sys.version_info[0] < 3:
      91 -    def func_code(f):
      92          return f.func_code
      93  else:
      94 -    def func_code(f):
      95          return f.__code__
      96
      97  # Compatibility
      98  try:
      99      MAXINT = sys.maxint
     100  except AttributeError:
     101      MAXINT = sys.maxsize
     102
     103  # Python 2.x/3.0 compatibility.
     104 -def load_ply_lex():
     105      if sys.version_info[0] < 3:
     106          import lex
     107      else:
     108          import ply.lex as lex
     109      return lex
     110
     111  # This object is a stand-in for a logging object created by the
     112  # logging module.   PLY will use this by default to create things
     113  # such as the parser.out file.  If a user wants more detailed
     114  # information, they can create their own logging object and pass
     115  # it into PLY.
     116
     117 -class PlyLogger(object):
     118 -    def __init__(self,f):
     119          self.f = f
     120 -    def debug(self,msg,*args,**kwargs):
     121          self.f.write((msg % args) + "\n")
     122      info     = debug
     123
     124 -    def warning(self,msg,*args,**kwargs):
     125          self.f.write("WARNING: "+ (msg % args) + "\n")
     126
     127 -    def error(self,msg,*args,**kwargs):
     128          self.f.write("ERROR: " + (msg % args) + "\n")
     129
     130      critical = debug
     131
     132  # Null logger is used when no output is generated. Does nothing.
     133 -class NullLogger(object):
     134 -    def __getattribute__(self,name):
     135          return self
     136 -    def __call__(self,*args,**kwargs):
     137          return self
     138
     139  # Exception raised for yacc-related errors
     140 -class YaccError(Exception):   pass
     141
     142  # Format the result message that the parser produces when running in debug mode.
     143 -def format_result(r):
     144      repr_str = repr(r)
     145      if '\n' in repr_str: repr_str = repr(repr_str)
     146      if len(repr_str) > resultlimit:
     147          repr_str = repr_str[:resultlimit]+" ..."
     148      result = "<%s @ 0x%x> (%s)" % (type(r).__name__,id(r),repr_str)
     149      return result
     150
     151
     152  # Format stack entries when the parser is running in debug mode
     153 -def format_stack_entry(r):
     154      repr_str = repr(r)
     155      if '\n' in repr_str: repr_str = repr(repr_str)
     156      if len(repr_str) < 16:
     157          return repr_str
     158      else:
     159          return "<%s @ 0x%x>" % (type(r).__name__,id(r))
     160
     161  #-----------------------------------------------------------------------------
     162  #                        ===  LR Parsing Engine ===
     163  #
     164  # The following classes are used for the LR parser itself.  These are not
     165  # used during table construction and are independent of the actual LR
     166  # table generation algorithm
     167  #-----------------------------------------------------------------------------
     168
     169  # This class is used to hold non-terminal grammar symbols during parsing.
     170  # It normally has the following attributes set:
     171  #        .type       = Grammar symbol type
     172  #        .value      = Symbol value
     173  #        .lineno     = Starting line number
     174  #        .endlineno  = Ending line number (optional, set automatically)
     175  #        .lexpos     = Starting lex position
     176  #        .endlexpos  = Ending lex position (optional, set automatically)
     177
     178 -class YaccSymbol:
     179 -    def __str__(self):    return self.type
     180 -    def __repr__(self):   return str(self)
     181
     182  # This class is a wrapper around the objects actually passed to each
     183  # grammar rule.   Index lookup and assignment actually assign the
     184  # .value attribute of the underlying YaccSymbol object.
     185  # The lineno() method returns the line number of a given
     186  # item (or 0 if not defined).   The linespan() method returns
     187  # a tuple of (startline,endline) representing the range of lines
     188  # for a symbol.  The lexspan() method returns a tuple (lexpos,endlexpos)
     189  # representing the range of positional information for a symbol.
     190
     191 -class YaccProduction:
     192 -    def __init__(self,s,stack=None):
     193          self.slice = s
     194          self.stack = stack
     195          self.lexer = None
     196          self.parser= None
     197 -    def __getitem__(self,n):
     198          if n >= 0: return self.slice[n].value
     199          else: return self.stack[n].value
     200
     201 -    def __setitem__(self,n,v):
     202          self.slice[n].value = v
     203
     204 -    def __getslice__(self,i,j):
     205          return [s.value for s in self.slice[i:j]]
     206
     207 -    def __len__(self):
     208          return len(self.slice)
     209
     210 -    def lineno(self,n):
     211          return getattr(self.slice[n],"lineno",0)
     212
     213 -    def set_lineno(self,n,lineno):
     214          self.slice[n].lineno = lineno
     215
     216 -    def linespan(self,n):
     217          startline = getattr(self.slice[n],"lineno",0)
     218          endline = getattr(self.slice[n],"endlineno",startline)
     219          return startline,endline
     220
     221 -    def lexpos(self,n):
     222          return getattr(self.slice[n],"lexpos",0)
     223
     224 -    def lexspan(self,n):
     225          startpos = getattr(self.slice[n],"lexpos",0)
     226          endpos = getattr(self.slice[n],"endlexpos",startpos)
     227          return startpos,endpos
     228
     229 -    def error(self):
     230         raise SyntaxError
     231
     232
     233  # -----------------------------------------------------------------------------
     234  #                               == LRParser ==
     235  #
     236  # The LR Parsing engine.
     237  # -----------------------------------------------------------------------------
     238
     239 -class LRParser:
     240 -    def __init__(self,lrtab,errorf):
     241          self.productions = lrtab.lr_productions
     242          self.action      = lrtab.lr_action
     243          self.goto        = lrtab.lr_goto
     244          self.errorfunc   = errorf
     245
     246 -    def errok(self):
     247          self.errorok     = 1
     248
     249 -    def restart(self):
     250          del self.statestack[:]
     251          del self.symstack[:]
     252          sym = YaccSymbol()
     253          sym.type = '$end'
     254          self.symstack.append(sym)
     255          self.statestack.append(0)
     256
     257 -    def parse(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
     258          if debug or yaccdevel:
     259              if isinstance(debug,int):
     260                  debug = PlyLogger(sys.stderr)
     261              return self.parsedebug(input,lexer,debug,tracking,tokenfunc)
     262          elif tracking:
     263              return self.parseopt(input,lexer,debug,tracking,tokenfunc)
     264          else:
     265              return self.parseopt_notrack(input,lexer,debug,tracking,tokenfunc)
     266
     267
     268      # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     269      # parsedebug().
     270      #
     271      # This is the debugging enabled version of parse().  All changes made to the
     272      # parsing engine should be made here.   For the non-debugging version,
     273      # copy this code to a method parseopt() and delete all of the sections
     274      # enclosed in:
     275      #
     276      #      #--! DEBUG
     277      #      statements
     278      #      #--! DEBUG
     279      #
     280      # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     281
     282 -    def parsedebug(self,input=None,lexer=None,debug=None,tracking=0,tokenfunc=None):
     283          lookahead = None                 # Current lookahead symbol
     284          lookaheadstack = [ ]             # Stack of lookahead symbols
     285          actions = self.action            # Local reference to action table (to avoid lookup on self.)
     286          goto    = self.goto              # Local reference to goto table (to avoid lookup on self.)
     287          prod    = self.productions       # Local reference to production list (to avoid lookup on self.)
     288          pslice  = YaccProduction(None)   # Production object passed to grammar rules
     289          errorcount = 0                   # Used during error recovery
     290
     291          # --! DEBUG
     292          debug.info("PLY: PARSE DEBUG START")
     293          # --! DEBUG
     294
     295          # If no lexer was given, we will try to use the lex module
     296          if not lexer:
     297              lex = load_ply_lex()
     298              lexer = lex.lexer
     299
     300          # Set up the lexer and parser objects on pslice
     301          pslice.lexer = lexer
     302          pslice.parser = self
     303
     304          # If input was supplied, pass to lexer
     305          if input is not None:
     306              lexer.input(input)
     307
     308          if tokenfunc is None:
     309             # Tokenize function
     310             get_token = lexer.token
     311          else:
     312             get_token = tokenfunc
     313
     314          # Set up the state and symbol stacks
     315
     316          statestack = [ ]                # Stack of parsing states
     317          self.statestack = statestack
     318          symstack   = [ ]                # Stack of grammar symbols
     319          self.symstack = symstack
     320
     321          pslice.stack = symstack         # Put in the production
     322          errtoken   = None               # Err token
     323
     324          # The start state is assumed to be (0,$end)
     325
     326          statestack.append(0)
     327          sym = YaccSymbol()
     328          sym.type = "$end"
     329          symstack.append(sym)
     330          state = 0
     331          while 1:
     332              # Get the next symbol on the input.  If a lookahead symbol
     333              # is already set, we just use that. Otherwise, we'll pull
     334              # the next token off of the lookaheadstack or from the lexer
     335
     336              # --! DEBUG
     337              debug.debug('')
     338              debug.debug('State  : %s', state)
     339              # --! DEBUG
     340
     341              if not lookahead:
     342                  if not lookaheadstack:
     343                      lookahead = get_token()     # Get the next token
     344                  else:
     345                      lookahead = lookaheadstack.pop()
     346                  if not lookahead:
     347                      lookahead = YaccSymbol()
     348                      lookahead.type = "$end"
     349
     350              # --! DEBUG
     351              debug.debug('Stack  : %s',
     352                          ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip())
     353              # --! DEBUG
     354
     355              # Check the action table
     356              ltype = lookahead.type
     357              t = actions[state].get(ltype)
     358
     359              if t is not None:
     360                  if t > 0:
     361                      # shift a symbol on the stack
     362                      statestack.append(t)
     363                      state = t
     364
     365                      # --! DEBUG
     366                      debug.debug("Action : Shift and goto state %s", t)
     367                      # --! DEBUG
     368
     369                      symstack.append(lookahead)
     370                      lookahead = None
     371
     372                      # Decrease error count on successful shift
     373                      if errorcount: errorcount -=1
     374                      continue
     375
     376                  if t < 0:
     377                      # reduce a symbol on the stack, emit a production
     378                      p = prod[-t]
     379                      pname = p.name
     380                      plen  = p.len
     381
     382                      # Get production function
     383                      sym = YaccSymbol()
     384                      sym.type = pname       # Production name
     385                      sym.value = None
     386
     387                      # --! DEBUG
     388                      if plen:
     389                          debug.info("Action : Reduce rule [%s] with %s and goto state %d", p.str, "["+",".join([format_stack_entry(_v.value) for _v in symstack[-plen:]])+"]",-t)
     390                      else:
     391                          debug.info("Action : Reduce rule [%s] with %s and goto state %d", p.str, [],-t)
     392
     393                      # --! DEBUG
     394
     395                      if plen:
     396                          targ = symstack[-plen-1:]
     397                          targ[0] = sym
     398
     399                          # --! TRACKING
     400                          if tracking:
     401                             t1 = targ[1]
     402                             sym.lineno = t1.lineno
     403                             sym.lexpos = t1.lexpos
     404                             t1 = targ[-1]
     405                             sym.endlineno = getattr(t1,"endlineno",t1.lineno)
     406                             sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos)
     407
     408                          # --! TRACKING
     409
     410                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     411                          # The code enclosed in this section is duplicated
     412                          # below as a performance optimization.  Make sure
     413                          # changes get made in both locations.
     414
     415                          pslice.slice = targ
     416
     417                          try:
     418                              # Call the grammar rule with our special slice object
     419                              del symstack[-plen:]
     420                              del statestack[-plen:]
     421                              p.callable(pslice)
     422                              # --! DEBUG
     423                              debug.info("Result : %s", format_result(pslice[0]))
     424                              # --! DEBUG
     425                              symstack.append(sym)
     426                              state = goto[statestack[-1]][pname]
     427                              statestack.append(state)
     428                          except SyntaxError:
     429                              # If an error was set. Enter error recovery state
     430                              lookaheadstack.append(lookahead)
     431                              symstack.pop()
     432                              statestack.pop()
     433                              state = statestack[-1]
     434                              sym.type = 'error'
     435                              lookahead = sym
     436                              errorcount = error_count
     437                              self.errorok = 0
     438                          continue
     439                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     440
     441                      else:
     442
     443                          # --! TRACKING
     444                          if tracking:
     445                             sym.lineno = lexer.lineno
     446                             sym.lexpos = lexer.lexpos
     447                          # --! TRACKING
     448
     449                          targ = [ sym ]
     450
     451                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     452                          # The code enclosed in this section is duplicated
     453                          # above as a performance optimization.  Make sure
     454                          # changes get made in both locations.
     455
     456                          pslice.slice = targ
     457
     458                          try:
     459                              # Call the grammar rule with our special slice object
     460                              p.callable(pslice)
     461                              # --! DEBUG
     462                              debug.info("Result : %s", format_result(pslice[0]))
     463                              # --! DEBUG
     464                              symstack.append(sym)
     465                              state = goto[statestack[-1]][pname]
     466                              statestack.append(state)
     467                          except SyntaxError:
     468                              # If an error was set. Enter error recovery state
     469                              lookaheadstack.append(lookahead)
     470                              symstack.pop()
     471                              statestack.pop()
     472                              state = statestack[-1]
     473                              sym.type = 'error'
     474                              lookahead = sym
     475                              errorcount = error_count
     476                              self.errorok = 0
     477                          continue
     478                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     479
     480                  if t == 0:
     481                      n = symstack[-1]
     482                      result = getattr(n,"value",None)
     483                      # --! DEBUG
     484                      debug.info("Done   : Returning %s", format_result(result))
     485                      debug.info("PLY: PARSE DEBUG END")
     486                      # --! DEBUG
     487                      return result
     488
     489              if t == None:
     490
     491                  # --! DEBUG
     492                  debug.error('Error  : %s',
     493                              ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip())
     494                  # --! DEBUG
     495
     496                  # We have some kind of parsing error here.  To handle
     497                  # this, we are going to push the current token onto
     498                  # the tokenstack and replace it with an 'error' token.
     499                  # If there are any synchronization rules, they may
     500                  # catch it.
     501                  #
     502                  # In addition to pushing the error token, we call call
     503                  # the user defined p_error() function if this is the
     504                  # first syntax error.  This function is only called if
     505                  # errorcount == 0.
     506                  if errorcount == 0 or self.errorok:
     507                      errorcount = error_count
     508                      self.errorok = 0
     509                      errtoken = lookahead
     510                      if errtoken.type == "$end":
     511                          errtoken = None               # End of file!
     512                      if self.errorfunc:
     513                          global errok,token,restart
     514                          errok = self.errok        # Set some special functions available in error recovery
     515                          token = get_token
     516                          restart = self.restart
     517                          if errtoken and not hasattr(errtoken,'lexer'):
     518                              errtoken.lexer = lexer
     519                          tok = self.errorfunc(errtoken)
     520                          del errok, token, restart   # Delete special functions
     521
     522                          if self.errorok:
     523                              # User must have done some kind of panic
     524                              # mode recovery on their own.  The
     525                              # returned token is the next lookahead
     526                              lookahead = tok
     527                              errtoken = None
     528                              continue
     529                      else:
     530                          if errtoken:
     531                              if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
     532                              else: lineno = 0
     533                              if lineno:
     534                                  sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
     535                              else:
     536                                  sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
     537                          else:
     538                              sys.stderr.write("yacc: Parse error in input. EOF\n")
     539                              return
     540
     541                  else:
     542                      errorcount = error_count
     543
     544                  # case 1:  the statestack only has 1 entry on it.  If we're in this state, the
     545                  # entire parse has been rolled back and we're completely hosed.   The token is
     546                  # discarded and we just keep going.
     547
     548                  if len(statestack) <= 1 and lookahead.type != "$end":
     549                      lookahead = None
     550                      errtoken = None
     551                      state = 0
     552                      # Nuke the pushback stack
     553                      del lookaheadstack[:]
     554                      continue
     555
     556                  # case 2: the statestack has a couple of entries on it, but we're
     557                  # at the end of the file. nuke the top entry and generate an error token
     558
     559                  # Start nuking entries on the stack
     560                  if lookahead.type == "$end":
     561                      # Whoa. We're really hosed here. Bail out
     562                      return
     563
     564                  if lookahead.type != 'error':
     565                      sym = symstack[-1]
     566                      if sym.type == 'error':
     567                          # Hmmm. Error is on top of stack, we'll just nuke input
     568                          # symbol and continue
     569                          lookahead = None
     570                          continue
     571                      t = YaccSymbol()
     572                      t.type = 'error'
     573                      if hasattr(lookahead,"lineno"):
     574                          t.lineno = lookahead.lineno
     575                      t.value = lookahead
     576                      lookaheadstack.append(lookahead)
     577                      lookahead = t
     578                  else:
     579                      symstack.pop()
     580                      statestack.pop()
     581                      state = statestack[-1]       # Potential bug fix
     582
     583                  continue
     584
     585              # Call an error function here
     586              raise RuntimeError("yacc: internal parser error!!!\n")
     587
     588      # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     589      # parseopt().
     590      #
     591      # Optimized version of parse() method.  DO NOT EDIT THIS CODE DIRECTLY.
     592      # Edit the debug version above, then copy any modifications to the method
     593      # below while removing #--! DEBUG sections.
     594      # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     595
     596
     597 -    def parseopt(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
     598          lookahead = None                 # Current lookahead symbol
     599          lookaheadstack = [ ]             # Stack of lookahead symbols
     600          actions = self.action            # Local reference to action table (to avoid lookup on self.)
     601          goto    = self.goto              # Local reference to goto table (to avoid lookup on self.)
     602          prod    = self.productions       # Local reference to production list (to avoid lookup on self.)
     603          pslice  = YaccProduction(None)   # Production object passed to grammar rules
     604          errorcount = 0                   # Used during error recovery
     605
     606          # If no lexer was given, we will try to use the lex module
     607          if not lexer:
     608              lex = load_ply_lex()
     609              lexer = lex.lexer
     610
     611          # Set up the lexer and parser objects on pslice
     612          pslice.lexer = lexer
     613          pslice.parser = self
     614
     615          # If input was supplied, pass to lexer
     616          if input is not None:
     617              lexer.input(input)
     618
     619          if tokenfunc is None:
     620             # Tokenize function
     621             get_token = lexer.token
     622          else:
     623             get_token = tokenfunc
     624
     625          # Set up the state and symbol stacks
     626
     627          statestack = [ ]                # Stack of parsing states
     628          self.statestack = statestack
     629          symstack   = [ ]                # Stack of grammar symbols
     630          self.symstack = symstack
     631
     632          pslice.stack = symstack         # Put in the production
     633          errtoken   = None               # Err token
     634
     635          # The start state is assumed to be (0,$end)
     636
     637          statestack.append(0)
     638          sym = YaccSymbol()
     639          sym.type = '$end'
     640          symstack.append(sym)
     641          state = 0
     642          while 1:
     643              # Get the next symbol on the input.  If a lookahead symbol
     644              # is already set, we just use that. Otherwise, we'll pull
     645              # the next token off of the lookaheadstack or from the lexer
     646
     647              if not lookahead:
     648                  if not lookaheadstack:
     649                      lookahead = get_token()     # Get the next token
     650                  else:
     651                      lookahead = lookaheadstack.pop()
     652                  if not lookahead:
     653                      lookahead = YaccSymbol()
     654                      lookahead.type = '$end'
     655
     656              # Check the action table
     657              ltype = lookahead.type
     658              t = actions[state].get(ltype)
     659
     660              if t is not None:
     661                  if t > 0:
     662                      # shift a symbol on the stack
     663                      statestack.append(t)
     664                      state = t
     665
     666                      symstack.append(lookahead)
     667                      lookahead = None
     668
     669                      # Decrease error count on successful shift
     670                      if errorcount: errorcount -=1
     671                      continue
     672
     673                  if t < 0:
     674                      # reduce a symbol on the stack, emit a production
     675                      p = prod[-t]
     676                      pname = p.name
     677                      plen  = p.len
     678
     679                      # Get production function
     680                      sym = YaccSymbol()
     681                      sym.type = pname       # Production name
     682                      sym.value = None
     683
     684                      if plen:
     685                          targ = symstack[-plen-1:]
     686                          targ[0] = sym
     687
     688                          # --! TRACKING
     689                          if tracking:
     690                             t1 = targ[1]
     691                             sym.lineno = t1.lineno
     692                             sym.lexpos = t1.lexpos
     693                             t1 = targ[-1]
     694                             sym.endlineno = getattr(t1,"endlineno",t1.lineno)
     695                             sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos)
     696
     697                          # --! TRACKING
     698
     699                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     700                          # The code enclosed in this section is duplicated
     701                          # below as a performance optimization.  Make sure
     702                          # changes get made in both locations.
     703
     704                          pslice.slice = targ
     705
     706                          try:
     707                              # Call the grammar rule with our special slice object
     708                              del symstack[-plen:]
     709                              del statestack[-plen:]
     710                              p.callable(pslice)
     711                              symstack.append(sym)
     712                              state = goto[statestack[-1]][pname]
     713                              statestack.append(state)
     714                          except SyntaxError:
     715                              # If an error was set. Enter error recovery state
     716                              lookaheadstack.append(lookahead)
     717                              symstack.pop()
     718                              statestack.pop()
     719                              state = statestack[-1]
     720                              sym.type = 'error'
     721                              lookahead = sym
     722                              errorcount = error_count
     723                              self.errorok = 0
     724                          continue
     725                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     726
     727                      else:
     728
     729                          # --! TRACKING
     730                          if tracking:
     731                             sym.lineno = lexer.lineno
     732                             sym.lexpos = lexer.lexpos
     733                          # --! TRACKING
     734
     735                          targ = [ sym ]
     736
     737                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     738                          # The code enclosed in this section is duplicated
     739                          # above as a performance optimization.  Make sure
     740                          # changes get made in both locations.
     741
     742                          pslice.slice = targ
     743
     744                          try:
     745                              # Call the grammar rule with our special slice object
     746                              p.callable(pslice)
     747                              symstack.append(sym)
     748                              state = goto[statestack[-1]][pname]
     749                              statestack.append(state)
     750                          except SyntaxError:
     751                              # If an error was set. Enter error recovery state
     752                              lookaheadstack.append(lookahead)
     753                              symstack.pop()
     754                              statestack.pop()
     755                              state = statestack[-1]
     756                              sym.type = 'error'
     757                              lookahead = sym
     758                              errorcount = error_count
     759                              self.errorok = 0
     760                          continue
     761                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     762
     763                  if t == 0:
     764                      n = symstack[-1]
     765                      return getattr(n,"value",None)
     766
     767              if t == None:
     768
     769                  # We have some kind of parsing error here.  To handle
     770                  # this, we are going to push the current token onto
     771                  # the tokenstack and replace it with an 'error' token.
     772                  # If there are any synchronization rules, they may
     773                  # catch it.
     774                  #
     775                  # In addition to pushing the error token, we call call
     776                  # the user defined p_error() function if this is the
     777                  # first syntax error.  This function is only called if
     778                  # errorcount == 0.
     779                  if errorcount == 0 or self.errorok:
     780                      errorcount = error_count
     781                      self.errorok = 0
     782                      errtoken = lookahead
     783                      if errtoken.type == '$end':
     784                          errtoken = None               # End of file!
     785                      if self.errorfunc:
     786                          global errok,token,restart
     787                          errok = self.errok        # Set some special functions available in error recovery
     788                          token = get_token
     789                          restart = self.restart
     790                          if errtoken and not hasattr(errtoken,'lexer'):
     791                              errtoken.lexer = lexer
     792                          tok = self.errorfunc(errtoken)
     793                          del errok, token, restart   # Delete special functions
     794
     795                          if self.errorok:
     796                              # User must have done some kind of panic
     797                              # mode recovery on their own.  The
     798                              # returned token is the next lookahead
     799                              lookahead = tok
     800                              errtoken = None
     801                              continue
     802                      else:
     803                          if errtoken:
     804                              if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
     805                              else: lineno = 0
     806                              if lineno:
     807                                  sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
     808                              else:
     809                                  sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
     810                          else:
     811                              sys.stderr.write("yacc: Parse error in input. EOF\n")
     812                              return
     813
     814                  else:
     815                      errorcount = error_count
     816
     817                  # case 1:  the statestack only has 1 entry on it.  If we're in this state, the
     818                  # entire parse has been rolled back and we're completely hosed.   The token is
     819                  # discarded and we just keep going.
     820
     821                  if len(statestack) <= 1 and lookahead.type != '$end':
     822                      lookahead = None
     823                      errtoken = None
     824                      state = 0
     825                      # Nuke the pushback stack
     826                      del lookaheadstack[:]
     827                      continue
     828
     829                  # case 2: the statestack has a couple of entries on it, but we're
     830                  # at the end of the file. nuke the top entry and generate an error token
     831
     832                  # Start nuking entries on the stack
     833                  if lookahead.type == '$end':
     834                      # Whoa. We're really hosed here. Bail out
     835                      return
     836
     837                  if lookahead.type != 'error':
     838                      sym = symstack[-1]
     839                      if sym.type == 'error':
     840                          # Hmmm. Error is on top of stack, we'll just nuke input
     841                          # symbol and continue
     842                          lookahead = None
     843                          continue
     844                      t = YaccSymbol()
     845                      t.type = 'error'
     846                      if hasattr(lookahead,"lineno"):
     847                          t.lineno = lookahead.lineno
     848                      t.value = lookahead
     849                      lookaheadstack.append(lookahead)
     850                      lookahead = t
     851                  else:
     852                      symstack.pop()
     853                      statestack.pop()
     854                      state = statestack[-1]       # Potential bug fix
     855
     856                  continue
     857
     858              # Call an error function here
     859              raise RuntimeError("yacc: internal parser error!!!\n")
     860
     861      # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     862      # parseopt_notrack().
     863      #
     864      # Optimized version of parseopt() with line number tracking removed.
     865      # DO NOT EDIT THIS CODE DIRECTLY. Copy the optimized version and remove
     866      # code in the #--! TRACKING sections
     867      # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     868
     869 -    def parseopt_notrack(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
     870          lookahead = None                 # Current lookahead symbol
     871          lookaheadstack = [ ]             # Stack of lookahead symbols
     872          actions = self.action            # Local reference to action table (to avoid lookup on self.)
     873          goto    = self.goto              # Local reference to goto table (to avoid lookup on self.)
     874          prod    = self.productions       # Local reference to production list (to avoid lookup on self.)
     875          pslice  = YaccProduction(None)   # Production object passed to grammar rules
     876          errorcount = 0                   # Used during error recovery
     877
     878          # If no lexer was given, we will try to use the lex module
     879          if not lexer:
     880              lex = load_ply_lex()
     881              lexer = lex.lexer
     882
     883          # Set up the lexer and parser objects on pslice
     884          pslice.lexer = lexer
     885          pslice.parser = self
     886
     887          # If input was supplied, pass to lexer
     888          if input is not None:
     889              lexer.input(input)
     890
     891          if tokenfunc is None:
     892             # Tokenize function
     893             get_token = lexer.token
     894          else:
     895             get_token = tokenfunc
     896
     897          # Set up the state and symbol stacks
     898
     899          statestack = [ ]                # Stack of parsing states
     900          self.statestack = statestack
     901          symstack   = [ ]                # Stack of grammar symbols
     902          self.symstack = symstack
     903
     904          pslice.stack = symstack         # Put in the production
     905          errtoken   = None               # Err token
     906
     907          # The start state is assumed to be (0,$end)
     908
     909          statestack.append(0)
     910          sym = YaccSymbol()
     911          sym.type = '$end'
     912          symstack.append(sym)
     913          state = 0
     914          while 1:
     915              # Get the next symbol on the input.  If a lookahead symbol
     916              # is already set, we just use that. Otherwise, we'll pull
     917              # the next token off of the lookaheadstack or from the lexer
     918
     919              if not lookahead:
     920                  if not lookaheadstack:
     921                      lookahead = get_token()     # Get the next token
     922                  else:
     923                      lookahead = lookaheadstack.pop()
     924                  if not lookahead:
     925                      lookahead = YaccSymbol()
     926                      lookahead.type = '$end'
     927
     928              # Check the action table
     929              ltype = lookahead.type
     930              t = actions[state].get(ltype)
     931
     932              if t is not None:
     933                  if t > 0:
     934                      # shift a symbol on the stack
     935                      statestack.append(t)
     936                      state = t
     937
     938                      symstack.append(lookahead)
     939                      lookahead = None
     940
     941                      # Decrease error count on successful shift
     942                      if errorcount: errorcount -=1
     943                      continue
     944
     945                  if t < 0:
     946                      # reduce a symbol on the stack, emit a production
     947                      p = prod[-t]
     948                      pname = p.name
     949                      plen  = p.len
     950
     951                      # Get production function
     952                      sym = YaccSymbol()
     953                      sym.type = pname       # Production name
     954                      sym.value = None
     955
     956                      if plen:
     957                          targ = symstack[-plen-1:]
     958                          targ[0] = sym
     959
     960                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     961                          # The code enclosed in this section is duplicated
     962                          # below as a performance optimization.  Make sure
     963                          # changes get made in both locations.
     964
     965                          pslice.slice = targ
     966
     967                          try:
     968                              # Call the grammar rule with our special slice object
     969                              del symstack[-plen:]
     970                              del statestack[-plen:]
     971                              p.callable(pslice)
     972                              symstack.append(sym)
     973                              state = goto[statestack[-1]][pname]
     974                              statestack.append(state)
     975                          except SyntaxError:
     976                              # If an error was set. Enter error recovery state
     977                              lookaheadstack.append(lookahead)
     978                              symstack.pop()
     979                              statestack.pop()
     980                              state = statestack[-1]
     981                              sym.type = 'error'
     982                              lookahead = sym
     983                              errorcount = error_count
     984                              self.errorok = 0
     985                          continue
     986                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     987
     988                      else:
     989
     990                          targ = [ sym ]
     991
     992                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
     993                          # The code enclosed in this section is duplicated
     994                          # above as a performance optimization.  Make sure
     995                          # changes get made in both locations.
     996
     997                          pslice.slice = targ
     998
     999                          try:
    1000                              # Call the grammar rule with our special slice object
    1001                              p.callable(pslice)
    1002                              symstack.append(sym)
    1003                              state = goto[statestack[-1]][pname]
    1004                              statestack.append(state)
    1005                          except SyntaxError:
    1006                              # If an error was set. Enter error recovery state
    1007                              lookaheadstack.append(lookahead)
    1008                              symstack.pop()
    1009                              statestack.pop()
    1010                              state = statestack[-1]
    1011                              sym.type = 'error'
    1012                              lookahead = sym
    1013                              errorcount = error_count
    1014                              self.errorok = 0
    1015                          continue
    1016                          # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
    1017
    1018                  if t == 0:
    1019                      n = symstack[-1]
    1020                      return getattr(n,"value",None)
    1021
    1022              if t == None:
    1023
    1024                  # We have some kind of parsing error here.  To handle
    1025                  # this, we are going to push the current token onto
    1026                  # the tokenstack and replace it with an 'error' token.
    1027                  # If there are any synchronization rules, they may
    1028                  # catch it.
    1029                  #
    1030                  # In addition to pushing the error token, we call call
    1031                  # the user defined p_error() function if this is the
    1032                  # first syntax error.  This function is only called if
    1033                  # errorcount == 0.
    1034                  if errorcount == 0 or self.errorok:
    1035                      errorcount = error_count
    1036                      self.errorok = 0
    1037                      errtoken = lookahead
    1038                      if errtoken.type == '$end':
    1039                          errtoken = None               # End of file!
    1040                      if self.errorfunc:
    1041                          global errok,token,restart
    1042                          errok = self.errok        # Set some special functions available in error recovery
    1043                          token = get_token
    1044                          restart = self.restart
    1045                          if errtoken and not hasattr(errtoken,'lexer'):
    1046                              errtoken.lexer = lexer
    1047                          tok = self.errorfunc(errtoken)
    1048                          del errok, token, restart   # Delete special functions
    1049
    1050                          if self.errorok:
    1051                              # User must have done some kind of panic
    1052                              # mode recovery on their own.  The
    1053                              # returned token is the next lookahead
    1054                              lookahead = tok
    1055                              errtoken = None
    1056                              continue
    1057                      else:
    1058                          if errtoken:
    1059                              if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
    1060                              else: lineno = 0
    1061                              if lineno:
    1062                                  sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
    1063                              else:
    1064                                  sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
    1065                          else:
    1066                              sys.stderr.write("yacc: Parse error in input. EOF\n")
    1067                              return
    1068
    1069                  else:
    1070                      errorcount = error_count
    1071
    1072                  # case 1:  the statestack only has 1 entry on it.  If we're in this state, the
    1073                  # entire parse has been rolled back and we're completely hosed.   The token is
    1074                  # discarded and we just keep going.
    1075
    1076                  if len(statestack) <= 1 and lookahead.type != '$end':
    1077                      lookahead = None
    1078                      errtoken = None
    1079                      state = 0
    1080                      # Nuke the pushback stack
    1081                      del lookaheadstack[:]
    1082                      continue
    1083
    1084                  # case 2: the statestack has a couple of entries on it, but we're
    1085                  # at the end of the file. nuke the top entry and generate an error token
    1086
    1087                  # Start nuking entries on the stack
    1088                  if lookahead.type == '$end':
    1089                      # Whoa. We're really hosed here. Bail out
    1090                      return
    1091
    1092                  if lookahead.type != 'error':
    1093                      sym = symstack[-1]
    1094                      if sym.type == 'error':
    1095                          # Hmmm. Error is on top of stack, we'll just nuke input
    1096                          # symbol and continue
    1097                          lookahead = None
    1098                          continue
    1099                      t = YaccSymbol()
    1100                      t.type = 'error'
    1101                      if hasattr(lookahead,"lineno"):
    1102                          t.lineno = lookahead.lineno
    1103                      t.value = lookahead
    1104                      lookaheadstack.append(lookahead)
    1105                      lookahead = t
    1106                  else:
    1107                      symstack.pop()
    1108                      statestack.pop()
    1109                      state = statestack[-1]       # Potential bug fix
    1110
    1111                  continue
    1112
    1113              # Call an error function here
    1114              raise RuntimeError("yacc: internal parser error!!!\n")
    1115
    1116  # -----------------------------------------------------------------------------
    1117  #                          === Grammar Representation ===
    1118  #
    1119  # The following functions, classes, and variables are used to represent and
    1120  # manipulate the rules that make up a grammar.
    1121  # -----------------------------------------------------------------------------
    1122
    1123  import re
    1124
    1125  # regex matching identifiers
    1126  _is_identifier = re.compile(r'^[a-zA-Z0-9_-]+$')
    1127
    1128  # -----------------------------------------------------------------------------
    1129  # class Production:
    1130  #
    1131  # This class stores the raw information about a single production or grammar rule.
    1132  # A grammar rule refers to a specification such as this:
    1133  #
    1134  #       expr : expr PLUS term
    1135  #
    1136  # Here are the basic attributes defined on all productions
    1137  #
    1138  #       name     - Name of the production.  For example 'expr'
    1139  #       prod     - A list of symbols on the right side ['expr','PLUS','term']
    1140  #       prec     - Production precedence level
    1141  #       number   - Production number.
    1142  #       func     - Function that executes on reduce
    1143  #       file     - File where production function is defined
    1144  #       lineno   - Line number where production function is defined
    1145  #
    1146  # The following attributes are defined or optional.
    1147  #
    1148  #       len       - Length of the production (number of symbols on right hand side)
    1149  #       usyms     - Set of unique symbols found in the production
    1150  # -----------------------------------------------------------------------------
    1151
    1152 -class Production(object):
    1153      reduced = 0
    1154 -    def __init__(self,number,name,prod,precedence=('right',0),func=None,file='',line=0):
    1155          self.name     = name
    1156          self.prod     = tuple(prod)
    1157          self.number   = number
    1158          self.func     = func
    1159          self.callable = None
    1160          self.file     = file
    1161          self.line     = line
    1162          self.prec     = precedence
    1163
    1164          # Internal settings used during table construction
    1165
    1166          self.len  = len(self.prod)   # Length of the production
    1167
    1168          # Create a list of unique production symbols used in the production
    1169          self.usyms = [ ]
    1170          for s in self.prod:
    1171              if s not in self.usyms:
    1172                  self.usyms.append(s)
    1173
    1174          # List of all LR items for the production
    1175          self.lr_items = []
    1176          self.lr_next = None
    1177
    1178          # Create a string representation
    1179          if self.prod:
    1180              self.str = "%s -> %s" % (self.name," ".join(self.prod))
    1181          else:
    1182              self.str = "%s -> <empty>" % self.name
    1183
    1184 -    def __str__(self):
    1185          return self.str
    1186
    1187 -    def __repr__(self):
    1188          return "Production("+str(self)+")"
    1189
    1190 -    def __len__(self):
    1191          return len(self.prod)
    1192
    1193 -    def __nonzero__(self):
    1194          return 1
    1195
    1196 -    def __getitem__(self,index):
    1197          return self.prod[index]
    1198
    1199      # Return the nth lr_item from the production (or None if at the end)
    1200 -    def lr_item(self,n):
    1201          if n > len(self.prod): return None
    1202          p = LRItem(self,n)
    1203
    1204          # Precompute the list of productions immediately following.  Hack. Remove later
    1205          try:
    1206              p.lr_after = Prodnames[p.prod[n+1]]
    1207          except (IndexError,KeyError):
    1208              p.lr_after = []
    1209          try:
    1210              p.lr_before = p.prod[n-1]
    1211          except IndexError:
    1212              p.lr_before = None
    1213
    1214          return p
    1215
    1216      # Bind the production function name to a callable
    1217 -    def bind(self,pdict):
    1218          if self.func:
    1219              self.callable = pdict[self.func]
    1220
    1221  # This class serves as a minimal standin for Production objects when
    1222  # reading table data from files.   It only contains information
    1223  # actually used by the LR parsing engine, plus some additional
    1224  # debugging information.
    1225 -class MiniProduction(object):
    1226 -    def __init__(self,str,name,len,func,file,line):
    1227          self.name     = name
    1228          self.len      = len
    1229          self.func     = func
    1230          self.callable = None
    1231          self.file     = file
    1232          self.line     = line
    1233          self.str      = str
    1234 -    def __str__(self):
    1235          return self.str
    1236 -    def __repr__(self):
    1237          return "MiniProduction(%s)" % self.str
    1238
    1239      # Bind the production function name to a callable
    1240 -    def bind(self,pdict):
    1241          if self.func:
    1242              self.callable = pdict[self.func]
    1243
    1244
    1245  # -----------------------------------------------------------------------------
    1246  # class LRItem
    1247  #
    1248  # This class represents a specific stage of parsing a production rule.  For
    1249  # example:
    1250  #
    1251  #       expr : expr . PLUS term
    1252  #
    1253  # In the above, the "." represents the current location of the parse.  Here
    1254  # basic attributes:
    1255  #
    1256  #       name       - Name of the production.  For example 'expr'
    1257  #       prod       - A list of symbols on the right side ['expr','.', 'PLUS','term']
    1258  #       number     - Production number.
    1259  #
    1260  #       lr_next      Next LR item. Example, if we are ' expr -> expr . PLUS term'
    1261  #                    then lr_next refers to 'expr -> expr PLUS . term'
    1262  #       lr_index   - LR item index (location of the ".") in the prod list.
    1263  #       lookaheads - LALR lookahead symbols for this item
    1264  #       len        - Length of the production (number of symbols on right hand side)
    1265  #       lr_after    - List of all productions that immediately follow
    1266  #       lr_before   - Grammar symbol immediately before
    1267  # -----------------------------------------------------------------------------
    1268
    1269 -class LRItem(object):
    1270 -    def __init__(self,p,n):
    1271          self.name       = p.name
    1272          self.prod       = list(p.prod)
    1273          self.number     = p.number
    1274          self.lr_index   = n
    1275          self.lookaheads = { }
    1276          self.prod.insert(n,".")
    1277          self.prod       = tuple(self.prod)
    1278          self.len        = len(self.prod)
    1279          self.usyms      = p.usyms
    1280
    1281 -    def __str__(self):
    1282          if self.prod:
    1283              s = "%s -> %s" % (self.name," ".join(self.prod))
    1284          else:
    1285              s = "%s -> <empty>" % self.name
    1286          return s
    1287
    1288 -    def __repr__(self):
    1289          return "LRItem("+str(self)+")"
    1290
    1291  # -----------------------------------------------------------------------------
    1292  # rightmost_terminal()
    1293  #
    1294  # Return the rightmost terminal from a list of symbols.  Used in add_production()
    1295  # -----------------------------------------------------------------------------
    1296 -def rightmost_terminal(symbols, terminals):
    1297      i = len(symbols) - 1
    1298      while i >= 0:
    1299          if symbols[i] in terminals:
    1300              return symbols[i]
    1301          i -= 1
    1302      return None
    1303
    1304  # -----------------------------------------------------------------------------
    1305  #                           === GRAMMAR CLASS ===
    1306  #
    1307  # The following class represents the contents of the specified grammar along
    1308  # with various computed properties such as first sets, follow sets, LR items, etc.
    1309  # This data is used for critical parts of the table generation process later.
    1310  # -----------------------------------------------------------------------------
    1311
    1312 -class GrammarError(YaccError): pass
    1313
    1314 -class Grammar(object):
    1315 -    def __init__(self,terminals):
    1316          self.Productions  = [None]  # A list of all of the productions.  The first
    1317                                      # entry is always reserved for the purpose of
    1318                                      # building an augmented grammar
    1319
    1320          self.Prodnames    = { }     # A dictionary mapping the names of nonterminals to a list of all
    1321                                      # productions of that nonterminal.
    1322
    1323          self.Prodmap      = { }     # A dictionary that is only used to detect duplicate
    1324                                      # productions.
    1325
    1326          self.Terminals    = { }     # A dictionary mapping the names of terminal symbols to a
    1327                                      # list of the rules where they are used.
    1328
    1329          for term in terminals:
    1330              self.Terminals[term] = []
    1331
    1332          self.Terminals['error'] = []
    1333
    1334          self.Nonterminals = { }     # A dictionary mapping names of nonterminals to a list
    1335                                      # of rule numbers where they are used.
    1336
    1337          self.First        = { }     # A dictionary of precomputed FIRST(x) symbols
    1338
    1339          self.Follow       = { }     # A dictionary of precomputed FOLLOW(x) symbols
    1340
    1341          self.Precedence   = { }     # Precedence rules for each terminal. Contains tuples of the
    1342                                      # form ('right',level) or ('nonassoc', level) or ('left',level)
    1343
    1344          self.UsedPrecedence = { }   # Precedence rules that were actually used by the grammer.
    1345                                      # This is only used to provide error checking and to generate
    1346                                      # a warning about unused precedence rules.
    1347
    1348          self.Start = None           # Starting symbol for the grammar
    1349
    1350
    1351 -    def __len__(self):
    1352          return len(self.Productions)
    1353
    1354 -    def __getitem__(self,index):
    1355          return self.Productions[index]
    1356
    1357      # -----------------------------------------------------------------------------
    1358      # set_precedence()
    1359      #
    1360      # Sets the precedence for a given terminal. assoc is the associativity such as
    1361      # 'left','right', or 'nonassoc'.  level is a numeric level.
    1362      #
    1363      # -----------------------------------------------------------------------------
    1364
    1365 -    def set_precedence(self,term,assoc,level):
    1366          assert self.Productions == [None],"Must call set_precedence() before add_production()"
    1367          if term in self.Precedence:
    1368              raise GrammarError("Precedence already specified for terminal '%s'" % term)
    1369          if assoc not in ['left','right','nonassoc']:
    1370              raise GrammarError("Associativity must be one of 'left','right', or 'nonassoc'")
    1371          self.Precedence[term] = (assoc,level)
    1372
    1373      # -----------------------------------------------------------------------------
    1374      # add_production()
    1375      #
    1376      # Given an action function, this function assembles a production rule and
    1377      # computes its precedence level.
    1378      #
    1379      # The production rule is supplied as a list of symbols.   For example,
    1380      # a rule such as 'expr : expr PLUS term' has a production name of 'expr' and
    1381      # symbols ['expr','PLUS','term'].
    1382      #
    1383      # Precedence is determined by the precedence of the right-most non-terminal
    1384      # or the precedence of a terminal specified by %prec.
    1385      #
    1386      # A variety of error checks are performed to make sure production symbols
    1387      # are valid and that %prec is used correctly.
    1388      # -----------------------------------------------------------------------------
    1389
    1390 -    def add_production(self,prodname,syms,func=None,file='',line=0):
    1391
    1392          if prodname in self.Terminals:
    1393              raise GrammarError("%s:%d: Illegal rule name '%s'. Already defined as a token" % (file,line,prodname))
    1394          if prodname == 'error':
    1395              raise GrammarError("%s:%d: Illegal rule name '%s'. error is a reserved word" % (file,line,prodname))
    1396          if not _is_identifier.match(prodname):
    1397              raise GrammarError("%s:%d: Illegal rule name '%s'" % (file,line,prodname))
    1398
    1399          # Look for literal tokens
    1400          for n,s in enumerate(syms):
    1401              if s[0] in "'\"":
    1402                   try:
    1403                       c = eval(s)
    1404                       if (len(c) > 1):
    1405                            raise GrammarError("%s:%d: Literal token %s in rule '%s' may only be a single character" % (file,line,s, prodname))
    1406                       if not c in self.Terminals:
    1407                            self.Terminals[c] = []
    1408                       syms[n] = c
    1409                       continue
    1410                   except SyntaxError:
    1411                       pass
    1412              if not _is_identifier.match(s) and s != '%prec':
    1413                  raise GrammarError("%s:%d: Illegal name '%s' in rule '%s'" % (file,line,s, prodname))
    1414
    1415          # Determine the precedence level
    1416          if '%prec' in syms:
    1417              if syms[-1] == '%prec':
    1418                  raise GrammarError("%s:%d: Syntax error. Nothing follows %%prec" % (file,line))
    1419              if syms[-2] != '%prec':
    1420                  raise GrammarError("%s:%d: Syntax error. %%prec can only appear at the end of a grammar rule" % (file,line))
    1421              precname = syms[-1]
    1422              prodprec = self.Precedence.get(precname,None)
    1423              if not prodprec:
    1424                  raise GrammarError("%s:%d: Nothing known about the precedence of '%s'" % (file,line,precname))
    1425              else:
    1426                  self.UsedPrecedence[precname] = 1
    1427              del syms[-2:]     # Drop %prec from the rule
    1428          else:
    1429              # If no %prec, precedence is determined by the rightmost terminal symbol
    1430              precname = rightmost_terminal(syms,self.Terminals)
    1431              prodprec = self.Precedence.get(precname,('right',0))
    1432
    1433          # See if the rule is already in the rulemap
    1434          map = "%s -> %s" % (prodname,syms)
    1435          if map in self.Prodmap:
    1436              m = self.Prodmap[map]
    1437              raise GrammarError("%s:%d: Duplicate rule %s. " % (file,line, m) +
    1438                                 "Previous definition at %s:%d" % (m.file, m.line))
    1439
    1440          # From this point on, everything is valid.  Create a new Production instance
    1441          pnumber  = len(self.Productions)
    1442          if not prodname in self.Nonterminals:
    1443              self.Nonterminals[prodname] = [ ]
    1444
    1445          # Add the production number to Terminals and Nonterminals
    1446          for t in syms:
    1447              if t in self.Terminals:
    1448                  self.Terminals[t].append(pnumber)
    1449              else:
    1450                  if not t in self.Nonterminals:
    1451                      self.Nonterminals[t] = [ ]
    1452                  self.Nonterminals[t].append(pnumber)
    1453
    1454          # Create a production and add it to the list of productions
    1455          p = Production(pnumber,prodname,syms,prodprec,func,file,line)
    1456          self.Productions.append(p)
    1457          self.Prodmap[map] = p
    1458
    1459          # Add to the global productions list
    1460          try:
    1461              self.Prodnames[prodname].append(p)
    1462          except KeyError:
    1463              self.Prodnames[prodname] = [ p ]
    1464          return 0
    1465
    1466      # -----------------------------------------------------------------------------
    1467      # set_start()
    1468      #
    1469      # Sets the starting symbol and creates the augmented grammar.  Production
    1470      # rule 0 is S' -> start where start is the start symbol.
    1471      # -----------------------------------------------------------------------------
    1472
    1473 -    def set_start(self,start=None):
    1474          if not start:
    1475              start = self.Productions[1].name
    1476          if start not in self.Nonterminals:
    1477              raise GrammarError("start symbol %s undefined" % start)
    1478          self.Productions[0] = Production(0,"S'",[start])
    1479          self.Nonterminals[start].append(0)
    1480          self.Start = start
    1481
    1482      # -----------------------------------------------------------------------------
    1483      # find_unreachable()
    1484      #
    1485      # Find all of the nonterminal symbols that can't be reached from the starting
    1486      # symbol.  Returns a list of nonterminals that can't be reached.
    1487      # -----------------------------------------------------------------------------
    1488
    1489 -    def find_unreachable(self):
    1490
    1491          # Mark all symbols that are reachable from a symbol s
    1492          def mark_reachable_from(s):
    1493              if reachable[s]:
    1494                  # We've already reached symbol s.
    1495                  return
    1496              reachable[s] = 1
    1497              for p in self.Prodnames.get(s,[]):
    1498                  for r in p.prod:
    1499                      mark_reachable_from(r)
    1500
    1501          reachable   = { }
    1502          for s in list(self.Terminals) + list(self.Nonterminals):
    1503              reachable[s] = 0
    1504
    1505          mark_reachable_from( self.Productions[0].prod[0] )
    1506
    1507          return [s for s in list(self.Nonterminals)
    1508                          if not reachable[s]]
    1509
    1510      # -----------------------------------------------------------------------------
    1511      # infinite_cycles()
    1512      #
    1513      # This function looks at the various parsing rules and tries to detect
    1514      # infinite recursion cycles (grammar rules where there is no possible way
    1515      # to derive a string of only terminals).
    1516      # -----------------------------------------------------------------------------
    1517
    1518 -    def infinite_cycles(self):
    1519          terminates = {}
    1520
    1521          # Terminals:
    1522          for t in self.Terminals:
    1523              terminates[t] = 1
    1524
    1525          terminates['$end'] = 1
    1526
    1527          # Nonterminals:
    1528
    1529          # Initialize to false:
    1530          for n in self.Nonterminals:
    1531              terminates[n] = 0
    1532
    1533          # Then propagate termination until no change:
    1534          while 1:
    1535              some_change = 0
    1536              for (n,pl) in self.Prodnames.items():
    1537                  # Nonterminal n terminates iff any of its productions terminates.
    1538                  for p in pl:
    1539                      # Production p terminates iff all of its rhs symbols terminate.
    1540                      for s in p.prod:
    1541                          if not terminates[s]:
    1542                              # The symbol s does not terminate,
    1543                              # so production p does not terminate.
    1544                              p_terminates = 0
    1545                              break
    1546                      else:
    1547                          # didn't break from the loop,
    1548                          # so every symbol s terminates
    1549                          # so production p terminates.
    1550                          p_terminates = 1
    1551
    1552                      if p_terminates:
    1553                          # symbol n terminates!
    1554                          if not terminates[n]:
    1555                              terminates[n] = 1
    1556                              some_change = 1
    1557                          # Don't need to consider any more productions for this n.
    1558                          break
    1559
    1560              if not some_change:
    1561                  break
    1562
    1563          infinite = []
    1564          for (s,term) in terminates.items():
    1565              if not term:
    1566                  if not s in self.Prodnames and not s in self.Terminals and s != 'error':
    1567                      # s is used-but-not-defined, and we've already warned of that,
    1568                      # so it would be overkill to say that it's also non-terminating.
    1569                      pass
    1570                  else:
    1571                      infinite.append(s)
    1572
    1573          return infinite
    1574
    1575
    1576      # -----------------------------------------------------------------------------
    1577      # undefined_symbols()
    1578      #
    1579      # Find all symbols that were used the grammar, but not defined as tokens or
    1580      # grammar rules.  Returns a list of tuples (sym, prod) where sym in the symbol
    1581      # and prod is the production where the symbol was used.
    1582      # -----------------------------------------------------------------------------
    1583 -    def undefined_symbols(self):
    1584          result = []
    1585          for p in self.Productions:
    1586              if not p: continue
    1587
    1588              for s in p.prod:
    1589                  if not s in self.Prodnames and not s in self.Terminals and s != 'error':
    1590                      result.append((s,p))
    1591          return result
    1592
    1593      # -----------------------------------------------------------------------------
    1594      # unused_terminals()
    1595      #
    1596      # Find all terminals that were defined, but not used by the grammar.  Returns
    1597      # a list of all symbols.
    1598      # -----------------------------------------------------------------------------
    1599 -    def unused_terminals(self):
    1600          unused_tok = []
    1601          for s,v in self.Terminals.items():
    1602              if s != 'error' and not v:
    1603                  unused_tok.append(s)
    1604
    1605          return unused_tok
    1606
    1607      # ------------------------------------------------------------------------------
    1608      # unused_rules()
    1609      #
    1610      # Find all grammar rules that were defined,  but not used (maybe not reachable)
    1611      # Returns a list of productions.
    1612      # ------------------------------------------------------------------------------
    1613
    1614 -    def unused_rules(self):
    1615          unused_prod = []
    1616          for s,v in self.Nonterminals.items():
    1617              if not v:
    1618                  p = self.Prodnames[s][0]
    1619                  unused_prod.append(p)
    1620          return unused_prod
    1621
    1622      # -----------------------------------------------------------------------------
    1623      # unused_precedence()
    1624      #
    1625      # Returns a list of tuples (term,precedence) corresponding to precedence
    1626      # rules that were never used by the grammar.  term is the name of the terminal
    1627      # on which precedence was applied and precedence is a string such as 'left' or
    1628      # 'right' corresponding to the type of precedence.
    1629      # -----------------------------------------------------------------------------
    1630
    1631 -    def unused_precedence(self):
    1632          unused = []
    1633          for termname in self.Precedence:
    1634              if not (termname in self.Terminals or termname in self.UsedPrecedence):
    1635                  unused.append((termname,self.Precedence[termname][0]))
    1636
    1637          return unused
    1638
    1639      # -------------------------------------------------------------------------
    1640      # _first()
    1641      #
    1642      # Compute the value of FIRST1(beta) where beta is a tuple of symbols.
    1643      #
    1644      # During execution of compute_first1, the result may be incomplete.
    1645      # Afterward (e.g., when called from compute_follow()), it will be complete.
    1646      # -------------------------------------------------------------------------
    1647 -    def _first(self,beta):
    1648
    1649          # We are computing First(x1,x2,x3,...,xn)
    1650          result = [ ]
    1651          for x in beta:
    1652              x_produces_empty = 0
    1653
    1654              # Add all the non-<empty> symbols of First[x] to the result.
    1655              for f in self.First[x]:
    1656                  if f == '<empty>':
    1657                      x_produces_empty = 1
    1658                  else:
    1659                      if f not in result: result.append(f)
    1660
    1661              if x_produces_empty:
    1662                  # We have to consider the next x in beta,
    1663                  # i.e. stay in the loop.
    1664                  pass
    1665              else:
    1666                  # We don't have to consider any further symbols in beta.
    1667                  break
    1668          else:
    1669              # There was no 'break' from the loop,
    1670              # so x_produces_empty was true for all x in beta,
    1671              # so beta produces empty as well.
    1672              result.append('<empty>')
    1673
    1674          return result
    1675
    1676      # -------------------------------------------------------------------------
    1677      # compute_first()
    1678      #
    1679      # Compute the value of FIRST1(X) for all symbols
    1680      # -------------------------------------------------------------------------
    1681 -    def compute_first(self):
    1682          if self.First:
    1683              return self.First
    1684
    1685          # Terminals:
    1686          for t in self.Terminals:
    1687              self.First[t] = [t]
    1688
    1689          self.First['$end'] = ['$end']
    1690
    1691          # Nonterminals:
    1692
    1693          # Initialize to the empty set:
    1694          for n in self.Nonterminals:
    1695              self.First[n] = []
    1696
    1697          # Then propagate symbols until no change:
    1698          while 1:
    1699              some_change = 0
    1700              for n in self.Nonterminals:
    1701                  for p in self.Prodnames[n]:
    1702                      for f in self._first(p.prod):
    1703                          if f not in self.First[n]:
    1704                              self.First[n].append( f )
    1705                              some_change = 1
    1706              if not some_change:
    1707                  break
    1708
    1709          return self.First
    1710
    1711      # ---------------------------------------------------------------------
    1712      # compute_follow()
    1713      #
    1714      # Computes all of the follow sets for every non-terminal symbol.  The
    1715      # follow set is the set of all symbols that might follow a given
    1716      # non-terminal.  See the Dragon book, 2nd Ed. p. 189.
    1717      # ---------------------------------------------------------------------
    1718 -    def compute_follow(self,start=None):
    1719          # If already computed, return the result
    1720          if self.Follow:
    1721              return self.Follow
    1722
    1723          # If first sets not computed yet, do that first.
    1724          if not self.First:
    1725              self.compute_first()
    1726
    1727          # Add '$end' to the follow list of the start symbol
    1728          for k in self.Nonterminals:
    1729              self.Follow[k] = [ ]
    1730
    1731          if not start:
    1732              start = self.Productions[1].name
    1733
    1734          self.Follow[start] = [ '$end' ]
    1735
    1736          while 1:
    1737              didadd = 0
    1738              for p in self.Productions[1:]:
    1739                  # Here is the production set
    1740                  for i in range(len(p.prod)):
    1741                      B = p.prod[i]
    1742                      if B in self.Nonterminals:
    1743                          # Okay. We got a non-terminal in a production
    1744                          fst = self._first(p.prod[i+1:])
    1745                          hasempty = 0
    1746                          for f in fst:
    1747                              if f != '<empty>' and f not in self.Follow[B]:
    1748                                  self.Follow[B].append(f)
    1749                                  didadd = 1
    1750                              if f == '<empty>':
    1751                                  hasempty = 1
    1752                          if hasempty or i == (len(p.prod)-1):
    1753                              # Add elements of follow(a) to follow(b)
    1754                              for f in self.Follow[p.name]:
    1755                                  if f not in self.Follow[B]:
    1756                                      self.Follow[B].append(f)
    1757                                      didadd = 1
    1758              if not didadd: break
    1759          return self.Follow
    1760
    1761
    1762      # -----------------------------------------------------------------------------
    1763      # build_lritems()
    1764      #
    1765      # This function walks the list of productions and builds a complete set of the
    1766      # LR items.  The LR items are stored in two ways:  First, they are uniquely
    1767      # numbered and placed in the list _lritems.  Second, a linked list of LR items
    1768      # is built for each production.  For example:
    1769      #
    1770      #   E -> E PLUS E
    1771      #
    1772      # Creates the list
    1773      #
    1774      #  [E -> . E PLUS E, E -> E . PLUS E, E -> E PLUS . E, E -> E PLUS E . ]
    1775      # -----------------------------------------------------------------------------
    1776
    1777 -    def build_lritems(self):
    1778          for p in self.Productions:
    1779              lastlri = p
    1780              i = 0
    1781              lr_items = []
    1782              while 1:
    1783                  if i > len(p):
    1784                      lri = None
    1785                  else:
    1786                      lri = LRItem(p,i)
    1787                      # Precompute the list of productions immediately following
    1788                      try:
    1789                          lri.lr_after = self.Prodnames[lri.prod[i+1]]
    1790                      except (IndexError,KeyError):
    1791                          lri.lr_after = []
    1792                      try:
    1793                          lri.lr_before = lri.prod[i-1]
    1794                      except IndexError:
    1795                          lri.lr_before = None
    1796
    1797                  lastlri.lr_next = lri
    1798                  if not lri: break
    1799                  lr_items.append(lri)
    1800                  lastlri = lri
    1801                  i += 1
    1802              p.lr_items = lr_items
    1803
    1804  # -----------------------------------------------------------------------------
    1805  #                            == Class LRTable ==
    1806  #
    1807  # This basic class represents a basic table of LR parsing information.
    1808  # Methods for generating the tables are not defined here.  They are defined
    1809  # in the derived class LRGeneratedTable.
    1810  # -----------------------------------------------------------------------------
    1811
    1812 -class VersionError(YaccError): pass
    1813
    1814 -class LRTable(object):
    1815 -    def __init__(self):
    1816          self.lr_action = None
    1817          self.lr_goto = None
    1818          self.lr_productions = None
    1819          self.lr_method = None
    1820
    1821 -    def read_table(self,module):
    1822          if isinstance(module,types.ModuleType):
    1823              parsetab = module
    1824          else:
    1825              if sys.version_info[0] < 3:
    1826                  exec("import %s as parsetab" % module)
    1827              else:
    1828                  env = { }
    1829                  exec("import %s as parsetab" % module, env, env)
    1830                  parsetab = env['parsetab']
    1831
    1832          if parsetab._tabversion != __tabversion__:
    1833              raise VersionError("yacc table file version is out of date")
    1834
    1835          self.lr_action = parsetab._lr_action
    1836          self.lr_goto = parsetab._lr_goto
    1837
    1838          self.lr_productions = []
    1839          for p in parsetab._lr_productions:
    1840              self.lr_productions.append(MiniProduction(*p))
    1841
    1842          self.lr_method = parsetab._lr_method
    1843          return parsetab._lr_signature
    1844
    1845 -    def read_pickle(self,filename):
    1846          try:
    1847              import cPickle as pickle
    1848          except ImportError:
    1849              import pickle
    1850
    1851          in_f = open(filename,"rb")
    1852
    1853          tabversion = pickle.load(in_f)
    1854          if tabversion != __tabversion__:
    1855              raise VersionError("yacc table file version is out of date")
    1856          self.lr_method = pickle.load(in_f)
    1857          signature      = pickle.load(in_f)
    1858          self.lr_action = pickle.load(in_f)
    1859          self.lr_goto   = pickle.load(in_f)
    1860          productions    = pickle.load(in_f)
    1861
    1862          self.lr_productions = []
    1863          for p in productions:
    1864              self.lr_productions.append(MiniProduction(*p))
    1865
    1866          in_f.close()
    1867          return signature
    1868
    1869      # Bind all production function names to callable objects in pdict
    1870 -    def bind_callables(self,pdict):
    1871          for p in self.lr_productions:
    1872              p.bind(pdict)
    1873
    1874  # -----------------------------------------------------------------------------
    1875  #                           === LR Generator ===
    1876  #
    1877  # The following classes and functions are used to generate LR parsing tables on
    1878  # a grammar.
    1879  # -----------------------------------------------------------------------------
    1880
    1881  # -----------------------------------------------------------------------------
    1882  # digraph()
    1883  # traverse()
    1884  #
    1885  # The following two functions are used to compute set valued functions
    1886  # of the form:
    1887  #
    1888  #     F(x) = F'(x) U U{F(y) | x R y}
    1889  #
    1890  # This is used to compute the values of Read() sets as well as FOLLOW sets
    1891  # in LALR(1) generation.
    1892  #
    1893  # Inputs:  X    - An input set
    1894  #          R    - A relation
    1895  #          FP   - Set-valued function
    1896  # ------------------------------------------------------------------------------
    1897
    1898 -def digraph(X,R,FP):
    1899      N = { }
    1900      for x in X:
    1901         N[x] = 0
    1902      stack = []
    1903      F = { }
    1904      for x in X:
    1905          if N[x] == 0: traverse(x,N,stack,F,X,R,FP)
    1906      return F
    1907
    1908 -def traverse(x,N,stack,F,X,R,FP):
    1909      stack.append(x)
    1910      d = len(stack)
    1911      N[x] = d
    1912      F[x] = FP(x)             # F(X) <- F'(x)
    1913
    1914      rel = R(x)               # Get y's related to x
    1915      for y in rel:
    1916          if N[y] == 0:
    1917               traverse(y,N,stack,F,X,R,FP)
    1918          N[x] = min(N[x],N[y])
    1919          for a in F.get(y,[]):
    1920              if a not in F[x]: F[x].append(a)
    1921      if N[x] == d:
    1922         N[stack[-1]] = MAXINT
    1923         F[stack[-1]] = F[x]
    1924         element = stack.pop()
    1925         while element != x:
    1926             N[stack[-1]] = MAXINT
    1927             F[stack[-1]] = F[x]
    1928             element = stack.pop()
    1929
    1930 -class LALRError(YaccError): pass
    1931
    1932  # -----------------------------------------------------------------------------
    1933  #                             == LRGeneratedTable ==
    1934  #
    1935  # This class implements the LR table generation algorithm.  There are no
    1936  # public methods except for write()
    1937  # -----------------------------------------------------------------------------
    1938
    1939 -class LRGeneratedTable(LRTable):
    1940 -    def __init__(self,grammar,method='LALR',log=None):
    1941          if method not in ['SLR','LALR']:
    1942              raise LALRError("Unsupported method %s" % method)
    1943
    1944          self.grammar = grammar
    1945          self.lr_method = method
    1946
    1947          # Set up the logger
    1948          if not log:
    1949              log = NullLogger()
    1950          self.log = log
    1951
    1952          # Internal attributes
    1953          self.lr_action     = {}        # Action table
    1954          self.lr_goto       = {}        # Goto table
    1955          self.lr_productions  = grammar.Productions    # Copy of grammar Production array
    1956          self.lr_goto_cache = {}        # Cache of computed gotos
    1957          self.lr0_cidhash   = {}        # Cache of closures
    1958
    1959          self._add_count    = 0         # Internal counter used to detect cycles
    1960
    1961          # Diagonistic information filled in by the table generator
    1962          self.sr_conflict   = 0
    1963          self.rr_conflict   = 0
    1964          self.conflicts     = []        # List of conflicts
    1965
    1966          self.sr_conflicts  = []
    1967          self.rr_conflicts  = []
    1968
    1969          # Build the tables
    1970          self.grammar.build_lritems()
    1971          self.grammar.compute_first()
    1972          self.grammar.compute_follow()
    1973          self.lr_parse_table()
    1974
    1975      # Compute the LR(0) closure operation on I, where I is a set of LR(0) items.
    1976
    1977 -    def lr0_closure(self,I):
    1978          self._add_count += 1
    1979
    1980          # Add everything in I to J
    1981          J = I[:]
    1982          didadd = 1
    1983          while didadd:
    1984              didadd = 0
    1985              for j in J:
    1986                  for x in j.lr_after:
    1987                      if getattr(x,"lr0_added",0) == self._add_count: continue
    1988                      # Add B --> .G to J
    1989                      J.append(x.lr_next)
    1990                      x.lr0_added = self._add_count
    1991                      didadd = 1
    1992
    1993          return J
    1994
    1995      # Compute the LR(0) goto function goto(I,X) where I is a set
    1996      # of LR(0) items and X is a grammar symbol.   This function is written
    1997      # in a way that guarantees uniqueness of the generated goto sets
    1998      # (i.e. the same goto set will never be returned as two different Python
    1999      # objects).  With uniqueness, we can later do fast set comparisons using
    2000      # id(obj) instead of element-wise comparison.
    2001
    2002 -    def lr0_goto(self,I,x):
    2003          # First we look for a previously cached entry
    2004          g = self.lr_goto_cache.get((id(I),x),None)
    2005          if g: return g
    2006
    2007          # Now we generate the goto set in a way that guarantees uniqueness
    2008          # of the result
    2009
    2010          s = self.lr_goto_cache.get(x,None)
    2011          if not s:
    2012              s = { }
    2013              self.lr_goto_cache[x] = s
    2014
    2015          gs = [ ]
    2016          for p in I:
    2017              n = p.lr_next
    2018              if n and n.lr_before == x:
    2019                  s1 = s.get(id(n),None)
    2020                  if not s1:
    2021                      s1 = { }
    2022                      s[id(n)] = s1
    2023                  gs.append(n)
    2024                  s = s1
    2025          g = s.get('$end',None)
    2026          if not g:
    2027              if gs:
    2028                  g = self.lr0_closure(gs)
    2029                  s['$end'] = g
    2030              else:
    2031                  s['$end'] = gs
    2032          self.lr_goto_cache[(id(I),x)] = g
    2033          return g
    2034
    2035      # Compute the LR(0) sets of item function
    2036 -    def lr0_items(self):
    2037
    2038          C = [ self.lr0_closure([self.grammar.Productions[0].lr_next]) ]
    2039          i = 0
    2040          for I in C:
    2041              self.lr0_cidhash[id(I)] = i
    2042              i += 1
    2043
    2044          # Loop over the items in C and each grammar symbols
    2045          i = 0
    2046          while i < len(C):
    2047              I = C[i]
    2048              i += 1
    2049
    2050              # Collect all of the symbols that could possibly be in the goto(I,X) sets
    2051              asyms = { }
    2052              for ii in I:
    2053                  for s in ii.usyms:
    2054                      asyms[s] = None
    2055
    2056              for x in asyms:
    2057                  g = self.lr0_goto(I,x)
    2058                  if not g:  continue
    2059                  if id(g) in self.lr0_cidhash: continue
    2060                  self.lr0_cidhash[id(g)] = len(C)
    2061                  C.append(g)
    2062
    2063          return C
    2064
    2065      # -----------------------------------------------------------------------------
    2066      #                       ==== LALR(1) Parsing ====
    2067      #
    2068      # LALR(1) parsing is almost exactly the same as SLR except that instead of
    2069      # relying upon Follow() sets when performing reductions, a more selective
    2070      # lookahead set that incorporates the state of the LR(0) machine is utilized.
    2071      # Thus, we mainly just have to focus on calculating the lookahead sets.
    2072      #
    2073      # The method used here is due to DeRemer and Pennelo (1982).
    2074      #
    2075      # DeRemer, F. L., and T. J. Pennelo: "Efficient Computation of LALR(1)
    2076      #     Lookahead Sets", ACM Transactions on Programming Languages and Systems,
    2077      #     Vol. 4, No. 4, Oct. 1982, pp. 615-649
    2078      #
    2079      # Further details can also be found in:
    2080      #
    2081      #  J. Tremblay and P. Sorenson, "The Theory and Practice of Compiler Writing",
    2082      #      McGraw-Hill Book Company, (1985).
    2083      #
    2084      # -----------------------------------------------------------------------------
    2085
    2086      # -----------------------------------------------------------------------------
    2087      # compute_nullable_nonterminals()
    2088      #
    2089      # Creates a dictionary containing all of the non-terminals that might produce
    2090      # an empty production.
    2091      # -----------------------------------------------------------------------------
    2092
    2093 -    def compute_nullable_nonterminals(self):
    2094          nullable = {}
    2095          num_nullable = 0
    2096          while 1:
    2097             for p in self.grammar.Productions[1:]:
    2098                 if p.len == 0:
    2099                      nullable[p.name] = 1
    2100                      continue
    2101                 for t in p.prod:
    2102                      if not t in nullable: break
    2103                 else:
    2104                      nullable[p.name] = 1
    2105             if len(nullable) == num_nullable: break
    2106             num_nullable = len(nullable)
    2107          return nullable
    2108
    2109      # -----------------------------------------------------------------------------
    2110      # find_nonterminal_trans(C)
    2111      #
    2112      # Given a set of LR(0) items, this functions finds all of the non-terminal
    2113      # transitions.    These are transitions in which a dot appears immediately before
    2114      # a non-terminal.   Returns a list of tuples of the form (state,N) where state
    2115      # is the state number and N is the nonterminal symbol.
    2116      #
    2117      # The input C is the set of LR(0) items.
    2118      # -----------------------------------------------------------------------------
    2119
    2120 -    def find_nonterminal_transitions(self,C):
    2121           trans = []
    2122           for state in range(len(C)):
    2123               for p in C[state]:
    2124                   if p.lr_index < p.len - 1:
    2125                        t = (state,p.prod[p.lr_index+1])
    2126                        if t[1] in self.grammar.Nonterminals:
    2127                              if t not in trans: trans.append(t)
    2128               state = state + 1
    2129           return trans
    2130
    2131      # -----------------------------------------------------------------------------
    2132      # dr_relation()
    2133      #
    2134      # Computes the DR(p,A) relationships for non-terminal transitions.  The input
    2135      # is a tuple (state,N) where state is a number and N is a nonterminal symbol.
    2136      #
    2137      # Returns a list of terminals.
    2138      # -----------------------------------------------------------------------------
    2139
    2140 -    def dr_relation(self,C,trans,nullable):
    2141          dr_set = { }
    2142          state,N = trans
    2143          terms = []
    2144
    2145          g = self.lr0_goto(C[state],N)
    2146          for p in g:
    2147             if p.lr_index < p.len - 1:
    2148                 a = p.prod[p.lr_index+1]
    2149                 if a in self.grammar.Terminals:
    2150                     if a not in terms: terms.append(a)
    2151
    2152          # This extra bit is to handle the start state
    2153          if state == 0 and N == self.grammar.Productions[0].prod[0]:
    2154             terms.append('$end')
    2155
    2156          return terms
    2157
    2158      # -----------------------------------------------------------------------------
    2159      # reads_relation()
    2160      #
    2161      # Computes the READS() relation (p,A) READS (t,C).
    2162      # -----------------------------------------------------------------------------
    2163
    2164 -    def reads_relation(self,C, trans, empty):
    2165          # Look for empty transitions
    2166          rel = []
    2167          state, N = trans
    2168
    2169          g = self.lr0_goto(C[state],N)
    2170          j = self.lr0_cidhash.get(id(g),-1)
    2171          for p in g:
    2172              if p.lr_index < p.len - 1:
    2173                   a = p.prod[p.lr_index + 1]
    2174                   if a in empty:
    2175                        rel.append((j,a))
    2176
    2177          return rel
    2178
    2179      # -----------------------------------------------------------------------------
    2180      # compute_lookback_includes()
    2181      #
    2182      # Determines the lookback and includes relations
    2183      #
    2184      # LOOKBACK:
    2185      #
    2186      # This relation is determined by running the LR(0) state machine forward.
    2187      # For example, starting with a production "N : . A B C", we run it forward
    2188      # to obtain "N : A B C ."   We then build a relationship between this final
    2189      # state and the starting state.   These relationships are stored in a dictionary
    2190      # lookdict.
    2191      #
    2192      # INCLUDES:
    2193      #
    2194      # Computes the INCLUDE() relation (p,A) INCLUDES (p',B).
    2195      #
    2196      # This relation is used to determine non-terminal transitions that occur
    2197      # inside of other non-terminal transition states.   (p,A) INCLUDES (p', B)
    2198      # if the following holds:
    2199      #
    2200      #       B -> LAT, where T -> epsilon and p' -L-> p
    2201      #
    2202      # L is essentially a prefix (which may be empty), T is a suffix that must be
    2203      # able to derive an empty string.  State p' must lead to state p with the string L.
    2204      #
    2205      # -----------------------------------------------------------------------------
    2206
    2207 -    def compute_lookback_includes(self,C,trans,nullable):
    2208
    2209          lookdict = {}          # Dictionary of lookback relations
    2210          includedict = {}       # Dictionary of include relations
    2211
    2212          # Make a dictionary of non-terminal transitions
    2213          dtrans = {}
    2214          for t in trans:
    2215              dtrans[t] = 1
    2216
    2217          # Loop over all transitions and compute lookbacks and includes
    2218          for state,N in trans:
    2219              lookb = []
    2220              includes = []
    2221              for p in C[state]:
    2222                  if p.name != N: continue
    2223
    2224                  # Okay, we have a name match.  We now follow the production all the way
    2225                  # through the state machine until we get the . on the right hand side
    2226
    2227                  lr_index = p.lr_index
    2228                  j = state
    2229                  while lr_index < p.len - 1:
    2230                       lr_index = lr_index + 1
    2231                       t = p.prod[lr_index]
    2232
    2233                       # Check to see if this symbol and state are a non-terminal transition
    2234                       if (j,t) in dtrans:
    2235                             # Yes.  Okay, there is some chance that this is an includes relation
    2236                             # the only way to know for certain is whether the rest of the
    2237                             # production derives empty
    2238
    2239                             li = lr_index + 1
    2240                             while li < p.len:
    2241                                  if p.prod[li] in self.grammar.Terminals: break      # No forget it
    2242                                  if not p.prod[li] in nullable: break
    2243                                  li = li + 1
    2244                             else:
    2245                                  # Appears to be a relation between (j,t) and (state,N)
    2246                                  includes.append((j,t))
    2247
    2248                       g = self.lr0_goto(C[j],t)               # Go to next set
    2249                       j = self.lr0_cidhash.get(id(g),-1)     # Go to next state
    2250
    2251                  # When we get here, j is the final state, now we have to locate the production
    2252                  for r in C[j]:
    2253                       if r.name != p.name: continue
    2254                       if r.len != p.len:   continue
    2255                       i = 0
    2256                       # This look is comparing a production ". A B C" with "A B C ."
    2257                       while i < r.lr_index:
    2258                            if r.prod[i] != p.prod[i+1]: break
    2259                            i = i + 1
    2260                       else:
    2261                            lookb.append((j,r))
    2262              for i in includes:
    2263                   if not i in includedict: includedict[i] = []
    2264                   includedict[i].append((state,N))
    2265              lookdict[(state,N)] = lookb
    2266
    2267          return lookdict,includedict
    2268
    2269      # -----------------------------------------------------------------------------
    2270      # compute_read_sets()
    2271      #
    2272      # Given a set of LR(0) items, this function computes the read sets.
    2273      #
    2274      # Inputs:  C        =  Set of LR(0) items
    2275      #          ntrans   = Set of nonterminal transitions
    2276      #          nullable = Set of empty transitions
    2277      #
    2278      # Returns a set containing the read sets
    2279      # -----------------------------------------------------------------------------
    2280
    2281 -    def compute_read_sets(self,C, ntrans, nullable):
    2282          FP = lambda x: self.dr_relation(C,x,nullable)
    2283          R =  lambda x: self.reads_relation(C,x,nullable)
    2284          F = digraph(ntrans,R,FP)
    2285          return F
    2286
    2287      # -----------------------------------------------------------------------------
    2288      # compute_follow_sets()
    2289      #
    2290      # Given a set of LR(0) items, a set of non-terminal transitions, a readset,
    2291      # and an include set, this function computes the follow sets
    2292      #
    2293      # Follow(p,A) = Read(p,A) U U {Follow(p',B) | (p,A) INCLUDES (p',B)}
    2294      #
    2295      # Inputs:
    2296      #            ntrans     = Set of nonterminal transitions
    2297      #            readsets   = Readset (previously computed)
    2298      #            inclsets   = Include sets (previously computed)
    2299      #
    2300      # Returns a set containing the follow sets
    2301      # -----------------------------------------------------------------------------
    2302
    2303 -    def compute_follow_sets(self,ntrans,readsets,inclsets):
    2304           FP = lambda x: readsets[x]
    2305           R  = lambda x: inclsets.get(x,[])
    2306           F = digraph(ntrans,R,FP)
    2307           return F
    2308
    2309      # -----------------------------------------------------------------------------
    2310      # add_lookaheads()
    2311      #
    2312      # Attaches the lookahead symbols to grammar rules.
    2313      #
    2314      # Inputs:    lookbacks         -  Set of lookback relations
    2315      #            followset         -  Computed follow set
    2316      #
    2317      # This function directly attaches the lookaheads to productions contained
    2318      # in the lookbacks set
    2319      # -----------------------------------------------------------------------------
    2320
    2321 -    def add_lookaheads(self,lookbacks,followset):
    2322          for trans,lb in lookbacks.items():
    2323              # Loop over productions in lookback
    2324              for state,p in lb:
    2325                   if not state in p.lookaheads:
    2326                        p.lookaheads[state] = []
    2327                   f = followset.get(trans,[])
    2328                   for a in f:
    2329                        if a not in p.lookaheads[state]: p.lookaheads[state].append(a)
    2330
    2331      # -----------------------------------------------------------------------------
    2332      # add_lalr_lookaheads()
    2333      #
    2334      # This function does all of the work of adding lookahead information for use
    2335      # with LALR parsing
    2336      # -----------------------------------------------------------------------------
    2337
    2338 -    def add_lalr_lookaheads(self,C):
    2339          # Determine all of the nullable nonterminals
    2340          nullable = self.compute_nullable_nonterminals()
    2341
    2342          # Find all non-terminal transitions
    2343          trans = self.find_nonterminal_transitions(C)
    2344
    2345          # Compute read sets
    2346          readsets = self.compute_read_sets(C,trans,nullable)
    2347
    2348          # Compute lookback/includes relations
    2349          lookd, included = self.compute_lookback_includes(C,trans,nullable)
    2350
    2351          # Compute LALR FOLLOW sets
    2352          followsets = self.compute_follow_sets(trans,readsets,included)
    2353
    2354          # Add all of the lookaheads
    2355          self.add_lookaheads(lookd,followsets)
    2356
    2357      # -----------------------------------------------------------------------------
    2358      # lr_parse_table()
    2359      #
    2360      # This function constructs the parse tables for SLR or LALR
    2361      # -----------------------------------------------------------------------------
    2362 -    def lr_parse_table(self):
    2363          Productions = self.grammar.Productions
    2364          Precedence  = self.grammar.Precedence
    2365          goto   = self.lr_goto         # Goto array
    2366          action = self.lr_action       # Action array
    2367          log    = self.log             # Logger for output
    2368
    2369          actionp = { }                 # Action production array (temporary)
    2370
    2371          log.info("Parsing method: %s", self.lr_method)
    2372
    2373          # Step 1: Construct C = { I0, I1, ... IN}, collection of LR(0) items
    2374          # This determines the number of states
    2375
    2376          C = self.lr0_items()
    2377
    2378          if self.lr_method == 'LALR':
    2379              self.add_lalr_lookaheads(C)
    2380
    2381          # Build the parser table, state by state
    2382          st = 0
    2383          for I in C:
    2384              # Loop over each production in I
    2385              actlist = [ ]              # List of actions
    2386              st_action  = { }
    2387              st_actionp = { }
    2388              st_goto    = { }
    2389              log.info("")
    2390              log.info("state %d", st)
    2391              log.info("")
    2392              for p in I:
    2393                  log.info("    (%d) %s", p.number, str(p))
    2394              log.info("")
    2395
    2396              for p in I:
    2397                      if p.len == p.lr_index + 1:
    2398                          if p.name == "S'":
    2399                              # Start symbol. Accept!
    2400                              st_action["$end"] = 0
    2401                              st_actionp["$end"] = p
    2402                          else:
    2403                              # We are at the end of a production.  Reduce!
    2404                              if self.lr_method == 'LALR':
    2405                                  laheads = p.lookaheads[st]
    2406                              else:
    2407                                  laheads = self.grammar.Follow[p.name]
    2408                              for a in laheads:
    2409                                  actlist.append((a,p,"reduce using rule %d (%s)" % (p.number,p)))
    2410                                  r = st_action.get(a,None)
    2411                                  if r is not None:
    2412                                      # Whoa. Have a shift/reduce or reduce/reduce conflict
    2413                                      if r > 0:
    2414                                          # Need to decide on shift or reduce here
    2415                                          # By default we favor shifting. Need to add
    2416                                          # some precedence rules here.
    2417                                          sprec,slevel = Productions[st_actionp[a].number].prec
    2418                                          rprec,rlevel = Precedence.get(a,('right',0))
    2419                                          if (slevel < rlevel) or ((slevel == rlevel) and (rprec == 'left')):
    2420                                              # We really need to reduce here.
    2421                                              st_action[a] = -p.number
    2422                                              st_actionp[a] = p
    2423                                              if not slevel and not rlevel:
    2424                                                  log.info("  ! shift/reduce conflict for %s resolved as reduce",a)
    2425                                                  self.sr_conflicts.append((st,a,'reduce'))
    2426                                              Productions[p.number].reduced += 1
    2427                                          elif (slevel == rlevel) and (rprec == 'nonassoc'):
    2428                                              st_action[a] = None
    2429                                          else:
    2430                                              # Hmmm. Guess we'll keep the shift
    2431                                              if not rlevel:
    2432                                                  log.info("  ! shift/reduce conflict for %s resolved as shift",a)
    2433                                                  self.sr_conflicts.append((st,a,'shift'))
    2434                                      elif r < 0:
    2435                                          # Reduce/reduce conflict.   In this case, we favor the rule
    2436                                          # that was defined first in the grammar file
    2437                                          oldp = Productions[-r]
    2438                                          pp = Productions[p.number]
    2439                                          if oldp.line > pp.line:
    2440                                              st_action[a] = -p.number
    2441                                              st_actionp[a] = p
    2442                                              chosenp,rejectp = pp,oldp
    2443                                              Productions[p.number].reduced += 1
    2444                                              Productions[oldp.number].reduced -= 1
    2445                                          else:
    2446                                              chosenp,rejectp = oldp,pp
    2447                                          self.rr_conflicts.append((st,chosenp,rejectp))
    2448                                          log.info("  ! reduce/reduce conflict for %s resolved using rule %d (%s)", a,st_actionp[a].number, st_actionp[a])
    2449                                      else:
    2450                                          raise LALRError("Unknown conflict in state %d" % st)
    2451                                  else:
    2452                                      st_action[a] = -p.number
    2453                                      st_actionp[a] = p
    2454                                      Productions[p.number].reduced += 1
    2455                      else:
    2456                          i = p.lr_index
    2457                          a = p.prod[i+1]       # Get symbol right after the "."
    2458                          if a in self.grammar.Terminals:
    2459                              g = self.lr0_goto(I,a)
    2460                              j = self.lr0_cidhash.get(id(g),-1)
    2461                              if j >= 0:
    2462                                  # We are in a shift state
    2463                                  actlist.append((a,p,"shift and go to state %d" % j))
    2464                                  r = st_action.get(a,None)
    2465                                  if r is not None:
    2466                                      # Whoa have a shift/reduce or shift/shift conflict
    2467                                      if r > 0:
    2468                                          if r != j:
    2469                                              raise LALRError("Shift/shift conflict in state %d" % st)
    2470                                      elif r < 0:
    2471                                          # Do a precedence check.
    2472                                          #   -  if precedence of reduce rule is higher, we reduce.
    2473                                          #   -  if precedence of reduce is same and left assoc, we reduce.
    2474                                          #   -  otherwise we shift
    2475                                          rprec,rlevel = Productions[st_actionp[a].number].prec
    2476                                          sprec,slevel = Precedence.get(a,('right',0))
    2477                                          if (slevel > rlevel) or ((slevel == rlevel) and (rprec == 'right')):
    2478                                              # We decide to shift here... highest precedence to shift
    2479                                              Productions[st_actionp[a].number].reduced -= 1
    2480                                              st_action[a] = j
    2481                                              st_actionp[a] = p
    2482                                              if not rlevel:
    2483                                                  log.info("  ! shift/reduce conflict for %s resolved as shift",a)
    2484                                                  self.sr_conflicts.append((st,a,'shift'))
    2485                                          elif (slevel == rlevel) and (rprec == 'nonassoc'):
    2486                                              st_action[a] = None
    2487                                          else:
    2488                                              # Hmmm. Guess we'll keep the reduce
    2489                                              if not slevel and not rlevel:
    2490                                                  log.info("  ! shift/reduce conflict for %s resolved as reduce",a)
    2491                                                  self.sr_conflicts.append((st,a,'reduce'))
    2492
    2493                                      else:
    2494                                          raise LALRError("Unknown conflict in state %d" % st)
    2495                                  else:
    2496                                      st_action[a] = j
    2497                                      st_actionp[a] = p
    2498
    2499              # Print the actions associated with each terminal
    2500              _actprint = { }
    2501              for a,p,m in actlist:
    2502                  if a in st_action:
    2503                      if p is st_actionp[a]:
    2504                          log.info("    %-15s %s",a,m)
    2505                          _actprint[(a,m)] = 1
    2506              log.info("")
    2507              # Print the actions that were not used. (debugging)
    2508              not_used = 0
    2509              for a,p,m in actlist:
    2510                  if a in st_action:
    2511                      if p is not st_actionp[a]:
    2512                          if not (a,m) in _actprint:
    2513                              log.debug("  ! %-15s [ %s ]",a,m)
    2514                              not_used = 1
    2515                              _actprint[(a,m)] = 1
    2516              if not_used:
    2517                  log.debug("")
    2518
    2519              # Construct the goto table for this state
    2520
    2521              nkeys = { }
    2522              for ii in I:
    2523                  for s in ii.usyms:
    2524                      if s in self.grammar.Nonterminals:
    2525                          nkeys[s] = None
    2526              for n in nkeys:
    2527                  g = self.lr0_goto(I,n)
    2528                  j = self.lr0_cidhash.get(id(g),-1)
    2529                  if j >= 0:
    2530                      st_goto[n] = j
    2531                      log.info("    %-30s shift and go to state %d",n,j)
    2532
    2533              action[st] = st_action
    2534              actionp[st] = st_actionp
    2535              goto[st] = st_goto
    2536              st += 1
    2537
    2538
    2539      # -----------------------------------------------------------------------------
    2540      # write()
    2541      #
    2542      # This function writes the LR parsing tables to a file
    2543      # -----------------------------------------------------------------------------
    2544
    2545 -    def write_table(self,modulename,outputdir='',signature=""):
    2546          basemodulename = modulename.split(".")[-1]
    2547          filename = os.path.join(outputdir,basemodulename) + ".py"
    2548          try:
    2549              f = open(filename,"w")
    2550
    2551              f.write("""
    2552  # %s
    2553  # This file is automatically generated. Do not edit.
    2554  _tabversion = %r
    2555
    2556  _lr_method = %r
    2557
    2558  _lr_signature = %r
    2559      """ % (filename, __tabversion__, self.lr_method, signature))
    2560
    2561              # Change smaller to 0 to go back to original tables
    2562              smaller = 1
    2563
    2564              # Factor out names to try and make smaller
    2565              if smaller:
    2566                  items = { }
    2567
    2568                  for s,nd in self.lr_action.items():
    2569                     for name,v in nd.items():
    2570                        i = items.get(name)
    2571                        if not i:
    2572                           i = ([],[])
    2573                           items[name] = i
    2574                        i[0].append(s)
    2575                        i[1].append(v)
    2576
    2577                  f.write("\n_lr_action_items = {")
    2578                  for k,v in items.items():
    2579                      f.write("%r:([" % k)
    2580                      for i in v[0]:
    2581                          f.write("%r," % i)
    2582                      f.write("],[")
    2583                      for i in v[1]:
    2584                          f.write("%r," % i)
    2585
    2586                      f.write("]),")
    2587                  f.write("}\n")
    2588
    2589                  f.write("""
    2590  _lr_action = { }
    2591  for _k, _v in _lr_action_items.items():
    2592     for _x,_y in zip(_v[0],_v[1]):
    2593        if not _x in _lr_action:  _lr_action[_x] = { }
    2594        _lr_action[_x][_k] = _y
    2595  del _lr_action_items
    2596  """)
    2597
    2598              else:
    2599                  f.write("\n_lr_action = { ");
    2600                  for k,v in self.lr_action.items():
    2601                      f.write("(%r,%r):%r," % (k[0],k[1],v))
    2602                  f.write("}\n");
    2603
    2604              if smaller:
    2605                  # Factor out names to try and make smaller
    2606                  items = { }
    2607
    2608                  for s,nd in self.lr_goto.items():
    2609                     for name,v in nd.items():
    2610                        i = items.get(name)
    2611                        if not i:
    2612                           i = ([],[])
    2613                           items[name] = i
    2614                        i[0].append(s)
    2615                        i[1].append(v)
    2616
    2617                  f.write("\n_lr_goto_items = {")
    2618                  for k,v in items.items():
    2619                      f.write("%r:([" % k)
    2620                      for i in v[0]:
    2621                          f.write("%r," % i)
    2622                      f.write("],[")
    2623                      for i in v[1]:
    2624                          f.write("%r," % i)
    2625
    2626                      f.write("]),")
    2627                  f.write("}\n")
    2628
    2629                  f.write("""
    2630  _lr_goto = { }
    2631  for _k, _v in _lr_goto_items.items():
    2632     for _x,_y in zip(_v[0],_v[1]):
    2633         if not _x in _lr_goto: _lr_goto[_x] = { }
    2634         _lr_goto[_x][_k] = _y
    2635  del _lr_goto_items
    2636  """)
    2637              else:
    2638                  f.write("\n_lr_goto = { ");
    2639                  for k,v in self.lr_goto.items():
    2640                      f.write("(%r,%r):%r," % (k[0],k[1],v))
    2641                  f.write("}\n");
    2642
    2643              # Write production table
    2644              f.write("_lr_productions = [\n")
    2645              for p in self.lr_productions:
    2646                  if p.func:
    2647                      f.write("  (%r,%r,%d,%r,%r,%d),\n" % (p.str,p.name, p.len, p.func,p.file,p.line))
    2648                  else:
    2649                      f.write("  (%r,%r,%d,None,None,None),\n" % (str(p),p.name, p.len))
    2650              f.write("]\n")
    2651              f.close()
    2652
    2653          except IOError:
    2654              e = sys.exc_info()[1]
    2655              sys.stderr.write("Unable to create '%s'\n" % filename)
    2656              sys.stderr.write(str(e)+"\n")
    2657              return
    2658
    2659
    2660      # -----------------------------------------------------------------------------
    2661      # pickle_table()
    2662      #
    2663      # This function pickles the LR parsing tables to a supplied file object
    2664      # -----------------------------------------------------------------------------
    2665
    2666 -    def pickle_table(self,filename,signature=""):
    2667          try:
    2668              import cPickle as pickle
    2669          except ImportError:
    2670              import pickle
    2671          outf = open(filename,"wb")
    2672          pickle.dump(__tabversion__,outf,pickle_protocol)
    2673          pickle.dump(self.lr_method,outf,pickle_protocol)
    2674          pickle.dump(signature,outf,pickle_protocol)
    2675          pickle.dump(self.lr_action,outf,pickle_protocol)
    2676          pickle.dump(self.lr_goto,outf,pickle_protocol)
    2677
    2678          outp = []
    2679          for p in self.lr_productions:
    2680              if p.func:
    2681                  outp.append((p.str,p.name, p.len, p.func,p.file,p.line))
    2682              else:
    2683                  outp.append((str(p),p.name,p.len,None,None,None))
    2684          pickle.dump(outp,outf,pickle_protocol)
    2685          outf.close()
    2686
    2687  # -----------------------------------------------------------------------------
    2688  #                            === INTROSPECTION ===
    2689  #
    2690  # The following functions and classes are used to implement the PLY
    2691  # introspection features followed by the yacc() function itself.
    2692  # -----------------------------------------------------------------------------
    2693
    2694  # -----------------------------------------------------------------------------
    2695  # get_caller_module_dict()
    2696  #
    2697  # This function returns a dictionary containing all of the symbols defined within
    2698  # a caller further down the call stack.  This is used to get the environment
    2699  # associated with the yacc() call if none was provided.
    2700  # -----------------------------------------------------------------------------
    2701
    2702 -def get_caller_module_dict(levels):
    2703      try:
    2704          raise RuntimeError
    2705      except RuntimeError:
    2706          e,b,t = sys.exc_info()
    2707          f = t.tb_frame
    2708          while levels > 0:
    2709              f = f.f_back
    2710              levels -= 1
    2711          ldict = f.f_globals.copy()
    2712          if f.f_globals != f.f_locals:
    2713              ldict.update(f.f_locals)
    2714
    2715          return ldict
    2716
    2717  # -----------------------------------------------------------------------------
    2718  # parse_grammar()
    2719  #
    2720  # This takes a raw grammar rule string and parses it into production data
    2721  # -----------------------------------------------------------------------------
    2722 -def parse_grammar(doc,file,line):
    2723      grammar = []
    2724      # Split the doc string into lines
    2725      pstrings = doc.splitlines()
    2726      lastp = None
    2727      dline = line
    2728      for ps in pstrings:
    2729          dline += 1
    2730          p = ps.split()
    2731          if not p: continue
    2732          try:
    2733              if p[0] == '|':
    2734                  # This is a continuation of a previous rule
    2735                  if not lastp:
    2736                      raise SyntaxError("%s:%d: Misplaced '|'" % (file,dline))
    2737                  prodname = lastp
    2738                  syms = p[1:]
    2739              else:
    2740                  prodname = p[0]
    2741                  lastp = prodname
    2742                  syms   = p[2:]
    2743                  assign = p[1]
    2744                  if assign != ':' and assign != '::=':
    2745                      raise SyntaxError("%s:%d: Syntax error. Expected ':'" % (file,dline))
    2746
    2747              grammar.append((file,dline,prodname,syms))
    2748          except SyntaxError:
    2749              raise
    2750          except Exception:
    2751              raise SyntaxError("%s:%d: Syntax error in rule '%s'" % (file,dline,ps.strip()))
    2752
    2753      return grammar
    2754
    2755  # -----------------------------------------------------------------------------
    2756  # ParserReflect()
    2757  #
    2758  # This class represents information extracted for building a parser including
    2759  # start symbol, error function, tokens, precedence list, action functions,
    2760  # etc.
    2761  # -----------------------------------------------------------------------------
    2762 -class ParserReflect(object):
    2763 -    def __init__(self,pdict,log=None):
    2764          self.pdict      = pdict
    2765          self.start      = None
    2766          self.error_func = None
    2767          self.tokens     = None
    2768          self.files      = {}
    2769          self.grammar    = []
    2770          self.error      = 0
    2771
    2772          if log is None:
    2773              self.log = PlyLogger(sys.stderr)
    2774          else:
    2775              self.log = log
    2776
    2777      # Get all of the basic information
    2778 -    def get_all(self):
    2779          self.get_start()
    2780          self.get_error_func()
    2781          self.get_tokens()
    2782          self.get_precedence()
    2783          self.get_pfunctions()
    2784
    2785      # Validate all of the information
    2786 -    def validate_all(self):
    2787          self.validate_start()
    2788          self.validate_error_func()
    2789          self.validate_tokens()
    2790          self.validate_precedence()
    2791          self.validate_pfunctions()
    2792          self.validate_files()
    2793          return self.error
    2794
    2795      # Compute a signature over the grammar
    2796 -    def signature(self):
    2797          try:
    2798              from hashlib import md5
    2799          except ImportError:
    2800              from md5 import md5
    2801          try:
    2802              sig = md5()
    2803              if self.start:
    2804                  sig.update(self.start.encode('latin-1'))
    2805              if self.prec:
    2806                  sig.update("".join(["".join(p) for p in self.prec]).encode('latin-1'))
    2807              if self.tokens:
    2808                  sig.update(" ".join(self.tokens).encode('latin-1'))
    2809              for f in self.pfuncs:
    2810                  if f[3]:
    2811                      sig.update(f[3].encode('latin-1'))
    2812          except (TypeError,ValueError):
    2813              pass
    2814          return sig.digest()
    2815
    2816      # -----------------------------------------------------------------------------
    2817      # validate_file()
    2818      #
    2819      # This method checks to see if there are duplicated p_rulename() functions
    2820      # in the parser module file.  Without this function, it is really easy for
    2821      # users to make mistakes by cutting and pasting code fragments (and it's a real
    2822      # bugger to try and figure out why the resulting parser doesn't work).  Therefore,
    2823      # we just do a little regular expression pattern matching of def statements
    2824      # to try and detect duplicates.
    2825      # -----------------------------------------------------------------------------
    2826
    2827 -    def validate_files(self):
    2828          # Match def p_funcname(
    2829          fre = re.compile(r'\s*def\s+(p_[a-zA-Z_0-9]*)\(')
    2830
    2831          for filename in self.files.keys():
    2832              base,ext = os.path.splitext(filename)
    2833              if ext != '.py': return 1          # No idea. Assume it's okay.
    2834
    2835              try:
    2836                  f = open(filename)
    2837                  lines = f.readlines()
    2838                  f.close()
    2839              except IOError:
    2840                  continue
    2841
    2842              counthash = { }
    2843              for linen,l in enumerate(lines):
    2844                  linen += 1
    2845                  m = fre.match(l)
    2846                  if m:
    2847                      name = m.group(1)
    2848                      prev = counthash.get(name)
    2849                      if not prev:
    2850                          counthash[name] = linen
    2851                      else:
    2852                          self.log.warning("%s:%d: Function %s redefined. Previously defined on line %d", filename,linen,name,prev)
    2853
    2854      # Get the start symbol
    2855 -    def get_start(self):
    2856          self.start = self.pdict.get('start')
    2857
    2858      # Validate the start symbol
    2859 -    def validate_start(self):
    2860          if self.start is not None:
    2861              if not isinstance(self.start,str):
    2862                  self.log.error("'start' must be a string")
    2863
    2864      # Look for error handler
    2865 -    def get_error_func(self):
    2866          self.error_func = self.pdict.get('p_error')
    2867
    2868      # Validate the error function
    2869 -    def validate_error_func(self):
    2870          if self.error_func:
    2871              if isinstance(self.error_func,types.FunctionType):
    2872                  ismethod = 0
    2873              elif isinstance(self.error_func, types.MethodType):
    2874                  ismethod = 1
    2875              else:
    2876                  self.log.error("'p_error' defined, but is not a function or method")
    2877                  self.error = 1
    2878                  return
    2879
    2880              eline = func_code(self.error_func).co_firstlineno
    2881              efile = func_code(self.error_func).co_filename
    2882              self.files[efile] = 1
    2883
    2884              if (func_code(self.error_func).co_argcount != 1+ismethod):
    2885                  self.log.error("%s:%d: p_error() requires 1 argument",efile,eline)
    2886                  self.error = 1
    2887
    2888      # Get the tokens map
    2889 -    def get_tokens(self):
    2890          tokens = self.pdict.get("tokens",None)
    2891          if not tokens:
    2892              self.log.error("No token list is defined")
    2893              self.error = 1
    2894              return
    2895
    2896          if not isinstance(tokens,(list, tuple)):
    2897              self.log.error("tokens must be a list or tuple")
    2898              self.error = 1
    2899              return
    2900
    2901          if not tokens:
    2902              self.log.error("tokens is empty")
    2903              self.error = 1
    2904              return
    2905
    2906          self.tokens = tokens
    2907
    2908      # Validate the tokens
    2909 -    def validate_tokens(self):
    2910          # Validate the tokens.
    2911          if 'error' in self.tokens:
    2912              self.log.error("Illegal token name 'error'. Is a reserved word")
    2913              self.error = 1
    2914              return
    2915
    2916          terminals = {}
    2917          for n in self.tokens:
    2918              if n in terminals:
    2919                  self.log.warning("Token '%s' multiply defined", n)
    2920              terminals[n] = 1
    2921
    2922      # Get the precedence map (if any)
    2923 -    def get_precedence(self):
    2924          self.prec = self.pdict.get("precedence",None)
    2925
    2926      # Validate and parse the precedence map
    2927 -    def validate_precedence(self):
    2928          preclist = []
    2929          if self.prec:
    2930              if not isinstance(self.prec,(list,tuple)):
    2931                  self.log.error("precedence must be a list or tuple")
    2932                  self.error = 1
    2933                  return
    2934              for level,p in enumerate(self.prec):
    2935                  if not isinstance(p,(list,tuple)):
    2936                      self.log.error("Bad precedence table")
    2937                      self.error = 1
    2938                      return
    2939
    2940                  if len(p) < 2:
    2941                      self.log.error("Malformed precedence entry %s. Must be (assoc, term, ..., term)",p)
    2942                      self.error = 1
    2943                      return
    2944                  assoc = p[0]
    2945                  if not isinstance(assoc,str):
    2946                      self.log.error("precedence associativity must be a string")
    2947                      self.error = 1
    2948                      return
    2949                  for term in p[1:]:
    2950                      if not isinstance(term,str):
    2951                          self.log.error("precedence items must be strings")
    2952                          self.error = 1
    2953                          return
    2954                      preclist.append((term,assoc,level+1))
    2955          self.preclist = preclist
    2956
    2957      # Get all p_functions from the grammar
    2958 -    def get_pfunctions(self):
    2959          p_functions = []
    2960          for name, item in self.pdict.items():
    2961              if name[:2] != 'p_': continue
    2962              if name == 'p_error': continue
    2963              if isinstance(item,(types.FunctionType,types.MethodType)):
    2964                  line = func_code(item).co_firstlineno
    2965                  file = func_code(item).co_filename
    2966                  p_functions.append((line,file,name,item.__doc__))
    2967
    2968          # Sort all of the actions by line number
    2969          p_functions.sort()
    2970          self.pfuncs = p_functions
    2971
    2972
    2973      # Validate all of the p_functions
    2974 -    def validate_pfunctions(self):
    2975          grammar = []
    2976          # Check for non-empty symbols
    2977          if len(self.pfuncs) == 0:
    2978              self.log.error("no rules of the form p_rulename are defined")
    2979              self.error = 1
    2980              return
    2981
    2982          for line, file, name, doc in self.pfuncs:
    2983              func = self.pdict[name]
    2984              if isinstance(func, types.MethodType):
    2985                  reqargs = 2
    2986              else:
    2987                  reqargs = 1
    2988              if func_code(func).co_argcount > reqargs:
    2989                  self.log.error("%s:%d: Rule '%s' has too many arguments",file,line,func.__name__)
    2990                  self.error = 1
    2991              elif func_code(func).co_argcount < reqargs:
    2992                  self.log.error("%s:%d: Rule '%s' requires an argument",file,line,func.__name__)
    2993                  self.error = 1
    2994              elif not func.__doc__:
    2995                  self.log.warning("%s:%d: No documentation string specified in function '%s' (ignored)",file,line,func.__name__)
    2996              else:
    2997                  try:
    2998                      parsed_g = parse_grammar(doc,file,line)
    2999                      for g in parsed_g:
    3000                          grammar.append((name, g))
    3001                  except SyntaxError:
    3002                      e = sys.exc_info()[1]
    3003                      self.log.error(str(e))
    3004                      self.error = 1
    3005
    3006                  # Looks like a valid grammar rule
    3007                  # Mark the file in which defined.
    3008                  self.files[file] = 1
    3009
    3010          # Secondary validation step that looks for p_ definitions that are not functions
    3011          # or functions that look like they might be grammar rules.
    3012
    3013          for n,v in self.pdict.items():
    3014              if n[0:2] == 'p_' and isinstance(v, (types.FunctionType, types.MethodType)): continue
    3015              if n[0:2] == 't_': continue
    3016              if n[0:2] == 'p_' and n != 'p_error':
    3017                  self.log.warning("'%s' not defined as a function", n)
    3018              if ((isinstance(v,types.FunctionType) and func_code(v).co_argcount == 1) or
    3019                  (isinstance(v,types.MethodType) and func_code(v).co_argcount == 2)):
    3020                  try:
    3021                      doc = v.__doc__.split(" ")
    3022                      if doc[1] == ':':
    3023                          self.log.warning("%s:%d: Possible grammar rule '%s' defined without p_ prefix",
    3024                                           func_code(v).co_filename, func_code(v).co_firstlineno,n)
    3025                  except Exception:
    3026                      pass
    3027
    3028          self.grammar = grammar
    3029
    3030  # -----------------------------------------------------------------------------
    3031  # yacc(module)
    3032  #
    3033  # Build a parser
    3034  # -----------------------------------------------------------------------------
    3035
    3036 -def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, start=None,
    3037           check_recursion=1, optimize=0, write_tables=1, debugfile=debug_file,outputdir='',
    3038           debuglog=None, errorlog = None, picklefile=None):
    3039
    3040      global parse                 # Reference to the parsing method of the last built parser
    3041
    3042      # If pickling is enabled, table files are not created
    3043
    3044      if picklefile:
    3045          write_tables = 0
    3046
    3047      if errorlog is None:
    3048          errorlog = PlyLogger(sys.stderr)
    3049
    3050      # Get the module dictionary used for the parser
    3051      if module:
    3052          _items = [(k,getattr(module,k)) for k in dir(module)]
    3053          pdict = dict(_items)
    3054      else:
    3055          pdict = get_caller_module_dict(2)
    3056
    3057      # Collect parser information from the dictionary
    3058      pinfo = ParserReflect(pdict,log=errorlog)
    3059      pinfo.get_all()
    3060
    3061      if pinfo.error:
    3062          raise YaccError("Unable to build parser")
    3063
    3064      # Check signature against table files (if any)
    3065      signature = pinfo.signature()
    3066
    3067      # Read the tables
    3068      try:
    3069          lr = LRTable()
    3070          if picklefile:
    3071              read_signature = lr.read_pickle(picklefile)
    3072          else:
    3073              read_signature = lr.read_table(tabmodule)
    3074          if optimize or (read_signature == signature):
    3075              try:
    3076                  lr.bind_callables(pinfo.pdict)
    3077                  parser = LRParser(lr,pinfo.error_func)
    3078                  parse = parser.parse
    3079                  return parser
    3080              except Exception:
    3081                  e = sys.exc_info()[1]
    3082                  errorlog.warning("There was a problem loading the table file: %s", repr(e))
    3083      except VersionError:
    3084          e = sys.exc_info()
    3085          errorlog.warning(str(e))
    3086      except Exception:
    3087          pass
    3088
    3089      if debuglog is None:
    3090          if debug:
    3091              debuglog = PlyLogger(open(debugfile,"w"))
    3092          else:
    3093              debuglog = NullLogger()
    3094
    3095      debuglog.info("Created by PLY version %s (http://www.dabeaz.com/ply)", __version__)
    3096
    3097
    3098      errors = 0
    3099
    3100      # Validate the parser information
    3101      if pinfo.validate_all():
    3102          raise YaccError("Unable to build parser")
    3103
    3104      if not pinfo.error_func:
    3105          errorlog.warning("no p_error() function is defined")
    3106
    3107      # Create a grammar object
    3108      grammar = Grammar(pinfo.tokens)
    3109
    3110      # Set precedence level for terminals
    3111      for term, assoc, level in pinfo.preclist:
    3112          try:
    3113              grammar.set_precedence(term,assoc,level)
    3114          except GrammarError:
    3115              e = sys.exc_info()[1]
    3116              errorlog.warning("%s",str(e))
    3117
    3118      # Add productions to the grammar
    3119      for funcname, gram in pinfo.grammar:
    3120          file, line, prodname, syms = gram
    3121          try:
    3122              grammar.add_production(prodname,syms,funcname,file,line)
    3123          except GrammarError:
    3124              e = sys.exc_info()[1]
    3125              errorlog.error("%s",str(e))
    3126              errors = 1
    3127
    3128      # Set the grammar start symbols
    3129      try:
    3130          if start is None:
    3131              grammar.set_start(pinfo.start)
    3132          else:
    3133              grammar.set_start(start)
    3134      except GrammarError:
    3135          e = sys.exc_info()[1]
    3136          errorlog.error(str(e))
    3137          errors = 1
    3138
    3139      if errors:
    3140          raise YaccError("Unable to build parser")
    3141
    3142      # Verify the grammar structure
    3143      undefined_symbols = grammar.undefined_symbols()
    3144      for sym, prod in undefined_symbols:
    3145          errorlog.error("%s:%d: Symbol '%s' used, but not defined as a token or a rule",prod.file,prod.line,sym)
    3146          errors = 1
    3147
    3148      unused_terminals = grammar.unused_terminals()
    3149      if unused_terminals:
    3150          debuglog.info("")
    3151          debuglog.info("Unused terminals:")
    3152          debuglog.info("")
    3153          for term in unused_terminals:
    3154              errorlog.warning("Token '%s' defined, but not used", term)
    3155              debuglog.info("    %s", term)
    3156
    3157      # Print out all productions to the debug log
    3158      if debug:
    3159          debuglog.info("")
    3160          debuglog.info("Grammar")
    3161          debuglog.info("")
    3162          for n,p in enumerate(grammar.Productions):
    3163              debuglog.info("Rule %-5d %s", n, p)
    3164
    3165      # Find unused non-terminals
    3166      unused_rules = grammar.unused_rules()
    3167      for prod in unused_rules:
    3168          errorlog.warning("%s:%d: Rule '%s' defined, but not used", prod.file, prod.line, prod.name)
    3169
    3170      if len(unused_terminals) == 1:
    3171          errorlog.warning("There is 1 unused token")
    3172      if len(unused_terminals) > 1:
    3173          errorlog.warning("There are %d unused tokens", len(unused_terminals))
    3174
    3175      if len(unused_rules) == 1:
    3176          errorlog.warning("There is 1 unused rule")
    3177      if len(unused_rules) > 1:
    3178          errorlog.warning("There are %d unused rules", len(unused_rules))
    3179
    3180      if debug:
    3181          debuglog.info("")
    3182          debuglog.info("Terminals, with rules where they appear")
    3183          debuglog.info("")
    3184          terms = list(grammar.Terminals)
    3185          terms.sort()
    3186          for term in terms:
    3187              debuglog.info("%-20s : %s", term, " ".join([str(s) for s in grammar.Terminals[term]]))
    3188
    3189          debuglog.info("")
    3190          debuglog.info("Nonterminals, with rules where they appear")
    3191          debuglog.info("")
    3192          nonterms = list(grammar.Nonterminals)
    3193          nonterms.sort()
    3194          for nonterm in nonterms:
    3195              debuglog.info("%-20s : %s", nonterm, " ".join([str(s) for s in grammar.Nonterminals[nonterm]]))
    3196          debuglog.info("")
    3197
    3198      if check_recursion:
    3199          unreachable = grammar.find_unreachable()
    3200          for u in unreachable:
    3201              errorlog.warning("Symbol '%s' is unreachable",u)
    3202
    3203          infinite = grammar.infinite_cycles()
    3204          for inf in infinite:
    3205              errorlog.error("Infinite recursion detected for symbol '%s'", inf)
    3206              errors = 1
    3207
    3208      unused_prec = grammar.unused_precedence()
    3209      for term, assoc in unused_prec:
    3210          errorlog.error("Precedence rule '%s' defined for unknown symbol '%s'", assoc, term)
    3211          errors = 1
    3212
    3213      if errors:
    3214          raise YaccError("Unable to build parser")
    3215
    3216      # Run the LRGeneratedTable on the grammar
    3217      if debug:
    3218          errorlog.debug("Generating %s tables", method)
    3219
    3220      lr = LRGeneratedTable(grammar,method,debuglog)
    3221
    3222      if debug:
    3223          num_sr = len(lr.sr_conflicts)
    3224
    3225          # Report shift/reduce and reduce/reduce conflicts
    3226          if num_sr == 1:
    3227              errorlog.warning("1 shift/reduce conflict")
    3228          elif num_sr > 1:
    3229              errorlog.warning("%d shift/reduce conflicts", num_sr)
    3230
    3231          num_rr = len(lr.rr_conflicts)
    3232          if num_rr == 1:
    3233              errorlog.warning("1 reduce/reduce conflict")
    3234          elif num_rr > 1:
    3235              errorlog.warning("%d reduce/reduce conflicts", num_rr)
    3236
    3237      # Write out conflicts to the output file
    3238      if debug and (lr.sr_conflicts or lr.rr_conflicts):
    3239          debuglog.warning("")
    3240          debuglog.warning("Conflicts:")
    3241          debuglog.warning("")
    3242
    3243          for state, tok, resolution in lr.sr_conflicts:
    3244              debuglog.warning("shift/reduce conflict for %s in state %d resolved as %s",  tok, state, resolution)
    3245
    3246          already_reported = {}
    3247          for state, rule, rejected in lr.rr_conflicts:
    3248              if (state,id(rule),id(rejected)) in already_reported:
    3249                  continue
    3250              debuglog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule)
    3251              debuglog.warning("rejected rule (%s) in state %d", rejected,state)
    3252              errorlog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule)
    3253              errorlog.warning("rejected rule (%s) in state %d", rejected, state)
    3254              already_reported[state,id(rule),id(rejected)] = 1
    3255
    3256          warned_never = []
    3257          for state, rule, rejected in lr.rr_conflicts:
    3258              if not rejected.reduced and (rejected not in warned_never):
    3259                  debuglog.warning("Rule (%s) is never reduced", rejected)
    3260                  errorlog.warning("Rule (%s) is never reduced", rejected)
    3261                  warned_never.append(rejected)
    3262
    3263      # Write the table file if requested
    3264      if write_tables:
    3265          lr.write_table(tabmodule,outputdir,signature)
    3266
    3267      # Write a pickled version of the tables
    3268      if picklefile:
    3269          lr.pickle_table(picklefile,signature)
    3270
    3271      # Build the parser
    3272      lr.bind_callables(pinfo.pdict)
    3273      parser = LRParser(lr,pinfo.error_func)
    3274
    3275      parse = parser.parse
    3276      return parser
    3277