Update minimum version requirement for GTK to 2.12.
[obnox/wireshark/wip.git] / tools / yacc.py
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