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

Source Code for Module PyFoam.ThirdParty.ply.yacc

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