|
- from grammar_analysis import ACTION_SHIFT
-
- class ParseError(Exception):
- pass
-
- class Parser(object):
- def __init__(self, ga, callback):
- self.ga = ga
- self.callbacks = {rule: getattr(callback, rule.alias or rule.origin, None)
- for rule in ga.rules}
-
- def parse(self, seq):
- states_idx = self.ga.states_idx
-
- stack = [(None, self.ga.init_state_idx)]
- i = 0
- res = None
-
- def get_action(key):
- state = stack[-1][1]
- try:
- return states_idx[state][key]
- except KeyError:
- expected = states_idx[state].keys()
- context = ' '.join(['%s(%r)' % (t.type, t.value) for t in seq[i:i+5]])
- raise ParseError("Unexpected input %r.\nExpected: %s\nContext: %s" % (key, expected, context))
-
- def reduce(rule):
- if rule.expansion:
- s = stack[-len(rule.expansion):]
- del stack[-len(rule.expansion):]
- else:
- s = []
-
- res = self.callbacks[rule]([x[0] for x in s])
-
- if rule.origin == 'start':
- return res
-
- _action, new_state = get_action(rule.origin)
- assert _action == ACTION_SHIFT
- stack.append((res, new_state))
-
- # Main LALR-parser loop
- while i < len(seq):
- action, arg = get_action(seq[i].type)
-
- if action == ACTION_SHIFT:
- stack.append((seq[i], arg))
- i+= 1
- else:
- reduce(arg)
-
- while len(stack) > 1:
- _action, rule = get_action('$end')
- assert _action == 'reduce'
- res = reduce(rule)
- if res:
- break
-
- assert stack == [(None, self.ga.init_state_idx)], len(stack)
- return res
-
|