2000-02-26 10:24:46 +00:00
|
|
|
__version__ = "$Id$"
|
|
|
|
|
|
2000-02-28 13:44:24 +00:00
|
|
|
import PyLRengine
|
|
|
|
|
|
2000-02-27 13:46:00 +00:00
|
|
|
class Parser:
|
2000-02-26 10:24:46 +00:00
|
|
|
def __init__(self, lexer, actiontable, gototable, prodinfo):
|
|
|
|
|
self.lexer = lexer
|
|
|
|
|
self.actions = actiontable
|
|
|
|
|
self.gotos = gototable
|
|
|
|
|
# get the function from the function name
|
|
|
|
|
# if we forgot to supply a function we get an AttributeError here
|
|
|
|
|
try: self.prodinfo = map(lambda x,s=self: (x[0], getattr(s, x[1]), x[2]),
|
|
|
|
|
prodinfo)
|
|
|
|
|
except AttributeError:
|
|
|
|
|
sys.stderr.write("Parser: error: forgot to supply a parser function\n")
|
|
|
|
|
raise
|
|
|
|
|
|
|
|
|
|
def unspecified(*args):
|
2000-02-28 13:44:24 +00:00
|
|
|
"""the unspecified function (the default for all productions)"""
|
|
|
|
|
if len(args)>1:
|
|
|
|
|
return args[1]
|
|
|
|
|
return None
|
2000-02-26 10:24:46 +00:00
|
|
|
|
|
|
|
|
def parse(self, text, verbose=0):
|
2000-02-28 13:44:24 +00:00
|
|
|
self.lexer.settext(text)
|
|
|
|
|
self.engine = PyLRengine.NewEngine(self.prodinfo, self.actions,
|
|
|
|
|
self.gotos)
|
|
|
|
|
while 1:
|
|
|
|
|
tok, val = self.lexer.scan(verbose)
|
|
|
|
|
if not self.engine.parse(tok, val):
|
|
|
|
|
break
|
|
|
|
|
|
|
|
|
|
# return final value
|
|
|
|
|
return None
|
|
|
|
|
|
|
|
|
|
def pyparse(self, text, verbose=0):
|
2000-02-27 00:43:20 +00:00
|
|
|
"""The parse algorithm for an LR-parser.
|
2000-02-28 13:44:24 +00:00
|
|
|
Written in Python for ease of debugging the parser.
|
2000-02-27 00:43:20 +00:00
|
|
|
Reference: [Aho,Seti,Ullmann: Compilerbau Teil 1, p. 266]
|
|
|
|
|
"""
|
2000-02-26 10:24:46 +00:00
|
|
|
self.lexer.settext(text)
|
2000-02-27 00:43:20 +00:00
|
|
|
# push the start state on the stack
|
|
|
|
|
stack = [0]
|
2000-02-27 20:45:44 +00:00
|
|
|
tok, val = self.lexer.scan(verbose)
|
2000-02-26 10:24:46 +00:00
|
|
|
while 1:
|
2000-02-28 13:44:24 +00:00
|
|
|
if verbose:
|
|
|
|
|
print "\nstack=",stack
|
2000-02-27 00:43:20 +00:00
|
|
|
state = stack[-1]
|
2000-02-27 13:46:00 +00:00
|
|
|
if verbose:
|
2000-02-27 20:45:44 +00:00
|
|
|
print "state=",state
|
2000-02-28 13:44:24 +00:00
|
|
|
action = self.actions[state][tok]
|
|
|
|
|
if verbose:
|
2000-02-27 20:45:44 +00:00
|
|
|
print "action=",action
|
2000-02-27 00:43:20 +00:00
|
|
|
if action[0]=='s':
|
2000-02-28 13:44:24 +00:00
|
|
|
# push the symbol and the new state
|
2000-02-27 00:43:20 +00:00
|
|
|
stack = stack + [tok, action[1]]
|
2000-02-27 20:45:44 +00:00
|
|
|
tok, val = self.lexer.scan(verbose)
|
2000-02-27 00:43:20 +00:00
|
|
|
elif action[0]=='r':
|
2000-02-27 20:45:44 +00:00
|
|
|
# action[1]-1: compensate previous augmentation
|
2000-02-27 13:46:00 +00:00
|
|
|
P = self.prodinfo[action[1]-1]
|
2000-02-28 13:44:24 +00:00
|
|
|
print "P=",P
|
2000-02-27 00:43:20 +00:00
|
|
|
# reduce P=A->b by popping 2*|b| from the stack
|
2000-02-28 13:44:24 +00:00
|
|
|
if P[0]:
|
|
|
|
|
stack = stack[:-2*P[0]]
|
2000-02-27 13:46:00 +00:00
|
|
|
goto = self.gotos[stack[-1]][P[2]]
|
2000-02-27 00:43:20 +00:00
|
|
|
# push A and the goto symbol
|
2000-02-27 13:46:00 +00:00
|
|
|
stack = stack + [P[2], goto]
|
2000-02-27 00:43:20 +00:00
|
|
|
if verbose:
|
|
|
|
|
print "reduce",P
|
|
|
|
|
elif action[0]=='a':
|
|
|
|
|
return
|
|
|
|
|
else:
|
2000-02-27 13:46:00 +00:00
|
|
|
print "error"
|
|
|
|
|
return
|
2000-02-26 10:24:46 +00:00
|
|
|
|