|
|
@@ -1,6 +1,9 @@ |
|
|
|
from ..common import ParseError, UnexpectedToken, is_terminal |
|
|
|
from .grammar_analysis import GrammarAnalyzer |
|
|
|
|
|
|
|
class EndToken(str): |
|
|
|
type = '$end' |
|
|
|
|
|
|
|
class Item: |
|
|
|
def __init__(self, rule, ptr, start, data): |
|
|
|
self.rule = rule |
|
|
@@ -34,7 +37,8 @@ class Parser: |
|
|
|
self.predictions = {} |
|
|
|
for rule in self.analysis.rules: |
|
|
|
if rule.origin != '$root': # XXX kinda ugly |
|
|
|
self.postprocess[rule] = getattr(parser_conf.callback, rule.alias) |
|
|
|
a = rule.alias |
|
|
|
self.postprocess[rule] = a if callable(a) else getattr(parser_conf.callback, a) |
|
|
|
self.predictions[rule.origin] = [(x.rule, x.index) for x in self.analysis.expand_rule(rule.origin)] |
|
|
|
|
|
|
|
def parse(self, stream): |
|
|
@@ -49,7 +53,7 @@ class Parser: |
|
|
|
return {old_item.advance(item.data) for old_item in table[item.start] |
|
|
|
if not old_item.is_complete and old_item.expect == item.rule.origin} |
|
|
|
|
|
|
|
def process_column(i, term): |
|
|
|
def process_column(i, token): |
|
|
|
assert i == len(table)-1 |
|
|
|
cur_set = table[i] |
|
|
|
next_set = set() |
|
|
@@ -63,7 +67,7 @@ class Parser: |
|
|
|
else: |
|
|
|
if is_terminal(item.expect): |
|
|
|
# scan |
|
|
|
match = item.expect[0](term) if callable(item.expect[0]) else item.expect[0] == term |
|
|
|
match = item.expect[0](token) if callable(item.expect[0]) else item.expect[0] == token.type |
|
|
|
if match: |
|
|
|
next_set.add(item.advance(stream[i])) |
|
|
|
else: |
|
|
@@ -74,9 +78,9 @@ class Parser: |
|
|
|
cur_set |= to_process |
|
|
|
|
|
|
|
|
|
|
|
if not next_set and term != '$end': |
|
|
|
if not next_set and token.type != '$end': |
|
|
|
expect = filter(is_terminal, [x.expect for x in cur_set if not x.is_complete]) |
|
|
|
raise UnexpectedToken(term, expect, stream, i) |
|
|
|
raise UnexpectedToken(token, expect, stream, i) |
|
|
|
|
|
|
|
table.append(next_set) |
|
|
|
|
|
|
@@ -84,9 +88,9 @@ class Parser: |
|
|
|
table = [predict(self.start, 0)] |
|
|
|
|
|
|
|
for i, char in enumerate(stream): |
|
|
|
process_column(i, char.type) |
|
|
|
process_column(i, char) |
|
|
|
|
|
|
|
process_column(len(stream), '$end') |
|
|
|
process_column(len(stream), EndToken()) |
|
|
|
|
|
|
|
# Parse ended. Now build a parse tree |
|
|
|
solutions = [n.data for n in table[len(stream)] |
|
|
|