1#-----------------------------------------------------------------------------
2# ply: yacc.py
3#
4# Author(s): David M. Beazley (dave@dabeaz.com)
5#
6# Copyright (C) 2001-2006, David M. Beazley
7#
8# This library is free software; you can redistribute it and/or
9# modify it under the terms of the GNU Lesser General Public
10# License as published by the Free Software Foundation; either
11# version 2.1 of the License, or (at your option) any later version.
12#
13# This library is distributed in the hope that it will be useful,
14# but WITHOUT ANY WARRANTY; without even the implied warranty of
15# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16# Lesser General Public License for more details.
17#
18# You should have received a copy of the GNU Lesser General Public
19# License along with this library; if not, write to the Free Software
20# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
21#
22# See the file COPYING for a complete copy of the LGPL.
23#
24#
25# This implements an LR parser that is constructed from grammar rules defined
26# as Python functions. The grammer is specified by supplying the BNF inside
27# Python documentation strings.  The inspiration for this technique was borrowed
28# from John Aycock's Spark parsing system.  PLY might be viewed as cross between
29# Spark and the GNU bison utility.
30#
31# The current implementation is only somewhat object-oriented. The
32# LR parser itself is defined in terms of an object (which allows multiple
33# parsers to co-exist).  However, most of the variables used during table
34# construction are defined in terms of global variables.  Users shouldn't
35# notice unless they are trying to define multiple parsers at the same
36# time using threads (in which case they should have their head examined).
37#
38# This implementation supports both SLR and LALR(1) parsing.  LALR(1)
39# support was originally implemented by Elias Ioup (ezioup@alumni.uchicago.edu),
40# using the algorithm found in Aho, Sethi, and Ullman "Compilers: Principles,
41# Techniques, and Tools" (The Dragon Book).  LALR(1) has since been replaced
42# by the more efficient DeRemer and Pennello algorithm.
43#
44# :::::::: WARNING :::::::
45#
46# Construction of LR parsing tables is fairly complicated and expensive.
47# To make this module run fast, a *LOT* of work has been put into
48# optimization---often at the expensive of readability and what might
49# consider to be good Python "coding style."   Modify the code at your
50# own risk!
51# ----------------------------------------------------------------------------
52
53__version__ = "2.2"
54
55#-----------------------------------------------------------------------------
56#                     === User configurable parameters ===
57#
58# Change these to modify the default behavior of yacc (if you wish)
59#-----------------------------------------------------------------------------
60
61yaccdebug   = 1                # Debugging mode.  If set, yacc generates a
62                               # a 'parser.out' file in the current directory
63
64debug_file  = 'parser.out'     # Default name of the debugging file
65tab_module  = 'parsetab'       # Default name of the table module
66default_lr  = 'LALR'           # Default LR table generation method
67
68error_count = 3                # Number of symbols that must be shifted to leave recovery mode
69
70import re, types, sys, hashlib, os.path
71try:
72    from cStringIO import StringIO
73except ImportError:
74    from io import StringIO
75
76from . import util
77
78# Exception raised for yacc-related errors
79class YaccError(Exception):   pass
80
81#-----------------------------------------------------------------------------
82#                        ===  LR Parsing Engine ===
83#
84# The following classes are used for the LR parser itself.  These are not
85# used during table construction and are independent of the actual LR
86# table generation algorithm
87#-----------------------------------------------------------------------------
88
89# This class is used to hold non-terminal grammar symbols during parsing.
90# It normally has the following attributes set:
91#        .type       = Grammar symbol type
92#        .value      = Symbol value
93#        .lineno     = Starting line number
94#        .endlineno  = Ending line number (optional, set automatically)
95#        .lexpos     = Starting lex position
96#        .endlexpos  = Ending lex position (optional, set automatically)
97
98class YaccSymbol:
99    def __str__(self):    return self.type
100    def __repr__(self):   return str(self)
101
102# This class is a wrapper around the objects actually passed to each
103# grammar rule.   Index lookup and assignment actually assign the
104# .value attribute of the underlying YaccSymbol object.
105# The lineno() method returns the line number of a given
106# item (or 0 if not defined).   The linespan() method returns
107# a tuple of (startline,endline) representing the range of lines
108# for a symbol.  The lexspan() method returns a tuple (lexpos,endlexpos)
109# representing the range of positional information for a symbol.
110
111class YaccProduction:
112    def __init__(self,s,stack=None):
113        self.slice = s
114        self.pbstack = []
115        self.stack = stack
116
117    def __getitem__(self,n):
118        if type(n) == int:
119             if n >= 0: return self.slice[n].value
120             else: return self.stack[n].value
121        else:
122             return [s.value for s in self.slice[n.start:n.stop:n.step]]
123
124    def __setitem__(self,n,v):
125        self.slice[n].value = v
126
127    def __len__(self):
128        return len(self.slice)
129
130    def lineno(self,n):
131        return getattr(self.slice[n],"lineno",0)
132
133    def linespan(self,n):
134        startline = getattr(self.slice[n],"lineno",0)
135        endline = getattr(self.slice[n],"endlineno",startline)
136        return startline,endline
137
138    def lexpos(self,n):
139        return getattr(self.slice[n],"lexpos",0)
140
141    def lexspan(self,n):
142        startpos = getattr(self.slice[n],"lexpos",0)
143        endpos = getattr(self.slice[n],"endlexpos",startpos)
144        return startpos,endpos
145
146    def pushback(self,n):
147        if n <= 0:
148            raise ValueError("Expected a positive value")
149        if n > (len(self.slice)-1):
150            raise ValueError("Can't push %d tokens. Only %d are available." % (n,len(self.slice)-1))
151        for i in range(0,n):
152            self.pbstack.append(self.slice[-i-1])
153
154# The LR Parsing engine.   This is defined as a class so that multiple parsers
155# can exist in the same process.  A user never instantiates this directly.
156# Instead, the global yacc() function should be used to create a suitable Parser
157# object.
158
159class Parser:
160    def __init__(self,magic=None):
161
162        # This is a hack to keep users from trying to instantiate a Parser
163        # object directly.
164
165        if magic != "xyzzy":
166            raise YaccError("Can't instantiate Parser. Use yacc() instead.")
167
168        # Reset internal state
169        self.productions = None          # List of productions
170        self.errorfunc   = None          # Error handling function
171        self.action      = { }           # LR Action table
172        self.goto        = { }           # LR goto table
173        self.require     = { }           # Attribute require table
174        self.method      = "Unknown LR"  # Table construction method used
175
176    def errok(self):
177        self.errorcount = 0
178
179    def restart(self):
180        del self.statestack[:]
181        del self.symstack[:]
182        sym = YaccSymbol()
183        sym.type = '$end'
184        self.symstack.append(sym)
185        self.statestack.append(0)
186
187    def parse(self,input=None,lexer=None,debug=0):
188        lookahead = None                 # Current lookahead symbol
189        lookaheadstack = [ ]             # Stack of lookahead symbols
190        actions = self.action            # Local reference to action table
191        goto    = self.goto              # Local reference to goto table
192        prod    = self.productions       # Local reference to production list
193        pslice  = YaccProduction(None)   # Production object passed to grammar rules
194        pslice.parser = self             # Parser object
195        self.errorcount = 0              # Used during error recovery
196
197        # If no lexer was given, we will try to use the lex module
198        if not lexer:
199            from . import lex
200            lexer = lex.lexer
201
202        pslice.lexer = lexer
203
204        # If input was supplied, pass to lexer
205        if input:
206            lexer.input(input)
207
208        # Tokenize function
209        get_token = lexer.token
210
211        statestack = [ ]                # Stack of parsing states
212        self.statestack = statestack
213        symstack   = [ ]                # Stack of grammar symbols
214        self.symstack = symstack
215
216        pslice.stack = symstack         # Put in the production
217        errtoken   = None               # Err token
218
219        # The start state is assumed to be (0,$end)
220        statestack.append(0)
221        sym = YaccSymbol()
222        sym.type = '$end'
223        symstack.append(sym)
224
225        while 1:
226            # Get the next symbol on the input.  If a lookahead symbol
227            # is already set, we just use that. Otherwise, we'll pull
228            # the next token off of the lookaheadstack or from the lexer
229            if debug > 1:
230                print('state', statestack[-1])
231            if not lookahead:
232                if not lookaheadstack:
233                    lookahead = get_token()     # Get the next token
234                else:
235                    lookahead = lookaheadstack.pop()
236                if not lookahead:
237                    lookahead = YaccSymbol()
238                    lookahead.type = '$end'
239            if debug:
240                errorlead = ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip()
241
242            # Check the action table
243            s = statestack[-1]
244            ltype = lookahead.type
245            t = actions.get((s,ltype),None)
246
247            if debug > 1:
248                print('action', t)
249            if t is not None:
250                if t > 0:
251                    # shift a symbol on the stack
252                    if ltype == '$end':
253                        # Error, end of input
254                        sys.stderr.write("yacc: Parse error. EOF\n")
255                        return
256                    statestack.append(t)
257                    if debug > 1:
258                        sys.stderr.write("%-60s shift state %s\n" % (errorlead, t))
259                    symstack.append(lookahead)
260                    lookahead = None
261
262                    # Decrease error count on successful shift
263                    if self.errorcount > 0:
264                        self.errorcount -= 1
265
266                    continue
267
268                if t < 0:
269                    # reduce a symbol on the stack, emit a production
270                    p = prod[-t]
271                    pname = p.name
272                    plen  = p.len
273
274                    # Get production function
275                    sym = YaccSymbol()
276                    sym.type = pname       # Production name
277                    sym.value = None
278                    if debug > 1:
279                        sys.stderr.write("%-60s reduce %d\n" % (errorlead, -t))
280
281                    if plen:
282                        targ = symstack[-plen-1:]
283                        targ[0] = sym
284                        try:
285                            sym.lineno = targ[1].lineno
286                            sym.endlineno = getattr(targ[-1],"endlineno",targ[-1].lineno)
287                            sym.lexpos = targ[1].lexpos
288                            sym.endlexpos = getattr(targ[-1],"endlexpos",targ[-1].lexpos)
289                        except AttributeError:
290                            sym.lineno = 0
291                        del symstack[-plen:]
292                        del statestack[-plen:]
293                    else:
294                        sym.lineno = 0
295                        targ = [ sym ]
296                    pslice.slice = targ
297                    pslice.pbstack = []
298                    # Call the grammar rule with our special slice object
299                    p.func(pslice)
300
301                    # If there was a pushback, put that on the stack
302                    if pslice.pbstack:
303                        lookaheadstack.append(lookahead)
304                        for _t in pslice.pbstack:
305                            lookaheadstack.append(_t)
306                        lookahead = None
307
308                    symstack.append(sym)
309                    statestack.append(goto[statestack[-1],pname])
310                    continue
311
312                if t == 0:
313                    n = symstack[-1]
314                    return getattr(n,"value",None)
315                    sys.stderr.write(errorlead, "\n")
316
317            if t == None:
318                if debug:
319                    sys.stderr.write(errorlead + "\n")
320                # We have some kind of parsing error here.  To handle
321                # this, we are going to push the current token onto
322                # the tokenstack and replace it with an 'error' token.
323                # If there are any synchronization rules, they may
324                # catch it.
325                #
326                # In addition to pushing the error token, we call call
327                # the user defined p_error() function if this is the
328                # first syntax error.  This function is only called if
329                # errorcount == 0.
330                if not self.errorcount:
331                    self.errorcount = error_count
332                    errtoken = lookahead
333                    if errtoken.type == '$end':
334                        errtoken = None               # End of file!
335                    if self.errorfunc:
336                        global errok,token,restart
337                        errok = self.errok        # Set some special functions available in error recovery
338                        token = get_token
339                        restart = self.restart
340                        tok = self.errorfunc(errtoken)
341                        del errok, token, restart   # Delete special functions
342
343                        if not self.errorcount:
344                            # User must have done some kind of panic
345                            # mode recovery on their own.  The
346                            # returned token is the next lookahead
347                            lookahead = tok
348                            errtoken = None
349                            continue
350                    else:
351                        if errtoken:
352                            if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
353                            else: lineno = 0
354                            if lineno:
355                                sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
356                            else:
357                                sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
358                        else:
359                            sys.stderr.write("yacc: Parse error in input. EOF\n")
360                            return
361
362                else:
363                    self.errorcount = error_count
364
365                # case 1:  the statestack only has 1 entry on it.  If we're in this state, the
366                # entire parse has been rolled back and we're completely hosed.   The token is
367                # discarded and we just keep going.
368
369                if len(statestack) <= 1 and lookahead.type != '$end':
370                    lookahead = None
371                    errtoken = None
372                    # Nuke the pushback stack
373                    del lookaheadstack[:]
374                    continue
375
376                # case 2: the statestack has a couple of entries on it, but we're
377                # at the end of the file. nuke the top entry and generate an error token
378
379                # Start nuking entries on the stack
380                if lookahead.type == '$end':
381                    # Whoa. We're really hosed here. Bail out
382                    return
383
384                if lookahead.type != 'error':
385                    sym = symstack[-1]
386                    if sym.type == 'error':
387                        # Hmmm. Error is on top of stack, we'll just nuke input
388                        # symbol and continue
389                        lookahead = None
390                        continue
391                    t = YaccSymbol()
392                    t.type = 'error'
393                    if hasattr(lookahead,"lineno"):
394                        t.lineno = lookahead.lineno
395                    t.value = lookahead
396                    lookaheadstack.append(lookahead)
397                    lookahead = t
398                else:
399                    symstack.pop()
400                    statestack.pop()
401
402                continue
403
404            # Call an error function here
405            raise RuntimeError("yacc: internal parser error!!!\n")
406
407# -----------------------------------------------------------------------------
408#                          === Parser Construction ===
409#
410# The following functions and variables are used to implement the yacc() function
411# itself.   This is pretty hairy stuff involving lots of error checking,
412# construction of LR items, kernels, and so forth.   Although a lot of
413# this work is done using global variables, the resulting Parser object
414# is completely self contained--meaning that it is safe to repeatedly
415# call yacc() with different grammars in the same application.
416# -----------------------------------------------------------------------------
417
418# -----------------------------------------------------------------------------
419# validate_file()
420#
421# This function checks to see if there are duplicated p_rulename() functions
422# in the parser module file.  Without this function, it is really easy for
423# users to make mistakes by cutting and pasting code fragments (and it's a real
424# bugger to try and figure out why the resulting parser doesn't work).  Therefore,
425# we just do a little regular expression pattern matching of def statements
426# to try and detect duplicates.
427# -----------------------------------------------------------------------------
428
429def validate_file(filename):
430    base,ext = os.path.splitext(filename)
431    if ext != '.py': return 1          # No idea. Assume it's okay.
432
433    try:
434        f = open(filename)
435        lines = f.readlines()
436        f.close()
437    except IOError:
438        return 1                       # Oh well
439
440    # Match def p_funcname(
441    fre = re.compile(r'\s*def\s+(p_[a-zA-Z_0-9]*)\(')
442    counthash = { }
443    linen = 1
444    noerror = 1
445    for l in lines:
446        m = fre.match(l)
447        if m:
448            name = m.group(1)
449            prev = counthash.get(name)
450            if not prev:
451                counthash[name] = linen
452            else:
453                sys.stderr.write("%s:%d: Function %s redefined. Previously defined on line %d\n" % (filename,linen,name,prev))
454                noerror = 0
455        linen += 1
456    return noerror
457
458# This function looks for functions that might be grammar rules, but which don't have the proper p_suffix.
459def validate_dict(d):
460    for n,v in d.items():
461        if n[0:2] == 'p_' and type(v) in (types.FunctionType, types.MethodType): continue
462        if n[0:2] == 't_': continue
463
464        if n[0:2] == 'p_':
465            sys.stderr.write("yacc: Warning. '%s' not defined as a function\n" % n)
466        if 1 and isinstance(v,types.FunctionType) and v.__code__.co_argcount == 1:
467            try:
468                doc = v.__doc__.split(" ")
469                if doc[1] == ':':
470                    sys.stderr.write("%s:%d: Warning. Possible grammar rule '%s' defined without p_ prefix.\n" % (v.__code__.co_filename, v.__code__.co_firstlineno,n))
471            except Exception:
472                pass
473
474# -----------------------------------------------------------------------------
475#                           === GRAMMAR FUNCTIONS ===
476#
477# The following global variables and functions are used to store, manipulate,
478# and verify the grammar rules specified by the user.
479# -----------------------------------------------------------------------------
480
481# Initialize all of the global variables used during grammar construction
482def initialize_vars():
483    global Productions, Prodnames, Prodmap, Terminals
484    global Nonterminals, First, Follow, Precedence, LRitems
485    global Errorfunc, Signature, Requires
486
487    Productions  = [None]  # A list of all of the productions.  The first
488                           # entry is always reserved for the purpose of
489                           # building an augmented grammar
490
491    Prodnames    = { }     # A dictionary mapping the names of nonterminals to a list of all
492                           # productions of that nonterminal.
493
494    Prodmap      = { }     # A dictionary that is only used to detect duplicate
495                           # productions.
496
497    Terminals    = { }     # A dictionary mapping the names of terminal symbols to a
498                           # list of the rules where they are used.
499
500    Nonterminals = { }     # A dictionary mapping names of nonterminals to a list
501                           # of rule numbers where they are used.
502
503    First        = { }     # A dictionary of precomputed FIRST(x) symbols
504
505    Follow       = { }     # A dictionary of precomputed FOLLOW(x) symbols
506
507    Precedence   = { }     # Precedence rules for each terminal. Contains tuples of the
508                           # form ('right',level) or ('nonassoc', level) or ('left',level)
509
510    LRitems      = [ ]     # A list of all LR items for the grammar.  These are the
511                           # productions with the "dot" like E -> E . PLUS E
512
513    Errorfunc    = None    # User defined error handler
514
515    Signature    = hashlib.sha256()   # Digital signature of the grammar rules, precedence
516                               # and other information.  Used to determined when a
517                               # parsing table needs to be regenerated.
518
519    Requires     = { }     # Requires list
520
521    # File objects used when creating the parser.out debugging file
522    global _vf, _vfc
523    _vf           = StringIO()
524    _vfc          = StringIO()
525
526# -----------------------------------------------------------------------------
527# class Production:
528#
529# This class stores the raw information about a single production or grammar rule.
530# It has a few required attributes:
531#
532#       name     - Name of the production (nonterminal)
533#       prod     - A list of symbols making up its production
534#       number   - Production number.
535#
536# In addition, a few additional attributes are used to help with debugging or
537# optimization of table generation.
538#
539#       file     - File where production action is defined.
540#       lineno   - Line number where action is defined
541#       func     - Action function
542#       prec     - Precedence level
543#       lr_next  - Next LR item. Example, if we are ' E -> E . PLUS E'
544#                  then lr_next refers to 'E -> E PLUS . E'
545#       lr_index - LR item index (location of the ".") in the prod list.
546#       lookaheads - LALR lookahead symbols for this item
547#       len      - Length of the production (number of symbols on right hand side)
548# -----------------------------------------------------------------------------
549
550class Production:
551    def __init__(self,**kw):
552        for k,v in kw.items():
553            setattr(self,k,v)
554        self.lr_index = -1
555        self.lr0_added = 0    # Flag indicating whether or not added to LR0 closure
556        self.lr1_added = 0    # Flag indicating whether or not added to LR1
557        self.usyms = [ ]
558        self.lookaheads = { }
559        self.lk_added = { }
560        self.setnumbers = [ ]
561
562    def __str__(self):
563        if self.prod:
564            s = "%s -> %s" % (self.name," ".join(self.prod))
565        else:
566            s = "%s -> <empty>" % self.name
567        return s
568
569    def __repr__(self):
570        return str(self)
571
572    # Compute lr_items from the production
573    def lr_item(self,n):
574        if n > len(self.prod): return None
575        p = Production()
576        p.name = self.name
577        p.prod = list(self.prod)
578        p.number = self.number
579        p.lr_index = n
580        p.lookaheads = { }
581        p.setnumbers = self.setnumbers
582        p.prod.insert(n,".")
583        p.prod = tuple(p.prod)
584        p.len = len(p.prod)
585        p.usyms = self.usyms
586
587        # Precompute list of productions immediately following
588        try:
589            p.lrafter = Prodnames[p.prod[n+1]]
590        except (IndexError,KeyError) as e:
591            p.lrafter = []
592        try:
593            p.lrbefore = p.prod[n-1]
594        except IndexError:
595            p.lrbefore = None
596
597        return p
598
599class MiniProduction:
600    pass
601
602# regex matching identifiers
603_is_identifier = re.compile(r'^[a-zA-Z0-9_-~]+$')
604
605# -----------------------------------------------------------------------------
606# add_production()
607#
608# Given an action function, this function assembles a production rule.
609# The production rule is assumed to be found in the function's docstring.
610# This rule has the general syntax:
611#
612#              name1 ::= production1
613#                     |  production2
614#                     |  production3
615#                    ...
616#                     |  productionn
617#              name2 ::= production1
618#                     |  production2
619#                    ...
620# -----------------------------------------------------------------------------
621
622def add_production(f,file,line,prodname,syms):
623
624    if prodname in Terminals:
625        sys.stderr.write("%s:%d: Illegal rule name '%s'. Already defined as a token.\n" % (file,line,prodname))
626        return -1
627    if prodname == 'error':
628        sys.stderr.write("%s:%d: Illegal rule name '%s'. error is a reserved word.\n" % (file,line,prodname))
629        return -1
630
631    if not _is_identifier.match(prodname):
632        sys.stderr.write("%s:%d: Illegal rule name '%s'\n" % (file,line,prodname))
633        return -1
634
635    for x in range(len(syms)):
636        s = syms[x]
637        if s[0] in "'\"":
638             try:
639                 c = eval(s)
640                 if (len(c) > 1):
641                      sys.stderr.write("%s:%d: Literal token %s in rule '%s' may only be a single character\n" % (file,line,s, prodname))
642                      return -1
643                 if c not in Terminals:
644                      Terminals[c] = []
645                 syms[x] = c
646                 continue
647             except SyntaxError:
648                 pass
649        if not _is_identifier.match(s) and s != '%prec':
650            sys.stderr.write("%s:%d: Illegal name '%s' in rule '%s'\n" % (file,line,s, prodname))
651            return -1
652
653    # See if the rule is already in the rulemap
654    map = "%s -> %s" % (prodname,syms)
655    if map in Prodmap:
656        m = Prodmap[map]
657        sys.stderr.write("%s:%d: Duplicate rule %s.\n" % (file,line, m))
658        sys.stderr.write("%s:%d: Previous definition at %s:%d\n" % (file,line, m.file, m.line))
659        return -1
660
661    p = Production()
662    p.name = prodname
663    p.prod = syms
664    p.file = file
665    p.line = line
666    p.func = f
667    p.number = len(Productions)
668
669
670    Productions.append(p)
671    Prodmap[map] = p
672    if prodname not in Nonterminals:
673        Nonterminals[prodname] = [ ]
674
675    # Add all terminals to Terminals
676    i = 0
677    while i < len(p.prod):
678        t = p.prod[i]
679        if t == '%prec':
680            try:
681                precname = p.prod[i+1]
682            except IndexError:
683                sys.stderr.write("%s:%d: Syntax error. Nothing follows %%prec.\n" % (p.file,p.line))
684                return -1
685
686            prec = Precedence.get(precname,None)
687            if not prec:
688                sys.stderr.write("%s:%d: Nothing known about the precedence of '%s'\n" % (p.file,p.line,precname))
689                return -1
690            else:
691                p.prec = prec
692            del p.prod[i]
693            del p.prod[i]
694            continue
695
696        if t in Terminals:
697            Terminals[t].append(p.number)
698            # Is a terminal.  We'll assign a precedence to p based on this
699            if not hasattr(p,"prec"):
700                p.prec = Precedence.get(t,('right',0))
701        else:
702            if t not in Nonterminals:
703                Nonterminals[t] = [ ]
704            Nonterminals[t].append(p.number)
705        i += 1
706
707    if not hasattr(p,"prec"):
708        p.prec = ('right',0)
709
710    # Set final length of productions
711    p.len  = len(p.prod)
712    p.prod = tuple(p.prod)
713
714    # Calculate unique syms in the production
715    p.usyms = [ ]
716    for s in p.prod:
717        if s not in p.usyms:
718            p.usyms.append(s)
719
720    # Add to the global productions list
721    try:
722        Prodnames[p.name].append(p)
723    except KeyError:
724        Prodnames[p.name] = [ p ]
725    return 0
726
727# Given a raw rule function, this function rips out its doc string
728# and adds rules to the grammar
729
730def add_function(f):
731    line = f.__code__.co_firstlineno
732    file = f.__code__.co_filename
733    error = 0
734
735    if isinstance(f,types.MethodType):
736        reqdargs = 2
737    else:
738        reqdargs = 1
739
740    if f.__code__.co_argcount > reqdargs:
741        sys.stderr.write("%s:%d: Rule '%s' has too many arguments.\n" % (file,line,f.__name__))
742        return -1
743
744    if f.__code__.co_argcount < reqdargs:
745        sys.stderr.write("%s:%d: Rule '%s' requires an argument.\n" % (file,line,f.__name__))
746        return -1
747
748    if f.__doc__:
749        # Split the doc string into lines
750        pstrings = f.__doc__.splitlines()
751        lastp = None
752        dline = line
753        for ps in pstrings:
754            dline += 1
755            p = ps.split()
756            if not p: continue
757            try:
758                if p[0] == '|':
759                    # This is a continuation of a previous rule
760                    if not lastp:
761                        sys.stderr.write("%s:%d: Misplaced '|'.\n" % (file,dline))
762                        return -1
763                    prodname = lastp
764                    if len(p) > 1:
765                        syms = p[1:]
766                    else:
767                        syms = [ ]
768                else:
769                    prodname = p[0]
770                    lastp = prodname
771                    assign = p[1]
772                    if len(p) > 2:
773                        syms = p[2:]
774                    else:
775                        syms = [ ]
776                    if assign != ':' and assign != '::=':
777                        sys.stderr.write("%s:%d: Syntax error. Expected ':'\n" % (file,dline))
778                        return -1
779
780
781                e = add_production(f,file,dline,prodname,syms)
782                error += e
783
784
785            except Exception:
786                sys.stderr.write("%s:%d: Syntax error in rule '%s'\n" % (file,dline,ps))
787                error -= 1
788    else:
789        sys.stderr.write("%s:%d: No documentation string specified in function '%s'\n" % (file,line,f.__name__))
790    return error
791
792
793# Cycle checking code (Michael Dyck)
794
795def compute_reachable():
796    '''
797    Find each symbol that can be reached from the start symbol.
798    Print a warning for any nonterminals that can't be reached.
799    (Unused terminals have already had their warning.)
800    '''
801    Reachable = { }
802    for s in list(Terminals.keys()) + list(Nonterminals.keys()):
803        Reachable[s] = 0
804
805    mark_reachable_from( Productions[0].prod[0], Reachable )
806
807    for s in Nonterminals.keys():
808        if not Reachable[s]:
809            sys.stderr.write("yacc: Symbol '%s' is unreachable.\n" % s)
810
811def mark_reachable_from(s, Reachable):
812    '''
813    Mark all symbols that are reachable from symbol s.
814    '''
815    if Reachable[s]:
816        # We've already reached symbol s.
817        return
818    Reachable[s] = 1
819    for p in Prodnames.get(s,[]):
820        for r in p.prod:
821            mark_reachable_from(r, Reachable)
822
823# -----------------------------------------------------------------------------
824# compute_terminates()
825#
826# This function looks at the various parsing rules and tries to detect
827# infinite recursion cycles (grammar rules where there is no possible way
828# to derive a string of only terminals).
829# -----------------------------------------------------------------------------
830def compute_terminates():
831    '''
832    Raise an error for any symbols that don't terminate.
833    '''
834    Terminates = {}
835
836    # Terminals:
837    for t in Terminals.keys():
838        Terminates[t] = 1
839
840    Terminates['$end'] = 1
841
842    # Nonterminals:
843
844    # Initialize to false:
845    for n in Nonterminals.keys():
846        Terminates[n] = 0
847
848    # Then propagate termination until no change:
849    while 1:
850        some_change = 0
851        for (n,pl) in Prodnames.items():
852            # Nonterminal n terminates iff any of its productions terminates.
853            for p in pl:
854                # Production p terminates iff all of its rhs symbols terminate.
855                for s in p.prod:
856                    if not Terminates[s]:
857                        # The symbol s does not terminate,
858                        # so production p does not terminate.
859                        p_terminates = 0
860                        break
861                else:
862                    # didn't break from the loop,
863                    # so every symbol s terminates
864                    # so production p terminates.
865                    p_terminates = 1
866
867                if p_terminates:
868                    # symbol n terminates!
869                    if not Terminates[n]:
870                        Terminates[n] = 1
871                        some_change = 1
872                    # Don't need to consider any more productions for this n.
873                    break
874
875        if not some_change:
876            break
877
878    some_error = 0
879    for (s,terminates) in Terminates.items():
880        if not terminates:
881            if s not in Prodnames and s not in Terminals and s != 'error':
882                # s is used-but-not-defined, and we've already warned of that,
883                # so it would be overkill to say that it's also non-terminating.
884                pass
885            else:
886                sys.stderr.write("yacc: Infinite recursion detected for symbol '%s'.\n" % s)
887                some_error = 1
888
889    return some_error
890
891# -----------------------------------------------------------------------------
892# verify_productions()
893#
894# This function examines all of the supplied rules to see if they seem valid.
895# -----------------------------------------------------------------------------
896def verify_productions(cycle_check=1):
897    error = 0
898    for p in Productions:
899        if not p: continue
900
901        for s in p.prod:
902            if s not in Prodnames and s not in Terminals and s != 'error':
903                sys.stderr.write("%s:%d: Symbol '%s' used, but not defined as a token or a rule.\n" % (p.file,p.line,s))
904                error = 1
905                continue
906
907    unused_tok = 0
908    # Now verify all of the tokens
909    if yaccdebug:
910        _vf.write("Unused terminals:\n\n")
911    for s,v in Terminals.items():
912        if s != 'error' and not v:
913            sys.stderr.write("yacc: Warning. Token '%s' defined, but not used.\n" % s)
914            if yaccdebug: _vf.write("   %s\n"% s)
915            unused_tok += 1
916
917    # Print out all of the productions
918    if yaccdebug:
919        _vf.write("\nGrammar\n\n")
920        for i in range(1,len(Productions)):
921            _vf.write("Rule %-5d %s\n" % (i, Productions[i]))
922
923    unused_prod = 0
924    # Verify the use of all productions
925    for s,v in Nonterminals.items():
926        if not v:
927            p = Prodnames[s][0]
928            sys.stderr.write("%s:%d: Warning. Rule '%s' defined, but not used.\n" % (p.file,p.line, s))
929            unused_prod += 1
930
931
932    if unused_tok == 1:
933        sys.stderr.write("yacc: Warning. There is 1 unused token.\n")
934    if unused_tok > 1:
935        sys.stderr.write("yacc: Warning. There are %d unused tokens.\n" % unused_tok)
936
937    if unused_prod == 1:
938        sys.stderr.write("yacc: Warning. There is 1 unused rule.\n")
939    if unused_prod > 1:
940        sys.stderr.write("yacc: Warning. There are %d unused rules.\n" % unused_prod)
941
942    if yaccdebug:
943        _vf.write("\nTerminals, with rules where they appear\n\n")
944        ks = list(Terminals.keys())
945        ks.sort()
946        for k in ks:
947            _vf.write("%-20s : %s\n" % (k, " ".join([str(s) for s in Terminals[k]])))
948        _vf.write("\nNonterminals, with rules where they appear\n\n")
949        ks = list(Nonterminals.keys())
950        ks.sort()
951        for k in ks:
952            _vf.write("%-20s : %s\n" % (k, " ".join([str(s) for s in Nonterminals[k]])))
953
954    if (cycle_check):
955        compute_reachable()
956        error += compute_terminates()
957#        error += check_cycles()
958    return error
959
960# -----------------------------------------------------------------------------
961# build_lritems()
962#
963# This function walks the list of productions and builds a complete set of the
964# LR items.  The LR items are stored in two ways:  First, they are uniquely
965# numbered and placed in the list _lritems.  Second, a linked list of LR items
966# is built for each production.  For example:
967#
968#   E -> E PLUS E
969#
970# Creates the list
971#
972#  [E -> . E PLUS E, E -> E . PLUS E, E -> E PLUS . E, E -> E PLUS E . ]
973# -----------------------------------------------------------------------------
974
975def build_lritems():
976    for p in Productions:
977        lastlri = p
978        lri = p.lr_item(0)
979        i = 0
980        while 1:
981            lri = p.lr_item(i)
982            lastlri.lr_next = lri
983            if not lri: break
984            lri.lr_num = len(LRitems)
985            LRitems.append(lri)
986            lastlri = lri
987            i += 1
988
989    # In order for the rest of the parser generator to work, we need to
990    # guarantee that no more lritems are generated.  Therefore, we nuke
991    # the p.lr_item method.  (Only used in debugging)
992    # Production.lr_item = None
993
994# -----------------------------------------------------------------------------
995# add_precedence()
996#
997# Given a list of precedence rules, add to the precedence table.
998# -----------------------------------------------------------------------------
999
1000def add_precedence(plist):
1001    plevel = 0
1002    error = 0
1003    for p in plist:
1004        plevel += 1
1005        try:
1006            prec = p[0]
1007            terms = p[1:]
1008            if prec != 'left' and prec != 'right' and prec != 'nonassoc':
1009                sys.stderr.write("yacc: Invalid precedence '%s'\n" % prec)
1010                return -1
1011            for t in terms:
1012                if t in Precedence:
1013                    sys.stderr.write("yacc: Precedence already specified for terminal '%s'\n" % t)
1014                    error += 1
1015                    continue
1016                Precedence[t] = (prec,plevel)
1017        except:
1018            sys.stderr.write("yacc: Invalid precedence table.\n")
1019            error += 1
1020
1021    return error
1022
1023# -----------------------------------------------------------------------------
1024# augment_grammar()
1025#
1026# Compute the augmented grammar.  This is just a rule S' -> start where start
1027# is the starting symbol.
1028# -----------------------------------------------------------------------------
1029
1030def augment_grammar(start=None):
1031    if not start:
1032        start = Productions[1].name
1033    Productions[0] = Production(name="S'",prod=[start],number=0,len=1,prec=('right',0),func=None)
1034    Productions[0].usyms = [ start ]
1035    Nonterminals[start].append(0)
1036
1037
1038# -------------------------------------------------------------------------
1039# first()
1040#
1041# Compute the value of FIRST1(beta) where beta is a tuple of symbols.
1042#
1043# During execution of compute_first1, the result may be incomplete.
1044# Afterward (e.g., when called from compute_follow()), it will be complete.
1045# -------------------------------------------------------------------------
1046def first(beta):
1047
1048    # We are computing First(x1,x2,x3,...,xn)
1049    result = [ ]
1050    for x in beta:
1051        x_produces_empty = 0
1052
1053        # Add all the non-<empty> symbols of First[x] to the result.
1054        for f in First[x]:
1055            if f == '<empty>':
1056                x_produces_empty = 1
1057            else:
1058                if f not in result: result.append(f)
1059
1060        if x_produces_empty:
1061            # We have to consider the next x in beta,
1062            # i.e. stay in the loop.
1063            pass
1064        else:
1065            # We don't have to consider any further symbols in beta.
1066            break
1067    else:
1068        # There was no 'break' from the loop,
1069        # so x_produces_empty was true for all x in beta,
1070        # so beta produces empty as well.
1071        result.append('<empty>')
1072
1073    return result
1074
1075
1076# FOLLOW(x)
1077# Given a non-terminal.  This function computes the set of all symbols
1078# that might follow it.  Dragon book, p. 189.
1079
1080def compute_follow(start=None):
1081    # Add '$end' to the follow list of the start symbol
1082    for k in Nonterminals.keys():
1083        Follow[k] = [ ]
1084
1085    if not start:
1086        start = Productions[1].name
1087
1088    Follow[start] = [ '$end' ]
1089
1090    while 1:
1091        didadd = 0
1092        for p in Productions[1:]:
1093            # Here is the production set
1094            for i in range(len(p.prod)):
1095                B = p.prod[i]
1096                if B in Nonterminals:
1097                    # Okay. We got a non-terminal in a production
1098                    fst = first(p.prod[i+1:])
1099                    hasempty = 0
1100                    for f in fst:
1101                        if f != '<empty>' and f not in Follow[B]:
1102                            Follow[B].append(f)
1103                            didadd = 1
1104                        if f == '<empty>':
1105                            hasempty = 1
1106                    if hasempty or i == (len(p.prod)-1):
1107                        # Add elements of follow(a) to follow(b)
1108                        for f in Follow[p.name]:
1109                            if f not in Follow[B]:
1110                                Follow[B].append(f)
1111                                didadd = 1
1112        if not didadd: break
1113
1114    if 0 and yaccdebug:
1115        _vf.write('\nFollow:\n')
1116        for k in Nonterminals.keys():
1117            _vf.write("%-20s : %s\n" % (k, " ".join([str(s) for s in Follow[k]])))
1118
1119# -------------------------------------------------------------------------
1120# compute_first1()
1121#
1122# Compute the value of FIRST1(X) for all symbols
1123# -------------------------------------------------------------------------
1124def compute_first1():
1125
1126    # Terminals:
1127    for t in Terminals.keys():
1128        First[t] = [t]
1129
1130    First['$end'] = ['$end']
1131    First['#'] = ['#'] # what's this for?
1132
1133    # Nonterminals:
1134
1135    # Initialize to the empty set:
1136    for n in Nonterminals.keys():
1137        First[n] = []
1138
1139    # Then propagate symbols until no change:
1140    while 1:
1141        some_change = 0
1142        for n in Nonterminals.keys():
1143            for p in Prodnames[n]:
1144                for f in first(p.prod):
1145                    if f not in First[n]:
1146                        First[n].append( f )
1147                        some_change = 1
1148        if not some_change:
1149            break
1150
1151    if 0 and yaccdebug:
1152        _vf.write('\nFirst:\n')
1153        for k in Nonterminals.keys():
1154            _vf.write("%-20s : %s\n" %
1155                (k, " ".join([str(s) for s in First[k]])))
1156
1157# -----------------------------------------------------------------------------
1158#                           === SLR Generation ===
1159#
1160# The following functions are used to construct SLR (Simple LR) parsing tables
1161# as described on p.221-229 of the dragon book.
1162# -----------------------------------------------------------------------------
1163
1164# Global variables for the LR parsing engine
1165def lr_init_vars():
1166    global _lr_action, _lr_goto, _lr_method
1167    global _lr_goto_cache, _lr0_cidhash
1168
1169    _lr_action       = { }        # Action table
1170    _lr_goto         = { }        # Goto table
1171    _lr_method       = "Unknown"  # LR method used
1172    _lr_goto_cache   = { }
1173    _lr0_cidhash     = { }
1174
1175
1176# Compute the LR(0) closure operation on I, where I is a set of LR(0) items.
1177# prodlist is a list of productions.
1178
1179_add_count = 0       # Counter used to detect cycles
1180
1181def lr0_closure(I):
1182    global _add_count
1183
1184    _add_count += 1
1185    prodlist = Productions
1186
1187    # Add everything in I to J
1188    J = I[:]
1189    didadd = 1
1190    while didadd:
1191        didadd = 0
1192        for j in J:
1193            for x in j.lrafter:
1194                if x.lr0_added == _add_count: continue
1195                # Add B --> .G to J
1196                J.append(x.lr_next)
1197                x.lr0_added = _add_count
1198                didadd = 1
1199
1200    return J
1201
1202# Compute the LR(0) goto function goto(I,X) where I is a set
1203# of LR(0) items and X is a grammar symbol.   This function is written
1204# in a way that guarantees uniqueness of the generated goto sets
1205# (i.e. the same goto set will never be returned as two different Python
1206# objects).  With uniqueness, we can later do fast set comparisons using
1207# id(obj) instead of element-wise comparison.
1208
1209def lr0_goto(I,x):
1210    # First we look for a previously cached entry
1211    g = _lr_goto_cache.get((id(I),x),None)
1212    if g: return g
1213
1214    # Now we generate the goto set in a way that guarantees uniqueness
1215    # of the result
1216
1217    s = _lr_goto_cache.get(x,None)
1218    if not s:
1219        s = { }
1220        _lr_goto_cache[x] = s
1221
1222    gs = [ ]
1223    for p in I:
1224        n = p.lr_next
1225        if n and n.lrbefore == x:
1226            s1 = s.get(id(n),None)
1227            if not s1:
1228                s1 = { }
1229                s[id(n)] = s1
1230            gs.append(n)
1231            s = s1
1232    g = s.get('$end',None)
1233    if not g:
1234        if gs:
1235            g = lr0_closure(gs)
1236            s['$end'] = g
1237        else:
1238            s['$end'] = gs
1239    _lr_goto_cache[(id(I),x)] = g
1240    return g
1241
1242_lr0_cidhash = { }
1243
1244# Compute the LR(0) sets of item function
1245def lr0_items():
1246
1247    C = [ lr0_closure([Productions[0].lr_next]) ]
1248    i = 0
1249    for I in C:
1250        _lr0_cidhash[id(I)] = i
1251        i += 1
1252
1253    # Loop over the items in C and each grammar symbols
1254    i = 0
1255    while i < len(C):
1256        I = C[i]
1257        i += 1
1258
1259        # Collect all of the symbols that could possibly be in the goto(I,X) sets
1260        asyms = { }
1261        for ii in I:
1262            for s in ii.usyms:
1263                asyms[s] = None
1264
1265        for x in asyms.keys():
1266            g = lr0_goto(I,x)
1267            if not g:  continue
1268            if id(g) in _lr0_cidhash: continue
1269            _lr0_cidhash[id(g)] = len(C)
1270            C.append(g)
1271
1272    return C
1273
1274# -----------------------------------------------------------------------------
1275#                       ==== LALR(1) Parsing ====
1276#
1277# LALR(1) parsing is almost exactly the same as SLR except that instead of
1278# relying upon Follow() sets when performing reductions, a more selective
1279# lookahead set that incorporates the state of the LR(0) machine is utilized.
1280# Thus, we mainly just have to focus on calculating the lookahead sets.
1281#
1282# The method used here is due to DeRemer and Pennelo (1982).
1283#
1284# DeRemer, F. L., and T. J. Pennelo: "Efficient Computation of LALR(1)
1285#     Lookahead Sets", ACM Transactions on Programming Languages and Systems,
1286#     Vol. 4, No. 4, Oct. 1982, pp. 615-649
1287#
1288# Further details can also be found in:
1289#
1290#  J. Tremblay and P. Sorenson, "The Theory and Practice of Compiler Writing",
1291#      McGraw-Hill Book Company, (1985).
1292#
1293# Note:  This implementation is a complete replacement of the LALR(1)
1294#        implementation in PLY-1.x releases.   That version was based on
1295#        a less efficient algorithm and it had bugs in its implementation.
1296# -----------------------------------------------------------------------------
1297
1298# -----------------------------------------------------------------------------
1299# compute_nullable_nonterminals()
1300#
1301# Creates a dictionary containing all of the non-terminals that might produce
1302# an empty production.
1303# -----------------------------------------------------------------------------
1304
1305def compute_nullable_nonterminals():
1306    nullable = {}
1307    num_nullable = 0
1308    while 1:
1309       for p in Productions[1:]:
1310           if p.len == 0:
1311                nullable[p.name] = 1
1312                continue
1313           for t in p.prod:
1314                if t not in nullable: break
1315           else:
1316                nullable[p.name] = 1
1317       if len(nullable) == num_nullable: break
1318       num_nullable = len(nullable)
1319    return nullable
1320
1321# -----------------------------------------------------------------------------
1322# find_nonterminal_trans(C)
1323#
1324# Given a set of LR(0) items, this functions finds all of the non-terminal
1325# transitions.    These are transitions in which a dot appears immediately before
1326# a non-terminal.   Returns a list of tuples of the form (state,N) where state
1327# is the state number and N is the nonterminal symbol.
1328#
1329# The input C is the set of LR(0) items.
1330# -----------------------------------------------------------------------------
1331
1332def find_nonterminal_transitions(C):
1333     trans = []
1334     for state in range(len(C)):
1335         for p in C[state]:
1336             if p.lr_index < p.len - 1:
1337                  t = (state,p.prod[p.lr_index+1])
1338                  if t[1] in Nonterminals:
1339                        if t not in trans: trans.append(t)
1340         state = state + 1
1341     return trans
1342
1343# -----------------------------------------------------------------------------
1344# dr_relation()
1345#
1346# Computes the DR(p,A) relationships for non-terminal transitions.  The input
1347# is a tuple (state,N) where state is a number and N is a nonterminal symbol.
1348#
1349# Returns a list of terminals.
1350# -----------------------------------------------------------------------------
1351
1352def dr_relation(C,trans,nullable):
1353    dr_set = { }
1354    state,N = trans
1355    terms = []
1356
1357    g = lr0_goto(C[state],N)
1358    for p in g:
1359       if p.lr_index < p.len - 1:
1360           a = p.prod[p.lr_index+1]
1361           if a in Terminals:
1362               if a not in terms: terms.append(a)
1363
1364    # This extra bit is to handle the start state
1365    if state == 0 and N == Productions[0].prod[0]:
1366       terms.append('$end')
1367
1368    return terms
1369
1370# -----------------------------------------------------------------------------
1371# reads_relation()
1372#
1373# Computes the READS() relation (p,A) READS (t,C).
1374# -----------------------------------------------------------------------------
1375
1376def reads_relation(C, trans, empty):
1377    # Look for empty transitions
1378    rel = []
1379    state, N = trans
1380
1381    g = lr0_goto(C[state],N)
1382    j = _lr0_cidhash.get(id(g),-1)
1383    for p in g:
1384        if p.lr_index < p.len - 1:
1385             a = p.prod[p.lr_index + 1]
1386             if a in empty:
1387                  rel.append((j,a))
1388
1389    return rel
1390
1391# -----------------------------------------------------------------------------
1392# compute_lookback_includes()
1393#
1394# Determines the lookback and includes relations
1395#
1396# LOOKBACK:
1397#
1398# This relation is determined by running the LR(0) state machine forward.
1399# For example, starting with a production "N : . A B C", we run it forward
1400# to obtain "N : A B C ."   We then build a relationship between this final
1401# state and the starting state.   These relationships are stored in a dictionary
1402# lookdict.
1403#
1404# INCLUDES:
1405#
1406# Computes the INCLUDE() relation (p,A) INCLUDES (p',B).
1407#
1408# This relation is used to determine non-terminal transitions that occur
1409# inside of other non-terminal transition states.   (p,A) INCLUDES (p', B)
1410# if the following holds:
1411#
1412#       B -> LAT, where T -> epsilon and p' -L-> p
1413#
1414# L is essentially a prefix (which may be empty), T is a suffix that must be
1415# able to derive an empty string.  State p' must lead to state p with the string L.
1416#
1417# -----------------------------------------------------------------------------
1418
1419def compute_lookback_includes(C,trans,nullable):
1420
1421    lookdict = {}          # Dictionary of lookback relations
1422    includedict = {}       # Dictionary of include relations
1423
1424    # Make a dictionary of non-terminal transitions
1425    dtrans = {}
1426    for t in trans:
1427        dtrans[t] = 1
1428
1429    # Loop over all transitions and compute lookbacks and includes
1430    for state,N in trans:
1431        lookb = []
1432        includes = []
1433        for p in C[state]:
1434            if p.name != N: continue
1435
1436            # Okay, we have a name match.  We now follow the production all the way
1437            # through the state machine until we get the . on the right hand side
1438
1439            lr_index = p.lr_index
1440            j = state
1441            while lr_index < p.len - 1:
1442                 lr_index = lr_index + 1
1443                 t = p.prod[lr_index]
1444
1445                 # Check to see if this symbol and state are a non-terminal transition
1446                 if (j,t) in dtrans:
1447                       # Yes.  Okay, there is some chance that this is an includes relation
1448                       # the only way to know for certain is whether the rest of the
1449                       # production derives empty
1450
1451                       li = lr_index + 1
1452                       while li < p.len:
1453                            if p.prod[li] in Terminals: break      # No forget it
1454                            if p.prod[li] not in nullable: break
1455                            li = li + 1
1456                       else:
1457                            # Appears to be a relation between (j,t) and (state,N)
1458                            includes.append((j,t))
1459
1460                 g = lr0_goto(C[j],t)               # Go to next set
1461                 j = _lr0_cidhash.get(id(g),-1)     # Go to next state
1462
1463            # When we get here, j is the final state, now we have to locate the production
1464            for r in C[j]:
1465                 if r.name != p.name: continue
1466                 if r.len != p.len:   continue
1467                 i = 0
1468                 # This look is comparing a production ". A B C" with "A B C ."
1469                 while i < r.lr_index:
1470                      if r.prod[i] != p.prod[i+1]: break
1471                      i = i + 1
1472                 else:
1473                      lookb.append((j,r))
1474        for i in includes:
1475             if i not in includedict: includedict[i] = []
1476             includedict[i].append((state,N))
1477        lookdict[(state,N)] = lookb
1478
1479    return lookdict,includedict
1480
1481# -----------------------------------------------------------------------------
1482# digraph()
1483# traverse()
1484#
1485# The following two functions are used to compute set valued functions
1486# of the form:
1487#
1488#     F(x) = F'(x) U U{F(y) | x R y}
1489#
1490# This is used to compute the values of Read() sets as well as FOLLOW sets
1491# in LALR(1) generation.
1492#
1493# Inputs:  X    - An input set
1494#          R    - A relation
1495#          FP   - Set-valued function
1496# ------------------------------------------------------------------------------
1497
1498def digraph(X,R,FP):
1499    N = { }
1500    for x in X:
1501       N[x] = 0
1502    stack = []
1503    F = { }
1504    for x in X:
1505        if N[x] == 0: traverse(x,N,stack,F,X,R,FP)
1506    return F
1507
1508def traverse(x,N,stack,F,X,R,FP):
1509    stack.append(x)
1510    d = len(stack)
1511    N[x] = d
1512    F[x] = FP(x)             # F(X) <- F'(x)
1513
1514    rel = R(x)               # Get y's related to x
1515    for y in rel:
1516        if N[y] == 0:
1517             traverse(y,N,stack,F,X,R,FP)
1518        N[x] = min(N[x],N[y])
1519        for a in F.get(y,[]):
1520            if a not in F[x]: F[x].append(a)
1521    if N[x] == d:
1522       N[stack[-1]] = sys.maxsize
1523       F[stack[-1]] = F[x]
1524       element = stack.pop()
1525       while element != x:
1526           N[stack[-1]] = sys.maxsize
1527           F[stack[-1]] = F[x]
1528           element = stack.pop()
1529
1530# -----------------------------------------------------------------------------
1531# compute_read_sets()
1532#
1533# Given a set of LR(0) items, this function computes the read sets.
1534#
1535# Inputs:  C        =  Set of LR(0) items
1536#          ntrans   = Set of nonterminal transitions
1537#          nullable = Set of empty transitions
1538#
1539# Returns a set containing the read sets
1540# -----------------------------------------------------------------------------
1541
1542def compute_read_sets(C, ntrans, nullable):
1543    FP = lambda x: dr_relation(C,x,nullable)
1544    R =  lambda x: reads_relation(C,x,nullable)
1545    F = digraph(ntrans,R,FP)
1546    return F
1547
1548# -----------------------------------------------------------------------------
1549# compute_follow_sets()
1550#
1551# Given a set of LR(0) items, a set of non-terminal transitions, a readset,
1552# and an include set, this function computes the follow sets
1553#
1554# Follow(p,A) = Read(p,A) U U {Follow(p',B) | (p,A) INCLUDES (p',B)}
1555#
1556# Inputs:
1557#            ntrans     = Set of nonterminal transitions
1558#            readsets   = Readset (previously computed)
1559#            inclsets   = Include sets (previously computed)
1560#
1561# Returns a set containing the follow sets
1562# -----------------------------------------------------------------------------
1563
1564def compute_follow_sets(ntrans,readsets,inclsets):
1565     FP = lambda x: readsets[x]
1566     R  = lambda x: inclsets.get(x,[])
1567     F = digraph(ntrans,R,FP)
1568     return F
1569
1570# -----------------------------------------------------------------------------
1571# add_lookaheads()
1572#
1573# Attaches the lookahead symbols to grammar rules.
1574#
1575# Inputs:    lookbacks         -  Set of lookback relations
1576#            followset         -  Computed follow set
1577#
1578# This function directly attaches the lookaheads to productions contained
1579# in the lookbacks set
1580# -----------------------------------------------------------------------------
1581
1582def add_lookaheads(lookbacks,followset):
1583    for trans,lb in lookbacks.items():
1584        # Loop over productions in lookback
1585        for state,p in lb:
1586             if state not in p.lookaheads:
1587                  p.lookaheads[state] = []
1588             f = followset.get(trans,[])
1589             for a in f:
1590                  if a not in p.lookaheads[state]: p.lookaheads[state].append(a)
1591
1592# -----------------------------------------------------------------------------
1593# add_lalr_lookaheads()
1594#
1595# This function does all of the work of adding lookahead information for use
1596# with LALR parsing
1597# -----------------------------------------------------------------------------
1598
1599def add_lalr_lookaheads(C):
1600    # Determine all of the nullable nonterminals
1601    nullable = compute_nullable_nonterminals()
1602
1603    # Find all non-terminal transitions
1604    trans = find_nonterminal_transitions(C)
1605
1606    # Compute read sets
1607    readsets = compute_read_sets(C,trans,nullable)
1608
1609    # Compute lookback/includes relations
1610    lookd, included = compute_lookback_includes(C,trans,nullable)
1611
1612    # Compute LALR FOLLOW sets
1613    followsets = compute_follow_sets(trans,readsets,included)
1614
1615    # Add all of the lookaheads
1616    add_lookaheads(lookd,followsets)
1617
1618# -----------------------------------------------------------------------------
1619# lr_parse_table()
1620#
1621# This function constructs the parse tables for SLR or LALR
1622# -----------------------------------------------------------------------------
1623def lr_parse_table(method):
1624    global _lr_method
1625    goto = _lr_goto           # Goto array
1626    action = _lr_action       # Action array
1627    actionp = { }             # Action production array (temporary)
1628
1629    _lr_method = method
1630
1631    n_srconflict = 0
1632    n_rrconflict = 0
1633
1634    if yaccdebug:
1635        sys.stderr.write("yacc: Generating %s parsing table...\n" % method)
1636        _vf.write("\n\nParsing method: %s\n\n" % method)
1637
1638    # Step 1: Construct C = { I0, I1, ... IN}, collection of LR(0) items
1639    # This determines the number of states
1640
1641    C = lr0_items()
1642
1643    if method == 'LALR':
1644        add_lalr_lookaheads(C)
1645
1646    # Build the parser table, state by state
1647    st = 0
1648    for I in C:
1649        # Loop over each production in I
1650        actlist = [ ]              # List of actions
1651
1652        if yaccdebug:
1653            _vf.write("\nstate %d\n\n" % st)
1654            for p in I:
1655                _vf.write("    (%d) %s\n" % (p.number, str(p)))
1656            _vf.write("\n")
1657
1658        for p in I:
1659            try:
1660                if p.prod[-1] == ".":
1661                    if p.name == "S'":
1662                        # Start symbol. Accept!
1663                        action[st,"$end"] = 0
1664                        actionp[st,"$end"] = p
1665                    else:
1666                        # We are at the end of a production.  Reduce!
1667                        if method == 'LALR':
1668                            laheads = p.lookaheads[st]
1669                        else:
1670                            laheads = Follow[p.name]
1671                        for a in laheads:
1672                            actlist.append((a,p,"reduce using rule %d (%s)" % (p.number,p)))
1673                            r = action.get((st,a),None)
1674                            if r is not None:
1675                                # Whoa. Have a shift/reduce or reduce/reduce conflict
1676                                if r > 0:
1677                                    # Need to decide on shift or reduce here
1678                                    # By default we favor shifting. Need to add
1679                                    # some precedence rules here.
1680                                    sprec,slevel = Productions[actionp[st,a].number].prec
1681                                    rprec,rlevel = Precedence.get(a,('right',0))
1682                                    if (slevel < rlevel) or ((slevel == rlevel) and (rprec == 'left')):
1683                                        # We really need to reduce here.
1684                                        action[st,a] = -p.number
1685                                        actionp[st,a] = p
1686                                        if not slevel and not rlevel:
1687                                            _vfc.write("shift/reduce conflict in state %d resolved as reduce.\n" % st)
1688                                            _vf.write("  ! shift/reduce conflict for %s resolved as reduce.\n" % a)
1689                                            n_srconflict += 1
1690                                    elif (slevel == rlevel) and (rprec == 'nonassoc'):
1691                                        action[st,a] = None
1692                                    else:
1693                                        # Hmmm. Guess we'll keep the shift
1694                                        if not rlevel:
1695                                            _vfc.write("shift/reduce conflict in state %d resolved as shift.\n" % st)
1696                                            _vf.write("  ! shift/reduce conflict for %s resolved as shift.\n" % a)
1697                                            n_srconflict +=1
1698                                elif r < 0:
1699                                    # Reduce/reduce conflict.   In this case, we favor the rule
1700                                    # that was defined first in the grammar file
1701                                    oldp = Productions[-r]
1702                                    pp = Productions[p.number]
1703                                    if oldp.line > pp.line:
1704                                        action[st,a] = -p.number
1705                                        actionp[st,a] = p
1706                                    # sys.stderr.write("Reduce/reduce conflict in state %d\n" % st)
1707                                    n_rrconflict += 1
1708                                    _vfc.write("reduce/reduce conflict in state %d resolved using rule %d (%s).\n" % (st, actionp[st,a].number, actionp[st,a]))
1709                                    _vf.write("  ! reduce/reduce conflict for %s resolved using rule %d (%s).\n" % (a,actionp[st,a].number, actionp[st,a]))
1710                                else:
1711                                    sys.stderr.write("Unknown conflict in state %d\n" % st)
1712                            else:
1713                                action[st,a] = -p.number
1714                                actionp[st,a] = p
1715                else:
1716                    i = p.lr_index
1717                    a = p.prod[i+1]       # Get symbol right after the "."
1718                    if a in Terminals:
1719                        g = lr0_goto(I,a)
1720                        j = _lr0_cidhash.get(id(g),-1)
1721                        if j >= 0:
1722                            # We are in a shift state
1723                            actlist.append((a,p,"shift and go to state %d" % j))
1724                            r = action.get((st,a),None)
1725                            if r is not None:
1726                                # Whoa have a shift/reduce or shift/shift conflict
1727                                if r > 0:
1728                                    if r != j:
1729                                        sys.stderr.write("Shift/shift conflict in state %d\n" % st)
1730                                elif r < 0:
1731                                    # Do a precedence check.
1732                                    #   -  if precedence of reduce rule is higher, we reduce.
1733                                    #   -  if precedence of reduce is same and left assoc, we reduce.
1734                                    #   -  otherwise we shift
1735                                    rprec,rlevel = Productions[actionp[st,a].number].prec
1736                                    sprec,slevel = Precedence.get(a,('right',0))
1737                                    if (slevel > rlevel) or ((slevel == rlevel) and (rprec != 'left')):
1738                                        # We decide to shift here... highest precedence to shift
1739                                        action[st,a] = j
1740                                        actionp[st,a] = p
1741                                        if not rlevel:
1742                                            n_srconflict += 1
1743                                            _vfc.write("shift/reduce conflict in state %d resolved as shift.\n" % st)
1744                                            _vf.write("  ! shift/reduce conflict for %s resolved as shift.\n" % a)
1745                                    elif (slevel == rlevel) and (rprec == 'nonassoc'):
1746                                        action[st,a] = None
1747                                    else:
1748                                        # Hmmm. Guess we'll keep the reduce
1749                                        if not slevel and not rlevel:
1750                                            n_srconflict +=1
1751                                            _vfc.write("shift/reduce conflict in state %d resolved as reduce.\n" % st)
1752                                            _vf.write("  ! shift/reduce conflict for %s resolved as reduce.\n" % a)
1753
1754                                else:
1755                                    sys.stderr.write("Unknown conflict in state %d\n" % st)
1756                            else:
1757                                action[st,a] = j
1758                                actionp[st,a] = p
1759
1760            except Exception as e:
1761                raise YaccError("Hosed in lr_parse_table").with_traceback(e)
1762
1763        # Print the actions associated with each terminal
1764        if yaccdebug:
1765          _actprint = { }
1766          for a,p,m in actlist:
1767            if (st,a) in action:
1768                if p is actionp[st,a]:
1769                    _vf.write("    %-15s %s\n" % (a,m))
1770                    _actprint[(a,m)] = 1
1771          _vf.write("\n")
1772          for a,p,m in actlist:
1773            if (st,a) in action:
1774                if p is not actionp[st,a]:
1775                    if (a,m) not in _actprint:
1776                        _vf.write("  ! %-15s [ %s ]\n" % (a,m))
1777                        _actprint[(a,m)] = 1
1778
1779        # Construct the goto table for this state
1780        if yaccdebug:
1781            _vf.write("\n")
1782        nkeys = { }
1783        for ii in I:
1784            for s in ii.usyms:
1785                if s in Nonterminals:
1786                    nkeys[s] = None
1787        for n in nkeys.keys():
1788            g = lr0_goto(I,n)
1789            j = _lr0_cidhash.get(id(g),-1)
1790            if j >= 0:
1791                goto[st,n] = j
1792                if yaccdebug:
1793                    _vf.write("    %-30s shift and go to state %d\n" % (n,j))
1794
1795        st += 1
1796
1797    if yaccdebug:
1798        if n_srconflict == 1:
1799            sys.stderr.write("yacc: %d shift/reduce conflict\n" % n_srconflict)
1800        if n_srconflict > 1:
1801            sys.stderr.write("yacc: %d shift/reduce conflicts\n" % n_srconflict)
1802        if n_rrconflict == 1:
1803            sys.stderr.write("yacc: %d reduce/reduce conflict\n" % n_rrconflict)
1804        if n_rrconflict > 1:
1805            sys.stderr.write("yacc: %d reduce/reduce conflicts\n" % n_rrconflict)
1806
1807# -----------------------------------------------------------------------------
1808#                          ==== LR Utility functions ====
1809# -----------------------------------------------------------------------------
1810
1811# -----------------------------------------------------------------------------
1812# _lr_write_tables()
1813#
1814# This function writes the LR parsing tables to a file
1815# -----------------------------------------------------------------------------
1816
1817def lr_write_tables(modulename=tab_module,outputdir=''):
1818    filename = os.path.join(outputdir,modulename) + ".py"
1819    try:
1820        f = open(filename,"w")
1821
1822        f.write("""
1823# %s
1824# This file is automatically generated. Do not edit.
1825
1826_lr_method = %s
1827
1828_lr_signature = %s
1829""" % (filename, repr(_lr_method), repr(Signature.digest())))
1830
1831        # Change smaller to 0 to go back to original tables
1832        smaller = 1
1833
1834        # Factor out names to try and make smaller
1835        if smaller:
1836            items = { }
1837
1838            for k,v in _lr_action.items():
1839                i = items.get(k[1])
1840                if not i:
1841                    i = ([],[])
1842                    items[k[1]] = i
1843                i[0].append(k[0])
1844                i[1].append(v)
1845
1846            f.write("\n_lr_action_items = {")
1847            for k,v in items.items():
1848                f.write("%r:([" % k)
1849                for i in v[0]:
1850                    f.write("%r," % i)
1851                f.write("],[")
1852                for i in v[1]:
1853                    f.write("%r," % i)
1854
1855                f.write("]),")
1856            f.write("}\n")
1857
1858            f.write("""
1859_lr_action = { }
1860for _k, _v in _lr_action_items.items():
1861   for _x,_y in zip(_v[0],_v[1]):
1862       _lr_action[(_x,_k)] = _y
1863del _lr_action_items
1864""")
1865
1866        else:
1867            f.write("\n_lr_action = { ");
1868            for k,v in _lr_action.items():
1869                f.write("(%r,%r):%r," % (k[0],k[1],v))
1870            f.write("}\n");
1871
1872        if smaller:
1873            # Factor out names to try and make smaller
1874            items = { }
1875
1876            for k,v in _lr_goto.items():
1877                i = items.get(k[1])
1878                if not i:
1879                    i = ([],[])
1880                    items[k[1]] = i
1881                i[0].append(k[0])
1882                i[1].append(v)
1883
1884            f.write("\n_lr_goto_items = {")
1885            for k,v in items.items():
1886                f.write("%r:([" % k)
1887                for i in v[0]:
1888                    f.write("%r," % i)
1889                f.write("],[")
1890                for i in v[1]:
1891                    f.write("%r," % i)
1892
1893                f.write("]),")
1894            f.write("}\n")
1895
1896            f.write("""
1897_lr_goto = { }
1898for _k, _v in _lr_goto_items.items():
1899   for _x,_y in zip(_v[0],_v[1]):
1900       _lr_goto[(_x,_k)] = _y
1901del _lr_goto_items
1902""")
1903        else:
1904            f.write("\n_lr_goto = { ");
1905            for k,v in _lr_goto.items():
1906                f.write("(%r,%r):%r," % (k[0],k[1],v))
1907            f.write("}\n");
1908
1909        # Write production table
1910        f.write("_lr_productions = [\n")
1911        for p in Productions:
1912            if p:
1913                if (p.func):
1914                    f.write("  (%r,%d,%r,%r,%d),\n" % (p.name, p.len, p.func.__name__,p.file,p.line))
1915                else:
1916                    f.write("  (%r,%d,None,None,None),\n" % (p.name, p.len))
1917            else:
1918                f.write("  None,\n")
1919        f.write("]\n")
1920
1921        f.close()
1922
1923    except IOError as e:
1924        print("Unable to create '%s'" % filename)
1925        print(e)
1926
1927def lr_read_tables(module=tab_module,optimize=0):
1928    global _lr_action, _lr_goto, _lr_productions, _lr_method
1929    try:
1930        exec("import %s as parsetab" % module)
1931
1932        if (optimize) or (Signature.digest() == parsetab._lr_signature):
1933            _lr_action = parsetab._lr_action
1934            _lr_goto   = parsetab._lr_goto
1935            _lr_productions = parsetab._lr_productions
1936            _lr_method = parsetab._lr_method
1937            return 1
1938        else:
1939            return 0
1940
1941    except (ImportError,AttributeError):
1942        return 0
1943
1944
1945# Available instance types.  This is used when parsers are defined by a class.
1946# In Python3 the InstanceType and ObjectType are no more, they've passed, ceased
1947# to be, they are ex-classes along with old-style classes
1948
1949try:
1950   _INSTANCETYPE = (types.InstanceType, types.ObjectType)
1951except AttributeError:
1952   _INSTANCETYPE = object
1953
1954# -----------------------------------------------------------------------------
1955# yacc(module)
1956#
1957# Build the parser module
1958# -----------------------------------------------------------------------------
1959
1960def yacc(method=default_lr, debug=yaccdebug, module=None, tabmodule=tab_module, start=None, check_recursion=1, optimize=0,write_tables=1,debugfile=debug_file,outputdir=''):
1961    global yaccdebug
1962    yaccdebug = debug
1963
1964    initialize_vars()
1965    files = { }
1966    error = 0
1967
1968
1969    # Add parsing method to signature
1970    Signature.update(util.encode_input(method))
1971
1972    # If a "module" parameter was supplied, extract its dictionary.
1973    # Note: a module may in fact be an instance as well.
1974
1975    if module:
1976        # User supplied a module object.
1977        if isinstance(module, types.ModuleType):
1978            ldict = module.__dict__
1979        elif isinstance(module, _INSTANCETYPE):
1980            _items = [(k,getattr(module,k)) for k in dir(module)]
1981            ldict = { }
1982            for i in _items:
1983                ldict[i[0]] = i[1]
1984        else:
1985            raise ValueError("Expected a module")
1986
1987    else:
1988        # No module given.  We might be able to get information from the caller.
1989        # Throw an exception and unwind the traceback to get the globals
1990
1991        try:
1992            raise RuntimeError
1993        except RuntimeError:
1994            e,b,t = sys.exc_info()
1995            f = t.tb_frame
1996            f = f.f_back           # Walk out to our calling function
1997            ldict = f.f_globals    # Grab its globals dictionary
1998
1999    # Add starting symbol to signature
2000    if not start:
2001        start = ldict.get("start",None)
2002    if start:
2003        Signature.update(util.encode_input(start))
2004
2005    # If running in optimized mode.  We're going to
2006
2007    if (optimize and lr_read_tables(tabmodule,1)):
2008        # Read parse table
2009        del Productions[:]
2010        for p in _lr_productions:
2011            if not p:
2012                Productions.append(None)
2013            else:
2014                m = MiniProduction()
2015                m.name = p[0]
2016                m.len  = p[1]
2017                m.file = p[3]
2018                m.line = p[4]
2019                if p[2]:
2020                    m.func = ldict[p[2]]
2021                Productions.append(m)
2022
2023    else:
2024        # Get the tokens map
2025        if (module and isinstance(module,_INSTANCETYPE)):
2026            tokens = getattr(module,"tokens",None)
2027        else:
2028            tokens = ldict.get("tokens",None)
2029
2030        if not tokens:
2031            raise YaccError("module does not define a list 'tokens'")
2032        if not (isinstance(tokens,list) or isinstance(tokens,tuple)):
2033            raise YaccError("tokens must be a list or tuple.")
2034
2035        # Check to see if a requires dictionary is defined.
2036        requires = ldict.get("require",None)
2037        if requires:
2038            if not (isinstance(requires,dict)):
2039                raise YaccError("require must be a dictionary.")
2040
2041            for r,v in requires.items():
2042                try:
2043                    if not (isinstance(v,list)):
2044                        raise TypeError
2045                    v1 = [x.split(".") for x in v]
2046                    Requires[r] = v1
2047                except Exception:
2048                    print("Invalid specification for rule '%s' in require. Expected a list of strings" % r)
2049
2050
2051        # Build the dictionary of terminals.  We a record a 0 in the
2052        # dictionary to track whether or not a terminal is actually
2053        # used in the grammar
2054
2055        if 'error' in tokens:
2056            print("yacc: Illegal token 'error'.  Is a reserved word.")
2057            raise YaccError("Illegal token name")
2058
2059        for n in tokens:
2060            if n in Terminals:
2061                print("yacc: Warning. Token '%s' multiply defined." % n)
2062            Terminals[n] = [ ]
2063
2064        Terminals['error'] = [ ]
2065
2066        # Get the precedence map (if any)
2067        prec = ldict.get("precedence",None)
2068        if prec:
2069            if not (isinstance(prec,list) or isinstance(prec,tuple)):
2070                raise YaccError("precedence must be a list or tuple.")
2071            add_precedence(prec)
2072            Signature.update(util.encode_input(repr(prec)))
2073
2074        for n in tokens:
2075            if n not in Precedence:
2076                Precedence[n] = ('right',0)         # Default, right associative, 0 precedence
2077
2078        # Look for error handler
2079        ef = ldict.get('p_error',None)
2080        if ef:
2081            if isinstance(ef,types.FunctionType):
2082                ismethod = 0
2083            elif isinstance(ef, types.MethodType):
2084                ismethod = 1
2085            else:
2086                raise YaccError("'p_error' defined, but is not a function or method.")
2087            eline = ef.__code__.co_firstlineno
2088            efile = ef.__code__.co_filename
2089            files[efile] = None
2090
2091            if (ef.__code__.co_argcount != 1+ismethod):
2092                raise YaccError("%s:%d: p_error() requires 1 argument." % (efile,eline))
2093            global Errorfunc
2094            Errorfunc = ef
2095        else:
2096            print("yacc: Warning. no p_error() function is defined.")
2097
2098        # Get the list of built-in functions with p_ prefix
2099        symbols = [ldict[f] for f in ldict.keys()
2100               if (type(ldict[f]) in (types.FunctionType, types.MethodType) and ldict[f].__name__[:2] == 'p_'
2101                   and ldict[f].__name__ != 'p_error')]
2102
2103        # Check for non-empty symbols
2104        if len(symbols) == 0:
2105            raise YaccError("no rules of the form p_rulename are defined.")
2106
2107        # Sort the symbols by line number
2108        symbols.sort(key=lambda x: x.__code__.co_firstlineno)
2109
2110        # Add all of the symbols to the grammar
2111        for f in symbols:
2112            if (add_function(f)) < 0:
2113                error += 1
2114            else:
2115                files[f.__code__.co_filename] = None
2116
2117        # Make a signature of the docstrings
2118        for f in symbols:
2119            if f.__doc__:
2120                Signature.update(util.encode_input(f.__doc__))
2121
2122        lr_init_vars()
2123
2124        if error:
2125            raise YaccError("Unable to construct parser.")
2126
2127        if not lr_read_tables(tabmodule):
2128
2129            # Validate files
2130            for filename in files.keys():
2131                if not validate_file(filename):
2132                    error = 1
2133
2134            # Validate dictionary
2135            validate_dict(ldict)
2136
2137            if start and start not in Prodnames:
2138                raise YaccError("Bad starting symbol '%s'" % start)
2139
2140            augment_grammar(start)
2141            error = verify_productions(cycle_check=check_recursion)
2142            otherfunc = [ldict[f] for f in ldict.keys()
2143               if (type(f) in (types.FunctionType,types.MethodType) and ldict[f].__name__[:2] != 'p_')]
2144
2145            if error:
2146                raise YaccError("Unable to construct parser.")
2147
2148            build_lritems()
2149            compute_first1()
2150            compute_follow(start)
2151
2152            if method in ['SLR','LALR']:
2153                lr_parse_table(method)
2154            else:
2155                raise YaccError("Unknown parsing method '%s'" % method)
2156
2157            if write_tables:
2158                lr_write_tables(tabmodule,outputdir)
2159
2160            if yaccdebug:
2161                try:
2162                    f = open(os.path.join(outputdir,debugfile),"w")
2163                    f.write(_vfc.getvalue())
2164                    f.write("\n\n")
2165                    f.write(_vf.getvalue())
2166                    f.close()
2167                except IOError as e:
2168                    print("yacc: can't create '%s'" % debugfile,e)
2169
2170    # Made it here.   Create a parser object and set up its internal state.
2171    # Set global parse() method to bound method of parser object.
2172
2173    p = Parser("xyzzy")
2174    p.productions = Productions
2175    p.errorfunc = Errorfunc
2176    p.action = _lr_action
2177    p.goto   = _lr_goto
2178    p.method = _lr_method
2179    p.require = Requires
2180
2181    global parse
2182    parse = p.parse
2183
2184    global parser
2185    parser = p
2186
2187    # Clean up all of the globals we created
2188    if (not optimize):
2189        yacc_cleanup()
2190    return p
2191
2192# yacc_cleanup function.  Delete all of the global variables
2193# used during table construction
2194
2195def yacc_cleanup():
2196    global _lr_action, _lr_goto, _lr_method, _lr_goto_cache
2197    del _lr_action, _lr_goto, _lr_method, _lr_goto_cache
2198
2199    global Productions, Prodnames, Prodmap, Terminals
2200    global Nonterminals, First, Follow, Precedence, LRitems
2201    global Errorfunc, Signature, Requires
2202
2203    del Productions, Prodnames, Prodmap, Terminals
2204    del Nonterminals, First, Follow, Precedence, LRitems
2205    del Errorfunc, Signature, Requires
2206
2207    global _vf, _vfc
2208    del _vf, _vfc
2209
2210
2211# Stub that raises an error if parsing is attempted without first calling yacc()
2212def parse(*args,**kwargs):
2213    raise YaccError("yacc: No parser built with yacc()")
2214
2215