1 # -----------------------------------------------------------------------------
4 # Copyright (C) 2001-2011,
5 # David M. Beazley (Dabeaz LLC)
8 # Redistribution and use in source and binary forms, with or without
9 # modification, are permitted provided that the following conditions are
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.
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 # -----------------------------------------------------------------------------
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.
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).
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.
53 # :::::::: WARNING :::::::
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
60 # ----------------------------------------------------------------------------
63 __tabversion__ = "3.2" # Table version
65 #-----------------------------------------------------------------------------
66 # === User configurable parameters ===
68 # Change these to modify the default behavior of yacc (if you wish)
69 #-----------------------------------------------------------------------------
71 yaccdebug = 1 # Debugging mode. If set, yacc generates a
72 # a 'parser.out' file in the current directory
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
78 error_count = 3 # Number of symbols that must be shifted to leave recovery mode
80 yaccdevel = 0 # Set to True if developing yacc. This turns off optimized
81 # implementations of certain functions.
83 resultlimit = 40 # Size limit of results when running in debug mode.
85 pickle_protocol = 0 # Protocol to use when writing pickle files
87 import re, types, sys, os.path, inspect
89 # Compatibility function for python 2.6/3.0
90 if sys.version_info[0] < 3:
97 # String type-checking compatibility
98 if sys.version_info[0] < 3:
99 string_types = basestring
106 except AttributeError:
109 # Python 2.x/3.0 compatibility.
111 if sys.version_info[0] < 3:
114 import ply.lex as lex
117 # This object is a stand-in for a logging object created by the
118 # logging module. PLY will use this by default to create things
119 # such as the parser.out file. If a user wants more detailed
120 # information, they can create their own logging object and pass
123 class PlyLogger(object):
124 def __init__(self,f):
126 def debug(self,msg,*args,**kwargs):
127 self.f.write((msg % args) + "\n")
130 def warning(self,msg,*args,**kwargs):
131 self.f.write("WARNING: "+ (msg % args) + "\n")
133 def error(self,msg,*args,**kwargs):
134 self.f.write("ERROR: " + (msg % args) + "\n")
138 # Null logger is used when no output is generated. Does nothing.
139 class NullLogger(object):
140 def __getattribute__(self,name):
142 def __call__(self,*args,**kwargs):
145 # Exception raised for yacc-related errors
146 class YaccError(Exception): pass
148 # Format the result message that the parser produces when running in debug mode.
149 def format_result(r):
151 if '\n' in repr_str: repr_str = repr(repr_str)
152 if len(repr_str) > resultlimit:
153 repr_str = repr_str[:resultlimit]+" ..."
154 result = "<%s @ 0x%x> (%s)" % (type(r).__name__,id(r),repr_str)
158 # Format stack entries when the parser is running in debug mode
159 def format_stack_entry(r):
161 if '\n' in repr_str: repr_str = repr(repr_str)
162 if len(repr_str) < 16:
165 return "<%s @ 0x%x>" % (type(r).__name__,id(r))
167 # Panic mode error recovery support. This feature is being reworked--much of the
168 # code here is to offer a deprecation/backwards compatible transition
173 _warnmsg = """PLY: Don't use global functions errok(), token(), and restart() in p_error().
174 Instead, invoke the methods on the associated parser instance:
178 # Use parser.errok(), parser.token(), parser.restart()
185 warnings.warn(_warnmsg)
189 warnings.warn(_warnmsg)
193 warnings.warn(_warnmsg)
196 # Utility function to call the p_error() function with some deprecation hacks
197 def call_errorfunc(errorfunc,token,parser):
198 global _errok, _token, _restart
199 _errok = parser.errok
200 _token = parser.token
201 _restart = parser.restart
203 del _errok, _token, _restart
205 #-----------------------------------------------------------------------------
206 # === LR Parsing Engine ===
208 # The following classes are used for the LR parser itself. These are not
209 # used during table construction and are independent of the actual LR
210 # table generation algorithm
211 #-----------------------------------------------------------------------------
213 # This class is used to hold non-terminal grammar symbols during parsing.
214 # It normally has the following attributes set:
215 # .type = Grammar symbol type
216 # .value = Symbol value
217 # .lineno = Starting line number
218 # .endlineno = Ending line number (optional, set automatically)
219 # .lexpos = Starting lex position
220 # .endlexpos = Ending lex position (optional, set automatically)
223 def __str__(self): return self.type
224 def __repr__(self): return str(self)
226 # This class is a wrapper around the objects actually passed to each
227 # grammar rule. Index lookup and assignment actually assign the
228 # .value attribute of the underlying YaccSymbol object.
229 # The lineno() method returns the line number of a given
230 # item (or 0 if not defined). The linespan() method returns
231 # a tuple of (startline,endline) representing the range of lines
232 # for a symbol. The lexspan() method returns a tuple (lexpos,endlexpos)
233 # representing the range of positional information for a symbol.
235 class YaccProduction:
236 def __init__(self,s,stack=None):
241 def __getitem__(self,n):
242 if isinstance(n, slice):
243 return [s.value for s in self.slice[n]]
245 return self.slice[n].value
247 return self.stack[n].value
249 def __setitem__(self,n,v):
250 self.slice[n].value = v
252 def __getslice__(self,i,j):
253 return [s.value for s in self.slice[i:j]]
256 return len(self.slice)
259 return getattr(self.slice[n],"lineno",0)
261 def set_lineno(self,n,lineno):
262 self.slice[n].lineno = lineno
264 def linespan(self,n):
265 startline = getattr(self.slice[n],"lineno",0)
266 endline = getattr(self.slice[n],"endlineno",startline)
267 return startline,endline
270 return getattr(self.slice[n],"lexpos",0)
273 startpos = getattr(self.slice[n],"lexpos",0)
274 endpos = getattr(self.slice[n],"endlexpos",startpos)
275 return startpos,endpos
281 # -----------------------------------------------------------------------------
284 # The LR Parsing engine.
285 # -----------------------------------------------------------------------------
288 def __init__(self,lrtab,errorf):
289 self.productions = lrtab.lr_productions
290 self.action = lrtab.lr_action
291 self.goto = lrtab.lr_goto
292 self.errorfunc = errorf
298 del self.statestack[:]
302 self.symstack.append(sym)
303 self.statestack.append(0)
305 def parse(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
306 if debug or yaccdevel:
307 if isinstance(debug,int):
308 debug = PlyLogger(sys.stderr)
309 return self.parsedebug(input,lexer,debug,tracking,tokenfunc)
311 return self.parseopt(input,lexer,debug,tracking,tokenfunc)
313 return self.parseopt_notrack(input,lexer,debug,tracking,tokenfunc)
316 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
319 # This is the debugging enabled version of parse(). All changes made to the
320 # parsing engine should be made here. For the non-debugging version,
321 # copy this code to a method parseopt() and delete all of the sections
328 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
330 def parsedebug(self,input=None,lexer=None,debug=None,tracking=0,tokenfunc=None):
331 lookahead = None # Current lookahead symbol
332 lookaheadstack = [ ] # Stack of lookahead symbols
333 actions = self.action # Local reference to action table (to avoid lookup on self.)
334 goto = self.goto # Local reference to goto table (to avoid lookup on self.)
335 prod = self.productions # Local reference to production list (to avoid lookup on self.)
336 pslice = YaccProduction(None) # Production object passed to grammar rules
337 errorcount = 0 # Used during error recovery
340 debug.info("PLY: PARSE DEBUG START")
343 # If no lexer was given, we will try to use the lex module
348 # Set up the lexer and parser objects on pslice
352 # If input was supplied, pass to lexer
353 if input is not None:
356 if tokenfunc is None:
358 get_token = lexer.token
360 get_token = tokenfunc
362 # Set the parser() token method (sometimes used in error recovery)
363 self.token = get_token
365 # Set up the state and symbol stacks
367 statestack = [ ] # Stack of parsing states
368 self.statestack = statestack
369 symstack = [ ] # Stack of grammar symbols
370 self.symstack = symstack
372 pslice.stack = symstack # Put in the production
373 errtoken = None # Err token
375 # The start state is assumed to be (0,$end)
383 # Get the next symbol on the input. If a lookahead symbol
384 # is already set, we just use that. Otherwise, we'll pull
385 # the next token off of the lookaheadstack or from the lexer
389 debug.debug('State : %s', state)
393 if not lookaheadstack:
394 lookahead = get_token() # Get the next token
396 lookahead = lookaheadstack.pop()
398 lookahead = YaccSymbol()
399 lookahead.type = "$end"
402 debug.debug('Stack : %s',
403 ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip())
406 # Check the action table
407 ltype = lookahead.type
408 t = actions[state].get(ltype)
412 # shift a symbol on the stack
417 debug.debug("Action : Shift and goto state %s", t)
420 symstack.append(lookahead)
423 # Decrease error count on successful shift
424 if errorcount: errorcount -=1
428 # reduce a symbol on the stack, emit a production
433 # Get production function
435 sym.type = pname # Production name
440 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)
442 debug.info("Action : Reduce rule [%s] with %s and goto state %d", p.str, [],-t)
447 targ = symstack[-plen-1:]
453 sym.lineno = t1.lineno
454 sym.lexpos = t1.lexpos
456 sym.endlineno = getattr(t1,"endlineno",t1.lineno)
457 sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos)
461 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
462 # The code enclosed in this section is duplicated
463 # below as a performance optimization. Make sure
464 # changes get made in both locations.
469 # Call the grammar rule with our special slice object
471 del statestack[-plen:]
474 debug.info("Result : %s", format_result(pslice[0]))
477 state = goto[statestack[-1]][pname]
478 statestack.append(state)
480 # If an error was set. Enter error recovery state
481 lookaheadstack.append(lookahead)
484 state = statestack[-1]
487 errorcount = error_count
490 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
496 sym.lineno = lexer.lineno
497 sym.lexpos = lexer.lexpos
502 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
503 # The code enclosed in this section is duplicated
504 # above as a performance optimization. Make sure
505 # changes get made in both locations.
510 # Call the grammar rule with our special slice object
513 debug.info("Result : %s", format_result(pslice[0]))
516 state = goto[statestack[-1]][pname]
517 statestack.append(state)
519 # If an error was set. Enter error recovery state
520 lookaheadstack.append(lookahead)
523 state = statestack[-1]
526 errorcount = error_count
529 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
533 result = getattr(n,"value",None)
535 debug.info("Done : Returning %s", format_result(result))
536 debug.info("PLY: PARSE DEBUG END")
543 debug.error('Error : %s',
544 ("%s . %s" % (" ".join([xx.type for xx in symstack][1:]), str(lookahead))).lstrip())
547 # We have some kind of parsing error here. To handle
548 # this, we are going to push the current token onto
549 # the tokenstack and replace it with an 'error' token.
550 # If there are any synchronization rules, they may
553 # In addition to pushing the error token, we call call
554 # the user defined p_error() function if this is the
555 # first syntax error. This function is only called if
557 if errorcount == 0 or self.errorok:
558 errorcount = error_count
561 if errtoken.type == "$end":
562 errtoken = None # End of file!
564 if errtoken and not hasattr(errtoken,'lexer'):
565 errtoken.lexer = lexer
566 tok = call_errorfunc(self.errorfunc, errtoken, self)
568 # User must have done some kind of panic
569 # mode recovery on their own. The
570 # returned token is the next lookahead
576 if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
579 sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
581 sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
583 sys.stderr.write("yacc: Parse error in input. EOF\n")
587 errorcount = error_count
589 # case 1: the statestack only has 1 entry on it. If we're in this state, the
590 # entire parse has been rolled back and we're completely hosed. The token is
591 # discarded and we just keep going.
593 if len(statestack) <= 1 and lookahead.type != "$end":
597 # Nuke the pushback stack
598 del lookaheadstack[:]
601 # case 2: the statestack has a couple of entries on it, but we're
602 # at the end of the file. nuke the top entry and generate an error token
604 # Start nuking entries on the stack
605 if lookahead.type == "$end":
606 # Whoa. We're really hosed here. Bail out
609 if lookahead.type != 'error':
611 if sym.type == 'error':
612 # Hmmm. Error is on top of stack, we'll just nuke input
613 # symbol and continue
615 sym.endlineno = getattr(lookahead,"lineno", sym.lineno)
616 sym.endlexpos = getattr(lookahead,"lexpos", sym.lexpos)
621 if hasattr(lookahead,"lineno"):
622 t.lineno = lookahead.lineno
623 if hasattr(lookahead,"lexpos"):
624 t.lexpos = lookahead.lexpos
626 lookaheadstack.append(lookahead)
631 lookahead.lineno = sym.lineno
632 lookahead.lexpos = sym.lexpos
634 state = statestack[-1] # Potential bug fix
638 # Call an error function here
639 raise RuntimeError("yacc: internal parser error!!!\n")
641 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
644 # Optimized version of parse() method. DO NOT EDIT THIS CODE DIRECTLY.
645 # Edit the debug version above, then copy any modifications to the method
646 # below while removing #--! DEBUG sections.
647 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
650 def parseopt(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
651 lookahead = None # Current lookahead symbol
652 lookaheadstack = [ ] # Stack of lookahead symbols
653 actions = self.action # Local reference to action table (to avoid lookup on self.)
654 goto = self.goto # Local reference to goto table (to avoid lookup on self.)
655 prod = self.productions # Local reference to production list (to avoid lookup on self.)
656 pslice = YaccProduction(None) # Production object passed to grammar rules
657 errorcount = 0 # Used during error recovery
659 # If no lexer was given, we will try to use the lex module
664 # Set up the lexer and parser objects on pslice
668 # If input was supplied, pass to lexer
669 if input is not None:
672 if tokenfunc is None:
674 get_token = lexer.token
676 get_token = tokenfunc
678 # Set the parser() token method (sometimes used in error recovery)
679 self.token = get_token
681 # Set up the state and symbol stacks
683 statestack = [ ] # Stack of parsing states
684 self.statestack = statestack
685 symstack = [ ] # Stack of grammar symbols
686 self.symstack = symstack
688 pslice.stack = symstack # Put in the production
689 errtoken = None # Err token
691 # The start state is assumed to be (0,$end)
699 # Get the next symbol on the input. If a lookahead symbol
700 # is already set, we just use that. Otherwise, we'll pull
701 # the next token off of the lookaheadstack or from the lexer
704 if not lookaheadstack:
705 lookahead = get_token() # Get the next token
707 lookahead = lookaheadstack.pop()
709 lookahead = YaccSymbol()
710 lookahead.type = '$end'
712 # Check the action table
713 ltype = lookahead.type
714 t = actions[state].get(ltype)
718 # shift a symbol on the stack
722 symstack.append(lookahead)
725 # Decrease error count on successful shift
726 if errorcount: errorcount -=1
730 # reduce a symbol on the stack, emit a production
735 # Get production function
737 sym.type = pname # Production name
741 targ = symstack[-plen-1:]
747 sym.lineno = t1.lineno
748 sym.lexpos = t1.lexpos
750 sym.endlineno = getattr(t1,"endlineno",t1.lineno)
751 sym.endlexpos = getattr(t1,"endlexpos",t1.lexpos)
755 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
756 # The code enclosed in this section is duplicated
757 # below as a performance optimization. Make sure
758 # changes get made in both locations.
763 # Call the grammar rule with our special slice object
765 del statestack[-plen:]
768 state = goto[statestack[-1]][pname]
769 statestack.append(state)
771 # If an error was set. Enter error recovery state
772 lookaheadstack.append(lookahead)
775 state = statestack[-1]
778 errorcount = error_count
781 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
787 sym.lineno = lexer.lineno
788 sym.lexpos = lexer.lexpos
793 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
794 # The code enclosed in this section is duplicated
795 # above as a performance optimization. Make sure
796 # changes get made in both locations.
801 # Call the grammar rule with our special slice object
804 state = goto[statestack[-1]][pname]
805 statestack.append(state)
807 # If an error was set. Enter error recovery state
808 lookaheadstack.append(lookahead)
811 state = statestack[-1]
814 errorcount = error_count
817 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
821 return getattr(n,"value",None)
825 # We have some kind of parsing error here. To handle
826 # this, we are going to push the current token onto
827 # the tokenstack and replace it with an 'error' token.
828 # If there are any synchronization rules, they may
831 # In addition to pushing the error token, we call call
832 # the user defined p_error() function if this is the
833 # first syntax error. This function is only called if
835 if errorcount == 0 or self.errorok:
836 errorcount = error_count
839 if errtoken.type == '$end':
840 errtoken = None # End of file!
842 if errtoken and not hasattr(errtoken,'lexer'):
843 errtoken.lexer = lexer
844 tok = call_errorfunc(self.errorfunc, errtoken, self)
847 # User must have done some kind of panic
848 # mode recovery on their own. The
849 # returned token is the next lookahead
855 if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
858 sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
860 sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
862 sys.stderr.write("yacc: Parse error in input. EOF\n")
866 errorcount = error_count
868 # case 1: the statestack only has 1 entry on it. If we're in this state, the
869 # entire parse has been rolled back and we're completely hosed. The token is
870 # discarded and we just keep going.
872 if len(statestack) <= 1 and lookahead.type != '$end':
876 # Nuke the pushback stack
877 del lookaheadstack[:]
880 # case 2: the statestack has a couple of entries on it, but we're
881 # at the end of the file. nuke the top entry and generate an error token
883 # Start nuking entries on the stack
884 if lookahead.type == '$end':
885 # Whoa. We're really hosed here. Bail out
888 if lookahead.type != 'error':
890 if sym.type == 'error':
891 # Hmmm. Error is on top of stack, we'll just nuke input
892 # symbol and continue
894 sym.endlineno = getattr(lookahead,"lineno", sym.lineno)
895 sym.endlexpos = getattr(lookahead,"lexpos", sym.lexpos)
900 if hasattr(lookahead,"lineno"):
901 t.lineno = lookahead.lineno
902 if hasattr(lookahead,"lexpos"):
903 t.lexpos = lookahead.lexpos
905 lookaheadstack.append(lookahead)
910 lookahead.lineno = sym.lineno
911 lookahead.lexpos = sym.lexpos
913 state = statestack[-1] # Potential bug fix
917 # Call an error function here
918 raise RuntimeError("yacc: internal parser error!!!\n")
920 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
921 # parseopt_notrack().
923 # Optimized version of parseopt() with line number tracking removed.
924 # DO NOT EDIT THIS CODE DIRECTLY. Copy the optimized version and remove
925 # code in the #--! TRACKING sections
926 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
928 def parseopt_notrack(self,input=None,lexer=None,debug=0,tracking=0,tokenfunc=None):
929 lookahead = None # Current lookahead symbol
930 lookaheadstack = [ ] # Stack of lookahead symbols
931 actions = self.action # Local reference to action table (to avoid lookup on self.)
932 goto = self.goto # Local reference to goto table (to avoid lookup on self.)
933 prod = self.productions # Local reference to production list (to avoid lookup on self.)
934 pslice = YaccProduction(None) # Production object passed to grammar rules
935 errorcount = 0 # Used during error recovery
937 # If no lexer was given, we will try to use the lex module
942 # Set up the lexer and parser objects on pslice
946 # If input was supplied, pass to lexer
947 if input is not None:
950 if tokenfunc is None:
952 get_token = lexer.token
954 get_token = tokenfunc
956 # Set the parser() token method (sometimes used in error recovery)
957 self.token = get_token
959 # Set up the state and symbol stacks
961 statestack = [ ] # Stack of parsing states
962 self.statestack = statestack
963 symstack = [ ] # Stack of grammar symbols
964 self.symstack = symstack
966 pslice.stack = symstack # Put in the production
967 errtoken = None # Err token
969 # The start state is assumed to be (0,$end)
977 # Get the next symbol on the input. If a lookahead symbol
978 # is already set, we just use that. Otherwise, we'll pull
979 # the next token off of the lookaheadstack or from the lexer
982 if not lookaheadstack:
983 lookahead = get_token() # Get the next token
985 lookahead = lookaheadstack.pop()
987 lookahead = YaccSymbol()
988 lookahead.type = '$end'
990 # Check the action table
991 ltype = lookahead.type
992 t = actions[state].get(ltype)
996 # shift a symbol on the stack
1000 symstack.append(lookahead)
1003 # Decrease error count on successful shift
1004 if errorcount: errorcount -=1
1008 # reduce a symbol on the stack, emit a production
1013 # Get production function
1015 sym.type = pname # Production name
1019 targ = symstack[-plen-1:]
1022 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1023 # The code enclosed in this section is duplicated
1024 # below as a performance optimization. Make sure
1025 # changes get made in both locations.
1030 # Call the grammar rule with our special slice object
1031 del symstack[-plen:]
1032 del statestack[-plen:]
1034 symstack.append(sym)
1035 state = goto[statestack[-1]][pname]
1036 statestack.append(state)
1038 # If an error was set. Enter error recovery state
1039 lookaheadstack.append(lookahead)
1042 state = statestack[-1]
1045 errorcount = error_count
1048 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1054 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1055 # The code enclosed in this section is duplicated
1056 # above as a performance optimization. Make sure
1057 # changes get made in both locations.
1062 # Call the grammar rule with our special slice object
1064 symstack.append(sym)
1065 state = goto[statestack[-1]][pname]
1066 statestack.append(state)
1068 # If an error was set. Enter error recovery state
1069 lookaheadstack.append(lookahead)
1072 state = statestack[-1]
1075 errorcount = error_count
1078 # !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
1082 return getattr(n,"value",None)
1086 # We have some kind of parsing error here. To handle
1087 # this, we are going to push the current token onto
1088 # the tokenstack and replace it with an 'error' token.
1089 # If there are any synchronization rules, they may
1092 # In addition to pushing the error token, we call call
1093 # the user defined p_error() function if this is the
1094 # first syntax error. This function is only called if
1096 if errorcount == 0 or self.errorok:
1097 errorcount = error_count
1099 errtoken = lookahead
1100 if errtoken.type == '$end':
1101 errtoken = None # End of file!
1103 if errtoken and not hasattr(errtoken,'lexer'):
1104 errtoken.lexer = lexer
1105 tok = call_errorfunc(self.errorfunc, errtoken, self)
1108 # User must have done some kind of panic
1109 # mode recovery on their own. The
1110 # returned token is the next lookahead
1116 if hasattr(errtoken,"lineno"): lineno = lookahead.lineno
1119 sys.stderr.write("yacc: Syntax error at line %d, token=%s\n" % (lineno, errtoken.type))
1121 sys.stderr.write("yacc: Syntax error, token=%s" % errtoken.type)
1123 sys.stderr.write("yacc: Parse error in input. EOF\n")
1127 errorcount = error_count
1129 # case 1: the statestack only has 1 entry on it. If we're in this state, the
1130 # entire parse has been rolled back and we're completely hosed. The token is
1131 # discarded and we just keep going.
1133 if len(statestack) <= 1 and lookahead.type != '$end':
1137 # Nuke the pushback stack
1138 del lookaheadstack[:]
1141 # case 2: the statestack has a couple of entries on it, but we're
1142 # at the end of the file. nuke the top entry and generate an error token
1144 # Start nuking entries on the stack
1145 if lookahead.type == '$end':
1146 # Whoa. We're really hosed here. Bail out
1149 if lookahead.type != 'error':
1151 if sym.type == 'error':
1152 # Hmmm. Error is on top of stack, we'll just nuke input
1153 # symbol and continue
1158 if hasattr(lookahead,"lineno"):
1159 t.lineno = lookahead.lineno
1160 if hasattr(lookahead,"lexpos"):
1161 t.lexpos = lookahead.lexpos
1163 lookaheadstack.append(lookahead)
1168 state = statestack[-1] # Potential bug fix
1172 # Call an error function here
1173 raise RuntimeError("yacc: internal parser error!!!\n")
1175 # -----------------------------------------------------------------------------
1176 # === Grammar Representation ===
1178 # The following functions, classes, and variables are used to represent and
1179 # manipulate the rules that make up a grammar.
1180 # -----------------------------------------------------------------------------
1184 # regex matching identifiers
1185 _is_identifier = re.compile(r'^[a-zA-Z0-9_-]+$')
1187 # -----------------------------------------------------------------------------
1190 # This class stores the raw information about a single production or grammar rule.
1191 # A grammar rule refers to a specification such as this:
1193 # expr : expr PLUS term
1195 # Here are the basic attributes defined on all productions
1197 # name - Name of the production. For example 'expr'
1198 # prod - A list of symbols on the right side ['expr','PLUS','term']
1199 # prec - Production precedence level
1200 # number - Production number.
1201 # func - Function that executes on reduce
1202 # file - File where production function is defined
1203 # lineno - Line number where production function is defined
1205 # The following attributes are defined or optional.
1207 # len - Length of the production (number of symbols on right hand side)
1208 # usyms - Set of unique symbols found in the production
1209 # -----------------------------------------------------------------------------
1211 class Production(object):
1213 def __init__(self,number,name,prod,precedence=('right',0),func=None,file='',line=0):
1215 self.prod = tuple(prod)
1216 self.number = number
1218 self.callable = None
1221 self.prec = precedence
1223 # Internal settings used during table construction
1225 self.len = len(self.prod) # Length of the production
1227 # Create a list of unique production symbols used in the production
1230 if s not in self.usyms:
1231 self.usyms.append(s)
1233 # List of all LR items for the production
1237 # Create a string representation
1239 self.str = "%s -> %s" % (self.name," ".join(self.prod))
1241 self.str = "%s -> <empty>" % self.name
1247 return "Production("+str(self)+")"
1250 return len(self.prod)
1252 def __nonzero__(self):
1255 def __getitem__(self,index):
1256 return self.prod[index]
1258 # Return the nth lr_item from the production (or None if at the end)
1259 def lr_item(self,n):
1260 if n > len(self.prod): return None
1263 # Precompute the list of productions immediately following. Hack. Remove later
1265 p.lr_after = Prodnames[p.prod[n+1]]
1266 except (IndexError,KeyError):
1269 p.lr_before = p.prod[n-1]
1275 # Bind the production function name to a callable
1276 def bind(self,pdict):
1278 self.callable = pdict[self.func]
1280 # This class serves as a minimal standin for Production objects when
1281 # reading table data from files. It only contains information
1282 # actually used by the LR parsing engine, plus some additional
1283 # debugging information.
1284 class MiniProduction(object):
1285 def __init__(self,str,name,len,func,file,line):
1289 self.callable = None
1296 return "MiniProduction(%s)" % self.str
1298 # Bind the production function name to a callable
1299 def bind(self,pdict):
1301 self.callable = pdict[self.func]
1304 # -----------------------------------------------------------------------------
1307 # This class represents a specific stage of parsing a production rule. For
1310 # expr : expr . PLUS term
1312 # In the above, the "." represents the current location of the parse. Here
1315 # name - Name of the production. For example 'expr'
1316 # prod - A list of symbols on the right side ['expr','.', 'PLUS','term']
1317 # number - Production number.
1319 # lr_next Next LR item. Example, if we are ' expr -> expr . PLUS term'
1320 # then lr_next refers to 'expr -> expr PLUS . term'
1321 # lr_index - LR item index (location of the ".") in the prod list.
1322 # lookaheads - LALR lookahead symbols for this item
1323 # len - Length of the production (number of symbols on right hand side)
1324 # lr_after - List of all productions that immediately follow
1325 # lr_before - Grammar symbol immediately before
1326 # -----------------------------------------------------------------------------
1328 class LRItem(object):
1329 def __init__(self,p,n):
1331 self.prod = list(p.prod)
1332 self.number = p.number
1334 self.lookaheads = { }
1335 self.prod.insert(n,".")
1336 self.prod = tuple(self.prod)
1337 self.len = len(self.prod)
1338 self.usyms = p.usyms
1342 s = "%s -> %s" % (self.name," ".join(self.prod))
1344 s = "%s -> <empty>" % self.name
1348 return "LRItem("+str(self)+")"
1350 # -----------------------------------------------------------------------------
1351 # rightmost_terminal()
1353 # Return the rightmost terminal from a list of symbols. Used in add_production()
1354 # -----------------------------------------------------------------------------
1355 def rightmost_terminal(symbols, terminals):
1356 i = len(symbols) - 1
1358 if symbols[i] in terminals:
1363 # -----------------------------------------------------------------------------
1364 # === GRAMMAR CLASS ===
1366 # The following class represents the contents of the specified grammar along
1367 # with various computed properties such as first sets, follow sets, LR items, etc.
1368 # This data is used for critical parts of the table generation process later.
1369 # -----------------------------------------------------------------------------
1371 class GrammarError(YaccError): pass
1373 class Grammar(object):
1374 def __init__(self,terminals):
1375 self.Productions = [None] # A list of all of the productions. The first
1376 # entry is always reserved for the purpose of
1377 # building an augmented grammar
1379 self.Prodnames = { } # A dictionary mapping the names of nonterminals to a list of all
1380 # productions of that nonterminal.
1382 self.Prodmap = { } # A dictionary that is only used to detect duplicate
1385 self.Terminals = { } # A dictionary mapping the names of terminal symbols to a
1386 # list of the rules where they are used.
1388 for term in terminals:
1389 self.Terminals[term] = []
1391 self.Terminals['error'] = []
1393 self.Nonterminals = { } # A dictionary mapping names of nonterminals to a list
1394 # of rule numbers where they are used.
1396 self.First = { } # A dictionary of precomputed FIRST(x) symbols
1398 self.Follow = { } # A dictionary of precomputed FOLLOW(x) symbols
1400 self.Precedence = { } # Precedence rules for each terminal. Contains tuples of the
1401 # form ('right',level) or ('nonassoc', level) or ('left',level)
1403 self.UsedPrecedence = { } # Precedence rules that were actually used by the grammer.
1404 # This is only used to provide error checking and to generate
1405 # a warning about unused precedence rules.
1407 self.Start = None # Starting symbol for the grammar
1411 return len(self.Productions)
1413 def __getitem__(self,index):
1414 return self.Productions[index]
1416 # -----------------------------------------------------------------------------
1419 # Sets the precedence for a given terminal. assoc is the associativity such as
1420 # 'left','right', or 'nonassoc'. level is a numeric level.
1422 # -----------------------------------------------------------------------------
1424 def set_precedence(self,term,assoc,level):
1425 assert self.Productions == [None],"Must call set_precedence() before add_production()"
1426 if term in self.Precedence:
1427 raise GrammarError("Precedence already specified for terminal %r" % term)
1428 if assoc not in ['left','right','nonassoc']:
1429 raise GrammarError("Associativity must be one of 'left','right', or 'nonassoc'")
1430 self.Precedence[term] = (assoc,level)
1432 # -----------------------------------------------------------------------------
1435 # Given an action function, this function assembles a production rule and
1436 # computes its precedence level.
1438 # The production rule is supplied as a list of symbols. For example,
1439 # a rule such as 'expr : expr PLUS term' has a production name of 'expr' and
1440 # symbols ['expr','PLUS','term'].
1442 # Precedence is determined by the precedence of the right-most non-terminal
1443 # or the precedence of a terminal specified by %prec.
1445 # A variety of error checks are performed to make sure production symbols
1446 # are valid and that %prec is used correctly.
1447 # -----------------------------------------------------------------------------
1449 def add_production(self,prodname,syms,func=None,file='',line=0):
1451 if prodname in self.Terminals:
1452 raise GrammarError("%s:%d: Illegal rule name %r. Already defined as a token" % (file,line,prodname))
1453 if prodname == 'error':
1454 raise GrammarError("%s:%d: Illegal rule name %r. error is a reserved word" % (file,line,prodname))
1455 if not _is_identifier.match(prodname):
1456 raise GrammarError("%s:%d: Illegal rule name %r" % (file,line,prodname))
1458 # Look for literal tokens
1459 for n,s in enumerate(syms):
1464 raise GrammarError("%s:%d: Literal token %s in rule %r may only be a single character" % (file,line,s, prodname))
1465 if not c in self.Terminals:
1466 self.Terminals[c] = []
1471 if not _is_identifier.match(s) and s != '%prec':
1472 raise GrammarError("%s:%d: Illegal name %r in rule %r" % (file,line,s, prodname))
1474 # Determine the precedence level
1476 if syms[-1] == '%prec':
1477 raise GrammarError("%s:%d: Syntax error. Nothing follows %%prec" % (file,line))
1478 if syms[-2] != '%prec':
1479 raise GrammarError("%s:%d: Syntax error. %%prec can only appear at the end of a grammar rule" % (file,line))
1481 prodprec = self.Precedence.get(precname)
1483 raise GrammarError("%s:%d: Nothing known about the precedence of %r" % (file,line,precname))
1485 self.UsedPrecedence[precname] = 1
1486 del syms[-2:] # Drop %prec from the rule
1488 # If no %prec, precedence is determined by the rightmost terminal symbol
1489 precname = rightmost_terminal(syms,self.Terminals)
1490 prodprec = self.Precedence.get(precname,('right',0))
1492 # See if the rule is already in the rulemap
1493 map = "%s -> %s" % (prodname,syms)
1494 if map in self.Prodmap:
1495 m = self.Prodmap[map]
1496 raise GrammarError("%s:%d: Duplicate rule %s. " % (file,line, m) +
1497 "Previous definition at %s:%d" % (m.file, m.line))
1499 # From this point on, everything is valid. Create a new Production instance
1500 pnumber = len(self.Productions)
1501 if not prodname in self.Nonterminals:
1502 self.Nonterminals[prodname] = [ ]
1504 # Add the production number to Terminals and Nonterminals
1506 if t in self.Terminals:
1507 self.Terminals[t].append(pnumber)
1509 if not t in self.Nonterminals:
1510 self.Nonterminals[t] = [ ]
1511 self.Nonterminals[t].append(pnumber)
1513 # Create a production and add it to the list of productions
1514 p = Production(pnumber,prodname,syms,prodprec,func,file,line)
1515 self.Productions.append(p)
1516 self.Prodmap[map] = p
1518 # Add to the global productions list
1520 self.Prodnames[prodname].append(p)
1522 self.Prodnames[prodname] = [ p ]
1525 # -----------------------------------------------------------------------------
1528 # Sets the starting symbol and creates the augmented grammar. Production
1529 # rule 0 is S' -> start where start is the start symbol.
1530 # -----------------------------------------------------------------------------
1532 def set_start(self,start=None):
1534 start = self.Productions[1].name
1535 if start not in self.Nonterminals:
1536 raise GrammarError("start symbol %s undefined" % start)
1537 self.Productions[0] = Production(0,"S'",[start])
1538 self.Nonterminals[start].append(0)
1541 # -----------------------------------------------------------------------------
1542 # find_unreachable()
1544 # Find all of the nonterminal symbols that can't be reached from the starting
1545 # symbol. Returns a list of nonterminals that can't be reached.
1546 # -----------------------------------------------------------------------------
1548 def find_unreachable(self):
1550 # Mark all symbols that are reachable from a symbol s
1551 def mark_reachable_from(s):
1553 # We've already reached symbol s.
1556 for p in self.Prodnames.get(s,[]):
1558 mark_reachable_from(r)
1561 for s in list(self.Terminals) + list(self.Nonterminals):
1564 mark_reachable_from( self.Productions[0].prod[0] )
1566 return [s for s in list(self.Nonterminals)
1567 if not reachable[s]]
1569 # -----------------------------------------------------------------------------
1572 # This function looks at the various parsing rules and tries to detect
1573 # infinite recursion cycles (grammar rules where there is no possible way
1574 # to derive a string of only terminals).
1575 # -----------------------------------------------------------------------------
1577 def infinite_cycles(self):
1581 for t in self.Terminals:
1584 terminates['$end'] = 1
1588 # Initialize to false:
1589 for n in self.Nonterminals:
1592 # Then propagate termination until no change:
1595 for (n,pl) in self.Prodnames.items():
1596 # Nonterminal n terminates iff any of its productions terminates.
1598 # Production p terminates iff all of its rhs symbols terminate.
1600 if not terminates[s]:
1601 # The symbol s does not terminate,
1602 # so production p does not terminate.
1606 # didn't break from the loop,
1607 # so every symbol s terminates
1608 # so production p terminates.
1612 # symbol n terminates!
1613 if not terminates[n]:
1616 # Don't need to consider any more productions for this n.
1623 for (s,term) in terminates.items():
1625 if not s in self.Prodnames and not s in self.Terminals and s != 'error':
1626 # s is used-but-not-defined, and we've already warned of that,
1627 # so it would be overkill to say that it's also non-terminating.
1635 # -----------------------------------------------------------------------------
1636 # undefined_symbols()
1638 # Find all symbols that were used the grammar, but not defined as tokens or
1639 # grammar rules. Returns a list of tuples (sym, prod) where sym in the symbol
1640 # and prod is the production where the symbol was used.
1641 # -----------------------------------------------------------------------------
1642 def undefined_symbols(self):
1644 for p in self.Productions:
1648 if not s in self.Prodnames and not s in self.Terminals and s != 'error':
1649 result.append((s,p))
1652 # -----------------------------------------------------------------------------
1653 # unused_terminals()
1655 # Find all terminals that were defined, but not used by the grammar. Returns
1656 # a list of all symbols.
1657 # -----------------------------------------------------------------------------
1658 def unused_terminals(self):
1660 for s,v in self.Terminals.items():
1661 if s != 'error' and not v:
1662 unused_tok.append(s)
1666 # ------------------------------------------------------------------------------
1669 # Find all grammar rules that were defined, but not used (maybe not reachable)
1670 # Returns a list of productions.
1671 # ------------------------------------------------------------------------------
1673 def unused_rules(self):
1675 for s,v in self.Nonterminals.items():
1677 p = self.Prodnames[s][0]
1678 unused_prod.append(p)
1681 # -----------------------------------------------------------------------------
1682 # unused_precedence()
1684 # Returns a list of tuples (term,precedence) corresponding to precedence
1685 # rules that were never used by the grammar. term is the name of the terminal
1686 # on which precedence was applied and precedence is a string such as 'left' or
1687 # 'right' corresponding to the type of precedence.
1688 # -----------------------------------------------------------------------------
1690 def unused_precedence(self):
1692 for termname in self.Precedence:
1693 if not (termname in self.Terminals or termname in self.UsedPrecedence):
1694 unused.append((termname,self.Precedence[termname][0]))
1698 # -------------------------------------------------------------------------
1701 # Compute the value of FIRST1(beta) where beta is a tuple of symbols.
1703 # During execution of compute_first1, the result may be incomplete.
1704 # Afterward (e.g., when called from compute_follow()), it will be complete.
1705 # -------------------------------------------------------------------------
1706 def _first(self,beta):
1708 # We are computing First(x1,x2,x3,...,xn)
1711 x_produces_empty = 0
1713 # Add all the non-<empty> symbols of First[x] to the result.
1714 for f in self.First[x]:
1716 x_produces_empty = 1
1718 if f not in result: result.append(f)
1720 if x_produces_empty:
1721 # We have to consider the next x in beta,
1722 # i.e. stay in the loop.
1725 # We don't have to consider any further symbols in beta.
1728 # There was no 'break' from the loop,
1729 # so x_produces_empty was true for all x in beta,
1730 # so beta produces empty as well.
1731 result.append('<empty>')
1735 # -------------------------------------------------------------------------
1738 # Compute the value of FIRST1(X) for all symbols
1739 # -------------------------------------------------------------------------
1740 def compute_first(self):
1745 for t in self.Terminals:
1748 self.First['$end'] = ['$end']
1752 # Initialize to the empty set:
1753 for n in self.Nonterminals:
1756 # Then propagate symbols until no change:
1759 for n in self.Nonterminals:
1760 for p in self.Prodnames[n]:
1761 for f in self._first(p.prod):
1762 if f not in self.First[n]:
1763 self.First[n].append( f )
1770 # ---------------------------------------------------------------------
1773 # Computes all of the follow sets for every non-terminal symbol. The
1774 # follow set is the set of all symbols that might follow a given
1775 # non-terminal. See the Dragon book, 2nd Ed. p. 189.
1776 # ---------------------------------------------------------------------
1777 def compute_follow(self,start=None):
1778 # If already computed, return the result
1782 # If first sets not computed yet, do that first.
1784 self.compute_first()
1786 # Add '$end' to the follow list of the start symbol
1787 for k in self.Nonterminals:
1788 self.Follow[k] = [ ]
1791 start = self.Productions[1].name
1793 self.Follow[start] = [ '$end' ]
1797 for p in self.Productions[1:]:
1798 # Here is the production set
1799 for i in range(len(p.prod)):
1801 if B in self.Nonterminals:
1802 # Okay. We got a non-terminal in a production
1803 fst = self._first(p.prod[i+1:])
1806 if f != '<empty>' and f not in self.Follow[B]:
1807 self.Follow[B].append(f)
1811 if hasempty or i == (len(p.prod)-1):
1812 # Add elements of follow(a) to follow(b)
1813 for f in self.Follow[p.name]:
1814 if f not in self.Follow[B]:
1815 self.Follow[B].append(f)
1817 if not didadd: break
1821 # -----------------------------------------------------------------------------
1824 # This function walks the list of productions and builds a complete set of the
1825 # LR items. The LR items are stored in two ways: First, they are uniquely
1826 # numbered and placed in the list _lritems. Second, a linked list of LR items
1827 # is built for each production. For example:
1833 # [E -> . E PLUS E, E -> E . PLUS E, E -> E PLUS . E, E -> E PLUS E . ]
1834 # -----------------------------------------------------------------------------
1836 def build_lritems(self):
1837 for p in self.Productions:
1846 # Precompute the list of productions immediately following
1848 lri.lr_after = self.Prodnames[lri.prod[i+1]]
1849 except (IndexError,KeyError):
1852 lri.lr_before = lri.prod[i-1]
1854 lri.lr_before = None
1856 lastlri.lr_next = lri
1858 lr_items.append(lri)
1861 p.lr_items = lr_items
1863 # -----------------------------------------------------------------------------
1864 # == Class LRTable ==
1866 # This basic class represents a basic table of LR parsing information.
1867 # Methods for generating the tables are not defined here. They are defined
1868 # in the derived class LRGeneratedTable.
1869 # -----------------------------------------------------------------------------
1871 class VersionError(YaccError): pass
1873 class LRTable(object):
1875 self.lr_action = None
1877 self.lr_productions = None
1878 self.lr_method = None
1880 def read_table(self,module):
1881 if isinstance(module,types.ModuleType):
1884 if sys.version_info[0] < 3:
1885 exec("import %s as parsetab" % module)
1888 exec("import %s as parsetab" % module, env, env)
1889 parsetab = env['parsetab']
1891 if parsetab._tabversion != __tabversion__:
1892 raise VersionError("yacc table file version is out of date")
1894 self.lr_action = parsetab._lr_action
1895 self.lr_goto = parsetab._lr_goto
1897 self.lr_productions = []
1898 for p in parsetab._lr_productions:
1899 self.lr_productions.append(MiniProduction(*p))
1901 self.lr_method = parsetab._lr_method
1902 return parsetab._lr_signature
1904 def read_pickle(self,filename):
1906 import cPickle as pickle
1910 in_f = open(filename,"rb")
1912 tabversion = pickle.load(in_f)
1913 if tabversion != __tabversion__:
1914 raise VersionError("yacc table file version is out of date")
1915 self.lr_method = pickle.load(in_f)
1916 signature = pickle.load(in_f)
1917 self.lr_action = pickle.load(in_f)
1918 self.lr_goto = pickle.load(in_f)
1919 productions = pickle.load(in_f)
1921 self.lr_productions = []
1922 for p in productions:
1923 self.lr_productions.append(MiniProduction(*p))
1928 # Bind all production function names to callable objects in pdict
1929 def bind_callables(self,pdict):
1930 for p in self.lr_productions:
1933 # -----------------------------------------------------------------------------
1934 # === LR Generator ===
1936 # The following classes and functions are used to generate LR parsing tables on
1938 # -----------------------------------------------------------------------------
1940 # -----------------------------------------------------------------------------
1944 # The following two functions are used to compute set valued functions
1947 # F(x) = F'(x) U U{F(y) | x R y}
1949 # This is used to compute the values of Read() sets as well as FOLLOW sets
1950 # in LALR(1) generation.
1952 # Inputs: X - An input set
1954 # FP - Set-valued function
1955 # ------------------------------------------------------------------------------
1957 def digraph(X,R,FP):
1964 if N[x] == 0: traverse(x,N,stack,F,X,R,FP)
1967 def traverse(x,N,stack,F,X,R,FP):
1971 F[x] = FP(x) # F(X) <- F'(x)
1973 rel = R(x) # Get y's related to x
1976 traverse(y,N,stack,F,X,R,FP)
1977 N[x] = min(N[x],N[y])
1978 for a in F.get(y,[]):
1979 if a not in F[x]: F[x].append(a)
1981 N[stack[-1]] = MAXINT
1983 element = stack.pop()
1985 N[stack[-1]] = MAXINT
1987 element = stack.pop()
1989 class LALRError(YaccError): pass
1991 # -----------------------------------------------------------------------------
1992 # == LRGeneratedTable ==
1994 # This class implements the LR table generation algorithm. There are no
1995 # public methods except for write()
1996 # -----------------------------------------------------------------------------
1998 class LRGeneratedTable(LRTable):
1999 def __init__(self,grammar,method='LALR',log=None):
2000 if method not in ['SLR','LALR']:
2001 raise LALRError("Unsupported method %s" % method)
2003 self.grammar = grammar
2004 self.lr_method = method
2011 # Internal attributes
2012 self.lr_action = {} # Action table
2013 self.lr_goto = {} # Goto table
2014 self.lr_productions = grammar.Productions # Copy of grammar Production array
2015 self.lr_goto_cache = {} # Cache of computed gotos
2016 self.lr0_cidhash = {} # Cache of closures
2018 self._add_count = 0 # Internal counter used to detect cycles
2020 # Diagonistic information filled in by the table generator
2021 self.sr_conflict = 0
2022 self.rr_conflict = 0
2023 self.conflicts = [] # List of conflicts
2025 self.sr_conflicts = []
2026 self.rr_conflicts = []
2029 self.grammar.build_lritems()
2030 self.grammar.compute_first()
2031 self.grammar.compute_follow()
2032 self.lr_parse_table()
2034 # Compute the LR(0) closure operation on I, where I is a set of LR(0) items.
2036 def lr0_closure(self,I):
2037 self._add_count += 1
2039 # Add everything in I to J
2045 for x in j.lr_after:
2046 if getattr(x,"lr0_added",0) == self._add_count: continue
2049 x.lr0_added = self._add_count
2054 # Compute the LR(0) goto function goto(I,X) where I is a set
2055 # of LR(0) items and X is a grammar symbol. This function is written
2056 # in a way that guarantees uniqueness of the generated goto sets
2057 # (i.e. the same goto set will never be returned as two different Python
2058 # objects). With uniqueness, we can later do fast set comparisons using
2059 # id(obj) instead of element-wise comparison.
2061 def lr0_goto(self,I,x):
2062 # First we look for a previously cached entry
2063 g = self.lr_goto_cache.get((id(I),x))
2066 # Now we generate the goto set in a way that guarantees uniqueness
2069 s = self.lr_goto_cache.get(x)
2072 self.lr_goto_cache[x] = s
2077 if n and n.lr_before == x:
2087 g = self.lr0_closure(gs)
2091 self.lr_goto_cache[(id(I),x)] = g
2094 # Compute the LR(0) sets of item function
2095 def lr0_items(self):
2097 C = [ self.lr0_closure([self.grammar.Productions[0].lr_next]) ]
2100 self.lr0_cidhash[id(I)] = i
2103 # Loop over the items in C and each grammar symbols
2109 # Collect all of the symbols that could possibly be in the goto(I,X) sets
2116 g = self.lr0_goto(I,x)
2118 if id(g) in self.lr0_cidhash: continue
2119 self.lr0_cidhash[id(g)] = len(C)
2124 # -----------------------------------------------------------------------------
2125 # ==== LALR(1) Parsing ====
2127 # LALR(1) parsing is almost exactly the same as SLR except that instead of
2128 # relying upon Follow() sets when performing reductions, a more selective
2129 # lookahead set that incorporates the state of the LR(0) machine is utilized.
2130 # Thus, we mainly just have to focus on calculating the lookahead sets.
2132 # The method used here is due to DeRemer and Pennelo (1982).
2134 # DeRemer, F. L., and T. J. Pennelo: "Efficient Computation of LALR(1)
2135 # Lookahead Sets", ACM Transactions on Programming Languages and Systems,
2136 # Vol. 4, No. 4, Oct. 1982, pp. 615-649
2138 # Further details can also be found in:
2140 # J. Tremblay and P. Sorenson, "The Theory and Practice of Compiler Writing",
2141 # McGraw-Hill Book Company, (1985).
2143 # -----------------------------------------------------------------------------
2145 # -----------------------------------------------------------------------------
2146 # compute_nullable_nonterminals()
2148 # Creates a dictionary containing all of the non-terminals that might produce
2149 # an empty production.
2150 # -----------------------------------------------------------------------------
2152 def compute_nullable_nonterminals(self):
2156 for p in self.grammar.Productions[1:]:
2158 nullable[p.name] = 1
2161 if not t in nullable: break
2163 nullable[p.name] = 1
2164 if len(nullable) == num_nullable: break
2165 num_nullable = len(nullable)
2168 # -----------------------------------------------------------------------------
2169 # find_nonterminal_trans(C)
2171 # Given a set of LR(0) items, this functions finds all of the non-terminal
2172 # transitions. These are transitions in which a dot appears immediately before
2173 # a non-terminal. Returns a list of tuples of the form (state,N) where state
2174 # is the state number and N is the nonterminal symbol.
2176 # The input C is the set of LR(0) items.
2177 # -----------------------------------------------------------------------------
2179 def find_nonterminal_transitions(self,C):
2181 for state in range(len(C)):
2183 if p.lr_index < p.len - 1:
2184 t = (state,p.prod[p.lr_index+1])
2185 if t[1] in self.grammar.Nonterminals:
2186 if t not in trans: trans.append(t)
2190 # -----------------------------------------------------------------------------
2193 # Computes the DR(p,A) relationships for non-terminal transitions. The input
2194 # is a tuple (state,N) where state is a number and N is a nonterminal symbol.
2196 # Returns a list of terminals.
2197 # -----------------------------------------------------------------------------
2199 def dr_relation(self,C,trans,nullable):
2204 g = self.lr0_goto(C[state],N)
2206 if p.lr_index < p.len - 1:
2207 a = p.prod[p.lr_index+1]
2208 if a in self.grammar.Terminals:
2209 if a not in terms: terms.append(a)
2211 # This extra bit is to handle the start state
2212 if state == 0 and N == self.grammar.Productions[0].prod[0]:
2213 terms.append('$end')
2217 # -----------------------------------------------------------------------------
2220 # Computes the READS() relation (p,A) READS (t,C).
2221 # -----------------------------------------------------------------------------
2223 def reads_relation(self,C, trans, empty):
2224 # Look for empty transitions
2228 g = self.lr0_goto(C[state],N)
2229 j = self.lr0_cidhash.get(id(g),-1)
2231 if p.lr_index < p.len - 1:
2232 a = p.prod[p.lr_index + 1]
2238 # -----------------------------------------------------------------------------
2239 # compute_lookback_includes()
2241 # Determines the lookback and includes relations
2245 # This relation is determined by running the LR(0) state machine forward.
2246 # For example, starting with a production "N : . A B C", we run it forward
2247 # to obtain "N : A B C ." We then build a relationship between this final
2248 # state and the starting state. These relationships are stored in a dictionary
2253 # Computes the INCLUDE() relation (p,A) INCLUDES (p',B).
2255 # This relation is used to determine non-terminal transitions that occur
2256 # inside of other non-terminal transition states. (p,A) INCLUDES (p', B)
2257 # if the following holds:
2259 # B -> LAT, where T -> epsilon and p' -L-> p
2261 # L is essentially a prefix (which may be empty), T is a suffix that must be
2262 # able to derive an empty string. State p' must lead to state p with the string L.
2264 # -----------------------------------------------------------------------------
2266 def compute_lookback_includes(self,C,trans,nullable):
2268 lookdict = {} # Dictionary of lookback relations
2269 includedict = {} # Dictionary of include relations
2271 # Make a dictionary of non-terminal transitions
2276 # Loop over all transitions and compute lookbacks and includes
2277 for state,N in trans:
2281 if p.name != N: continue
2283 # Okay, we have a name match. We now follow the production all the way
2284 # through the state machine until we get the . on the right hand side
2286 lr_index = p.lr_index
2288 while lr_index < p.len - 1:
2289 lr_index = lr_index + 1
2290 t = p.prod[lr_index]
2292 # Check to see if this symbol and state are a non-terminal transition
2294 # Yes. Okay, there is some chance that this is an includes relation
2295 # the only way to know for certain is whether the rest of the
2296 # production derives empty
2300 if p.prod[li] in self.grammar.Terminals: break # No forget it
2301 if not p.prod[li] in nullable: break
2304 # Appears to be a relation between (j,t) and (state,N)
2305 includes.append((j,t))
2307 g = self.lr0_goto(C[j],t) # Go to next set
2308 j = self.lr0_cidhash.get(id(g),-1) # Go to next state
2310 # When we get here, j is the final state, now we have to locate the production
2312 if r.name != p.name: continue
2313 if r.len != p.len: continue
2315 # This look is comparing a production ". A B C" with "A B C ."
2316 while i < r.lr_index:
2317 if r.prod[i] != p.prod[i+1]: break
2322 if not i in includedict: includedict[i] = []
2323 includedict[i].append((state,N))
2324 lookdict[(state,N)] = lookb
2326 return lookdict,includedict
2328 # -----------------------------------------------------------------------------
2329 # compute_read_sets()
2331 # Given a set of LR(0) items, this function computes the read sets.
2333 # Inputs: C = Set of LR(0) items
2334 # ntrans = Set of nonterminal transitions
2335 # nullable = Set of empty transitions
2337 # Returns a set containing the read sets
2338 # -----------------------------------------------------------------------------
2340 def compute_read_sets(self,C, ntrans, nullable):
2341 FP = lambda x: self.dr_relation(C,x,nullable)
2342 R = lambda x: self.reads_relation(C,x,nullable)
2343 F = digraph(ntrans,R,FP)
2346 # -----------------------------------------------------------------------------
2347 # compute_follow_sets()
2349 # Given a set of LR(0) items, a set of non-terminal transitions, a readset,
2350 # and an include set, this function computes the follow sets
2352 # Follow(p,A) = Read(p,A) U U {Follow(p',B) | (p,A) INCLUDES (p',B)}
2355 # ntrans = Set of nonterminal transitions
2356 # readsets = Readset (previously computed)
2357 # inclsets = Include sets (previously computed)
2359 # Returns a set containing the follow sets
2360 # -----------------------------------------------------------------------------
2362 def compute_follow_sets(self,ntrans,readsets,inclsets):
2363 FP = lambda x: readsets[x]
2364 R = lambda x: inclsets.get(x,[])
2365 F = digraph(ntrans,R,FP)
2368 # -----------------------------------------------------------------------------
2371 # Attaches the lookahead symbols to grammar rules.
2373 # Inputs: lookbacks - Set of lookback relations
2374 # followset - Computed follow set
2376 # This function directly attaches the lookaheads to productions contained
2377 # in the lookbacks set
2378 # -----------------------------------------------------------------------------
2380 def add_lookaheads(self,lookbacks,followset):
2381 for trans,lb in lookbacks.items():
2382 # Loop over productions in lookback
2384 if not state in p.lookaheads:
2385 p.lookaheads[state] = []
2386 f = followset.get(trans,[])
2388 if a not in p.lookaheads[state]: p.lookaheads[state].append(a)
2390 # -----------------------------------------------------------------------------
2391 # add_lalr_lookaheads()
2393 # This function does all of the work of adding lookahead information for use
2395 # -----------------------------------------------------------------------------
2397 def add_lalr_lookaheads(self,C):
2398 # Determine all of the nullable nonterminals
2399 nullable = self.compute_nullable_nonterminals()
2401 # Find all non-terminal transitions
2402 trans = self.find_nonterminal_transitions(C)
2405 readsets = self.compute_read_sets(C,trans,nullable)
2407 # Compute lookback/includes relations
2408 lookd, included = self.compute_lookback_includes(C,trans,nullable)
2410 # Compute LALR FOLLOW sets
2411 followsets = self.compute_follow_sets(trans,readsets,included)
2413 # Add all of the lookaheads
2414 self.add_lookaheads(lookd,followsets)
2416 # -----------------------------------------------------------------------------
2419 # This function constructs the parse tables for SLR or LALR
2420 # -----------------------------------------------------------------------------
2421 def lr_parse_table(self):
2422 Productions = self.grammar.Productions
2423 Precedence = self.grammar.Precedence
2424 goto = self.lr_goto # Goto array
2425 action = self.lr_action # Action array
2426 log = self.log # Logger for output
2428 actionp = { } # Action production array (temporary)
2430 log.info("Parsing method: %s", self.lr_method)
2432 # Step 1: Construct C = { I0, I1, ... IN}, collection of LR(0) items
2433 # This determines the number of states
2435 C = self.lr0_items()
2437 if self.lr_method == 'LALR':
2438 self.add_lalr_lookaheads(C)
2440 # Build the parser table, state by state
2443 # Loop over each production in I
2444 actlist = [ ] # List of actions
2449 log.info("state %d", st)
2452 log.info(" (%d) %s", p.number, str(p))
2456 if p.len == p.lr_index + 1:
2458 # Start symbol. Accept!
2459 st_action["$end"] = 0
2460 st_actionp["$end"] = p
2462 # We are at the end of a production. Reduce!
2463 if self.lr_method == 'LALR':
2464 laheads = p.lookaheads[st]
2466 laheads = self.grammar.Follow[p.name]
2468 actlist.append((a,p,"reduce using rule %d (%s)" % (p.number,p)))
2469 r = st_action.get(a)
2471 # Whoa. Have a shift/reduce or reduce/reduce conflict
2473 # Need to decide on shift or reduce here
2474 # By default we favor shifting. Need to add
2475 # some precedence rules here.
2476 sprec,slevel = Productions[st_actionp[a].number].prec
2477 rprec,rlevel = Precedence.get(a,('right',0))
2478 if (slevel < rlevel) or ((slevel == rlevel) and (rprec == 'left')):
2479 # We really need to reduce here.
2480 st_action[a] = -p.number
2482 if not slevel and not rlevel:
2483 log.info(" ! shift/reduce conflict for %s resolved as reduce",a)
2484 self.sr_conflicts.append((st,a,'reduce'))
2485 Productions[p.number].reduced += 1
2486 elif (slevel == rlevel) and (rprec == 'nonassoc'):
2489 # Hmmm. Guess we'll keep the shift
2491 log.info(" ! shift/reduce conflict for %s resolved as shift",a)
2492 self.sr_conflicts.append((st,a,'shift'))
2494 # Reduce/reduce conflict. In this case, we favor the rule
2495 # that was defined first in the grammar file
2496 oldp = Productions[-r]
2497 pp = Productions[p.number]
2498 if oldp.line > pp.line:
2499 st_action[a] = -p.number
2501 chosenp,rejectp = pp,oldp
2502 Productions[p.number].reduced += 1
2503 Productions[oldp.number].reduced -= 1
2505 chosenp,rejectp = oldp,pp
2506 self.rr_conflicts.append((st,chosenp,rejectp))
2507 log.info(" ! reduce/reduce conflict for %s resolved using rule %d (%s)", a,st_actionp[a].number, st_actionp[a])
2509 raise LALRError("Unknown conflict in state %d" % st)
2511 st_action[a] = -p.number
2513 Productions[p.number].reduced += 1
2516 a = p.prod[i+1] # Get symbol right after the "."
2517 if a in self.grammar.Terminals:
2518 g = self.lr0_goto(I,a)
2519 j = self.lr0_cidhash.get(id(g),-1)
2521 # We are in a shift state
2522 actlist.append((a,p,"shift and go to state %d" % j))
2523 r = st_action.get(a)
2525 # Whoa have a shift/reduce or shift/shift conflict
2528 raise LALRError("Shift/shift conflict in state %d" % st)
2530 # Do a precedence check.
2531 # - if precedence of reduce rule is higher, we reduce.
2532 # - if precedence of reduce is same and left assoc, we reduce.
2533 # - otherwise we shift
2534 rprec,rlevel = Productions[st_actionp[a].number].prec
2535 sprec,slevel = Precedence.get(a,('right',0))
2536 if (slevel > rlevel) or ((slevel == rlevel) and (rprec == 'right')):
2537 # We decide to shift here... highest precedence to shift
2538 Productions[st_actionp[a].number].reduced -= 1
2542 log.info(" ! shift/reduce conflict for %s resolved as shift",a)
2543 self.sr_conflicts.append((st,a,'shift'))
2544 elif (slevel == rlevel) and (rprec == 'nonassoc'):
2547 # Hmmm. Guess we'll keep the reduce
2548 if not slevel and not rlevel:
2549 log.info(" ! shift/reduce conflict for %s resolved as reduce",a)
2550 self.sr_conflicts.append((st,a,'reduce'))
2553 raise LALRError("Unknown conflict in state %d" % st)
2558 # Print the actions associated with each terminal
2560 for a,p,m in actlist:
2562 if p is st_actionp[a]:
2563 log.info(" %-15s %s",a,m)
2564 _actprint[(a,m)] = 1
2566 # Print the actions that were not used. (debugging)
2568 for a,p,m in actlist:
2570 if p is not st_actionp[a]:
2571 if not (a,m) in _actprint:
2572 log.debug(" ! %-15s [ %s ]",a,m)
2574 _actprint[(a,m)] = 1
2578 # Construct the goto table for this state
2583 if s in self.grammar.Nonterminals:
2586 g = self.lr0_goto(I,n)
2587 j = self.lr0_cidhash.get(id(g),-1)
2590 log.info(" %-30s shift and go to state %d",n,j)
2592 action[st] = st_action
2593 actionp[st] = st_actionp
2598 # -----------------------------------------------------------------------------
2601 # This function writes the LR parsing tables to a file
2602 # -----------------------------------------------------------------------------
2604 def write_table(self,modulename,outputdir='',signature=""):
2605 basemodulename = modulename.split(".")[-1]
2606 filename = os.path.join(outputdir,basemodulename) + ".py"
2608 f = open(filename,"w")
2612 # This file is automatically generated. Do not edit.
2618 """ % (filename, __tabversion__, self.lr_method, signature))
2620 # Change smaller to 0 to go back to original tables
2623 # Factor out names to try and make smaller
2627 for s,nd in self.lr_action.items():
2628 for name,v in nd.items():
2636 f.write("\n_lr_action_items = {")
2637 for k,v in items.items():
2638 f.write("%r:([" % k)
2650 for _k, _v in _lr_action_items.items():
2651 for _x,_y in zip(_v[0],_v[1]):
2652 if not _x in _lr_action: _lr_action[_x] = { }
2653 _lr_action[_x][_k] = _y
2654 del _lr_action_items
2658 f.write("\n_lr_action = { ");
2659 for k,v in self.lr_action.items():
2660 f.write("(%r,%r):%r," % (k[0],k[1],v))
2664 # Factor out names to try and make smaller
2667 for s,nd in self.lr_goto.items():
2668 for name,v in nd.items():
2676 f.write("\n_lr_goto_items = {")
2677 for k,v in items.items():
2678 f.write("%r:([" % k)
2690 for _k, _v in _lr_goto_items.items():
2691 for _x,_y in zip(_v[0],_v[1]):
2692 if not _x in _lr_goto: _lr_goto[_x] = { }
2693 _lr_goto[_x][_k] = _y
2697 f.write("\n_lr_goto = { ");
2698 for k,v in self.lr_goto.items():
2699 f.write("(%r,%r):%r," % (k[0],k[1],v))
2702 # Write production table
2703 f.write("_lr_productions = [\n")
2704 for p in self.lr_productions:
2706 f.write(" (%r,%r,%d,%r,%r,%d),\n" % (p.str,p.name, p.len, p.func,p.file,p.line))
2708 f.write(" (%r,%r,%d,None,None,None),\n" % (str(p),p.name, p.len))
2713 e = sys.exc_info()[1]
2714 sys.stderr.write("Unable to create %r\n" % filename)
2715 sys.stderr.write(str(e)+"\n")
2719 # -----------------------------------------------------------------------------
2722 # This function pickles the LR parsing tables to a supplied file object
2723 # -----------------------------------------------------------------------------
2725 def pickle_table(self,filename,signature=""):
2727 import cPickle as pickle
2730 outf = open(filename,"wb")
2731 pickle.dump(__tabversion__,outf,pickle_protocol)
2732 pickle.dump(self.lr_method,outf,pickle_protocol)
2733 pickle.dump(signature,outf,pickle_protocol)
2734 pickle.dump(self.lr_action,outf,pickle_protocol)
2735 pickle.dump(self.lr_goto,outf,pickle_protocol)
2738 for p in self.lr_productions:
2740 outp.append((p.str,p.name, p.len, p.func,p.file,p.line))
2742 outp.append((str(p),p.name,p.len,None,None,None))
2743 pickle.dump(outp,outf,pickle_protocol)
2746 # -----------------------------------------------------------------------------
2747 # === INTROSPECTION ===
2749 # The following functions and classes are used to implement the PLY
2750 # introspection features followed by the yacc() function itself.
2751 # -----------------------------------------------------------------------------
2753 # -----------------------------------------------------------------------------
2754 # get_caller_module_dict()
2756 # This function returns a dictionary containing all of the symbols defined within
2757 # a caller further down the call stack. This is used to get the environment
2758 # associated with the yacc() call if none was provided.
2759 # -----------------------------------------------------------------------------
2761 def get_caller_module_dict(levels):
2764 except RuntimeError:
2765 e,b,t = sys.exc_info()
2770 ldict = f.f_globals.copy()
2771 if f.f_globals != f.f_locals:
2772 ldict.update(f.f_locals)
2776 # -----------------------------------------------------------------------------
2779 # This takes a raw grammar rule string and parses it into production data
2780 # -----------------------------------------------------------------------------
2781 def parse_grammar(doc,file,line):
2783 # Split the doc string into lines
2784 pstrings = doc.splitlines()
2793 # This is a continuation of a previous rule
2795 raise SyntaxError("%s:%d: Misplaced '|'" % (file,dline))
2803 if assign != ':' and assign != '::=':
2804 raise SyntaxError("%s:%d: Syntax error. Expected ':'" % (file,dline))
2806 grammar.append((file,dline,prodname,syms))
2810 raise SyntaxError("%s:%d: Syntax error in rule %r" % (file,dline,ps.strip()))
2814 # -----------------------------------------------------------------------------
2817 # This class represents information extracted for building a parser including
2818 # start symbol, error function, tokens, precedence list, action functions,
2820 # -----------------------------------------------------------------------------
2821 class ParserReflect(object):
2822 def __init__(self,pdict,log=None):
2825 self.error_func = None
2832 self.log = PlyLogger(sys.stderr)
2836 # Get all of the basic information
2839 self.get_error_func()
2841 self.get_precedence()
2842 self.get_pfunctions()
2844 # Validate all of the information
2845 def validate_all(self):
2846 self.validate_start()
2847 self.validate_error_func()
2848 self.validate_tokens()
2849 self.validate_precedence()
2850 self.validate_pfunctions()
2851 self.validate_modules()
2854 # Compute a signature over the grammar
2855 def signature(self):
2857 from hashlib import md5
2863 sig.update(self.start.encode('latin-1'))
2865 sig.update("".join(["".join(p) for p in self.prec]).encode('latin-1'))
2867 sig.update(" ".join(self.tokens).encode('latin-1'))
2868 for f in self.pfuncs:
2870 sig.update(f[3].encode('latin-1'))
2871 except (TypeError,ValueError):
2875 # -----------------------------------------------------------------------------
2876 # validate_modules()
2878 # This method checks to see if there are duplicated p_rulename() functions
2879 # in the parser module file. Without this function, it is really easy for
2880 # users to make mistakes by cutting and pasting code fragments (and it's a real
2881 # bugger to try and figure out why the resulting parser doesn't work). Therefore,
2882 # we just do a little regular expression pattern matching of def statements
2883 # to try and detect duplicates.
2884 # -----------------------------------------------------------------------------
2886 def validate_modules(self):
2887 # Match def p_funcname(
2888 fre = re.compile(r'\s*def\s+(p_[a-zA-Z_0-9]*)\(')
2890 for module in self.modules.keys():
2891 lines, linen = inspect.getsourcelines(module)
2894 for linen,l in enumerate(lines):
2899 prev = counthash.get(name)
2901 counthash[name] = linen
2903 filename = inspect.getsourcefile(module)
2904 self.log.warning("%s:%d: Function %s redefined. Previously defined on line %d", filename,linen,name,prev)
2906 # Get the start symbol
2907 def get_start(self):
2908 self.start = self.pdict.get('start')
2910 # Validate the start symbol
2911 def validate_start(self):
2912 if self.start is not None:
2913 if not isinstance(self.start, string_types):
2914 self.log.error("'start' must be a string")
2916 # Look for error handler
2917 def get_error_func(self):
2918 self.error_func = self.pdict.get('p_error')
2920 # Validate the error function
2921 def validate_error_func(self):
2923 if isinstance(self.error_func,types.FunctionType):
2925 elif isinstance(self.error_func, types.MethodType):
2928 self.log.error("'p_error' defined, but is not a function or method")
2932 eline = func_code(self.error_func).co_firstlineno
2933 efile = func_code(self.error_func).co_filename
2934 module = inspect.getmodule(self.error_func)
2935 self.modules[module] = 1
2937 argcount = func_code(self.error_func).co_argcount - ismethod
2939 self.log.error("%s:%d: p_error() requires 1 argument",efile,eline)
2942 # Get the tokens map
2943 def get_tokens(self):
2944 tokens = self.pdict.get("tokens")
2946 self.log.error("No token list is defined")
2950 if not isinstance(tokens,(list, tuple)):
2951 self.log.error("tokens must be a list or tuple")
2956 self.log.error("tokens is empty")
2960 self.tokens = tokens
2962 # Validate the tokens
2963 def validate_tokens(self):
2964 # Validate the tokens.
2965 if 'error' in self.tokens:
2966 self.log.error("Illegal token name 'error'. Is a reserved word")
2971 for n in self.tokens:
2973 self.log.warning("Token %r multiply defined", n)
2976 # Get the precedence map (if any)
2977 def get_precedence(self):
2978 self.prec = self.pdict.get("precedence")
2980 # Validate and parse the precedence map
2981 def validate_precedence(self):
2984 if not isinstance(self.prec,(list,tuple)):
2985 self.log.error("precedence must be a list or tuple")
2988 for level,p in enumerate(self.prec):
2989 if not isinstance(p,(list,tuple)):
2990 self.log.error("Bad precedence table")
2995 self.log.error("Malformed precedence entry %s. Must be (assoc, term, ..., term)",p)
2999 if not isinstance(assoc, string_types):
3000 self.log.error("precedence associativity must be a string")
3004 if not isinstance(term, string_types):
3005 self.log.error("precedence items must be strings")
3008 preclist.append((term, assoc, level+1))
3009 self.preclist = preclist
3011 # Get all p_functions from the grammar
3012 def get_pfunctions(self):
3014 for name, item in self.pdict.items():
3015 if not name.startswith('p_'): continue
3016 if name == 'p_error': continue
3017 if isinstance(item,(types.FunctionType,types.MethodType)):
3018 line = func_code(item).co_firstlineno
3019 module = inspect.getmodule(item)
3020 p_functions.append((line,module,name,item.__doc__))
3022 # Sort all of the actions by line number
3024 self.pfuncs = p_functions
3027 # Validate all of the p_functions
3028 def validate_pfunctions(self):
3030 # Check for non-empty symbols
3031 if len(self.pfuncs) == 0:
3032 self.log.error("no rules of the form p_rulename are defined")
3036 for line, module, name, doc in self.pfuncs:
3037 file = inspect.getsourcefile(module)
3038 func = self.pdict[name]
3039 if isinstance(func, types.MethodType):
3043 if func_code(func).co_argcount > reqargs:
3044 self.log.error("%s:%d: Rule %r has too many arguments",file,line,func.__name__)
3046 elif func_code(func).co_argcount < reqargs:
3047 self.log.error("%s:%d: Rule %r requires an argument",file,line,func.__name__)
3049 elif not func.__doc__:
3050 self.log.warning("%s:%d: No documentation string specified in function %r (ignored)",file,line,func.__name__)
3053 parsed_g = parse_grammar(doc,file,line)
3055 grammar.append((name, g))
3057 e = sys.exc_info()[1]
3058 self.log.error(str(e))
3061 # Looks like a valid grammar rule
3062 # Mark the file in which defined.
3063 self.modules[module] = 1
3065 # Secondary validation step that looks for p_ definitions that are not functions
3066 # or functions that look like they might be grammar rules.
3068 for n,v in self.pdict.items():
3069 if n.startswith('p_') and isinstance(v, (types.FunctionType, types.MethodType)): continue
3070 if n.startswith('t_'): continue
3071 if n.startswith('p_') and n != 'p_error':
3072 self.log.warning("%r not defined as a function", n)
3073 if ((isinstance(v,types.FunctionType) and func_code(v).co_argcount == 1) or
3074 (isinstance(v,types.MethodType) and func_code(v).co_argcount == 2)):
3076 doc = v.__doc__.split(" ")
3078 self.log.warning("%s:%d: Possible grammar rule %r defined without p_ prefix",
3079 func_code(v).co_filename, func_code(v).co_firstlineno,n)
3083 self.grammar = grammar
3085 # -----------------------------------------------------------------------------
3089 # -----------------------------------------------------------------------------
3091 def yacc(method='LALR', debug=yaccdebug, module=None, tabmodule=tab_module, start=None,
3092 check_recursion=1, optimize=0, write_tables=1, debugfile=debug_file,outputdir='',
3093 debuglog=None, errorlog = None, picklefile=None):
3095 global parse # Reference to the parsing method of the last built parser
3097 # If pickling is enabled, table files are not created
3102 if errorlog is None:
3103 errorlog = PlyLogger(sys.stderr)
3105 # Get the module dictionary used for the parser
3107 _items = [(k,getattr(module,k)) for k in dir(module)]
3108 pdict = dict(_items)
3110 pdict = get_caller_module_dict(2)
3112 # Collect parser information from the dictionary
3113 pinfo = ParserReflect(pdict,log=errorlog)
3117 raise YaccError("Unable to build parser")
3119 # Check signature against table files (if any)
3120 signature = pinfo.signature()
3126 read_signature = lr.read_pickle(picklefile)
3128 read_signature = lr.read_table(tabmodule)
3129 if optimize or (read_signature == signature):
3131 lr.bind_callables(pinfo.pdict)
3132 parser = LRParser(lr,pinfo.error_func)
3133 parse = parser.parse
3136 e = sys.exc_info()[1]
3137 errorlog.warning("There was a problem loading the table file: %s", repr(e))
3138 except VersionError:
3140 errorlog.warning(str(e))
3144 if debuglog is None:
3146 debuglog = PlyLogger(open(debugfile,"w"))
3148 debuglog = NullLogger()
3150 debuglog.info("Created by PLY version %s (http://www.dabeaz.com/ply)", __version__)
3155 # Validate the parser information
3156 if pinfo.validate_all():
3157 raise YaccError("Unable to build parser")
3159 if not pinfo.error_func:
3160 errorlog.warning("no p_error() function is defined")
3162 # Create a grammar object
3163 grammar = Grammar(pinfo.tokens)
3165 # Set precedence level for terminals
3166 for term, assoc, level in pinfo.preclist:
3168 grammar.set_precedence(term,assoc,level)
3169 except GrammarError:
3170 e = sys.exc_info()[1]
3171 errorlog.warning("%s",str(e))
3173 # Add productions to the grammar
3174 for funcname, gram in pinfo.grammar:
3175 file, line, prodname, syms = gram
3177 grammar.add_production(prodname,syms,funcname,file,line)
3178 except GrammarError:
3179 e = sys.exc_info()[1]
3180 errorlog.error("%s",str(e))
3183 # Set the grammar start symbols
3186 grammar.set_start(pinfo.start)
3188 grammar.set_start(start)
3189 except GrammarError:
3190 e = sys.exc_info()[1]
3191 errorlog.error(str(e))
3195 raise YaccError("Unable to build parser")
3197 # Verify the grammar structure
3198 undefined_symbols = grammar.undefined_symbols()
3199 for sym, prod in undefined_symbols:
3200 errorlog.error("%s:%d: Symbol %r used, but not defined as a token or a rule",prod.file,prod.line,sym)
3203 unused_terminals = grammar.unused_terminals()
3204 if unused_terminals:
3206 debuglog.info("Unused terminals:")
3208 for term in unused_terminals:
3209 errorlog.warning("Token %r defined, but not used", term)
3210 debuglog.info(" %s", term)
3212 # Print out all productions to the debug log
3215 debuglog.info("Grammar")
3217 for n,p in enumerate(grammar.Productions):
3218 debuglog.info("Rule %-5d %s", n, p)
3220 # Find unused non-terminals
3221 unused_rules = grammar.unused_rules()
3222 for prod in unused_rules:
3223 errorlog.warning("%s:%d: Rule %r defined, but not used", prod.file, prod.line, prod.name)
3225 if len(unused_terminals) == 1:
3226 errorlog.warning("There is 1 unused token")
3227 if len(unused_terminals) > 1:
3228 errorlog.warning("There are %d unused tokens", len(unused_terminals))
3230 if len(unused_rules) == 1:
3231 errorlog.warning("There is 1 unused rule")
3232 if len(unused_rules) > 1:
3233 errorlog.warning("There are %d unused rules", len(unused_rules))
3237 debuglog.info("Terminals, with rules where they appear")
3239 terms = list(grammar.Terminals)
3242 debuglog.info("%-20s : %s", term, " ".join([str(s) for s in grammar.Terminals[term]]))
3245 debuglog.info("Nonterminals, with rules where they appear")
3247 nonterms = list(grammar.Nonterminals)
3249 for nonterm in nonterms:
3250 debuglog.info("%-20s : %s", nonterm, " ".join([str(s) for s in grammar.Nonterminals[nonterm]]))
3254 unreachable = grammar.find_unreachable()
3255 for u in unreachable:
3256 errorlog.warning("Symbol %r is unreachable",u)
3258 infinite = grammar.infinite_cycles()
3259 for inf in infinite:
3260 errorlog.error("Infinite recursion detected for symbol %r", inf)
3263 unused_prec = grammar.unused_precedence()
3264 for term, assoc in unused_prec:
3265 errorlog.error("Precedence rule %r defined for unknown symbol %r", assoc, term)
3269 raise YaccError("Unable to build parser")
3271 # Run the LRGeneratedTable on the grammar
3273 errorlog.debug("Generating %s tables", method)
3275 lr = LRGeneratedTable(grammar,method,debuglog)
3278 num_sr = len(lr.sr_conflicts)
3280 # Report shift/reduce and reduce/reduce conflicts
3282 errorlog.warning("1 shift/reduce conflict")
3284 errorlog.warning("%d shift/reduce conflicts", num_sr)
3286 num_rr = len(lr.rr_conflicts)
3288 errorlog.warning("1 reduce/reduce conflict")
3290 errorlog.warning("%d reduce/reduce conflicts", num_rr)
3292 # Write out conflicts to the output file
3293 if debug and (lr.sr_conflicts or lr.rr_conflicts):
3294 debuglog.warning("")
3295 debuglog.warning("Conflicts:")
3296 debuglog.warning("")
3298 for state, tok, resolution in lr.sr_conflicts:
3299 debuglog.warning("shift/reduce conflict for %s in state %d resolved as %s", tok, state, resolution)
3301 already_reported = {}
3302 for state, rule, rejected in lr.rr_conflicts:
3303 if (state,id(rule),id(rejected)) in already_reported:
3305 debuglog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule)
3306 debuglog.warning("rejected rule (%s) in state %d", rejected,state)
3307 errorlog.warning("reduce/reduce conflict in state %d resolved using rule (%s)", state, rule)
3308 errorlog.warning("rejected rule (%s) in state %d", rejected, state)
3309 already_reported[state,id(rule),id(rejected)] = 1
3312 for state, rule, rejected in lr.rr_conflicts:
3313 if not rejected.reduced and (rejected not in warned_never):
3314 debuglog.warning("Rule (%s) is never reduced", rejected)
3315 errorlog.warning("Rule (%s) is never reduced", rejected)
3316 warned_never.append(rejected)
3318 # Write the table file if requested
3320 lr.write_table(tabmodule,outputdir,signature)
3322 # Write a pickled version of the tables
3324 lr.pickle_table(picklefile,signature)
3327 lr.bind_callables(pinfo.pdict)
3328 parser = LRParser(lr,pinfo.error_func)
3330 parse = parser.parse