class Res: def __init__(self, subtree, pos): self.subtree = subtre self.pos = pos def __str__(self): return '(' + ', '.join((str(self.subtree), str(self.pos))) + ')' def __bool__(self): return self.subtree != None
class Tree: def __init__(self, root = None, children = None): self.root = root if children == None: self.children = [] else: self.children = children def __str__(self): r = str(self.root) c = ', '.join(str(c) for c in self.children) if c: r = '[' + r + ', ' + c + ']' return r
import abc class Parser(metaclass = abc.ABCMeta): @abc.abstractmethod def __call__(self): pass def __lshift__(self, other): # << return Concat(self, other, 1) def __rshift__(self, other): # >> return Concat(self, other, 0) def __or__(self, other): # | return Alt(self, other)
class Atom(Parser): def __init__(self, token): self.token = token def __call__(self, tokens, pos = 0): if pos != len(tokens) and self.token == tokens[pos]: return Res(Tree(tokens[pos]), pos + 1) return Res(None, pos)
class Concat(Parser): def __init__(self, left, right, F = 0): self.left = left self.right = right self.F = F # F == 0 - , # – - def __call__(self, tokens, pos = 0): left_res = self.left(tokens, pos) if left_res: right_res = self.right(tokens, left_res.pos) if right_res: if self.F == 0: right_res.subtree.children.insert(0, left_res.subtree) return right_res left_res.subtree.children.append(right_res.subtree) return Res(left_res.subtree, right_res.pos) return right_res return left_res
class Alt(Parser): def __init__(self, left, right): self.left = left self.right = right def __call__(self, tokens, pos = 0): left_res = self.left(tokens, pos) if left_res: return left_res right_res = self.right(tokens, pos) if right_res: return right_res if left_res.pos > right_res.pos: return left_res return right_res
class Opt(Parser): def __init__(self, parser, default = None): self.parser = parser def __call__(self, tokens, pos = 0): res = self.parser(tokens, pos) if res: return res return Res(Tree(default), pos)
class Repeat(Parser): def __init__(self, root, parser, F = 0): self.root = root self.parser = parser self.F = F def __call__(self, tokens, pos = 0): tree = Tree(self.root) while True: res = self.parser(tokens, pos) if not res: break if self.F == 0: tree.children.append(res.subtree) else: tree.children.insert(0, res.subtree) pos = res.pos return Res(tree, pos)
class Prog(Parser): def __init__(self, parser, *others, N = -1): self.parser = parser self.others = others self.N = N def __call__(self, tokens, pos = 0): i = 1 + len(self.others) + self.N if self.N < 0 else self.N if i < 0 or i > len(self.others): raise IndexError res = self.parser(tokens, pos) if not res: return res t = res error = 0 j = 1 for parser in self.others: res = parser(tokens, res.pos) if not res: error = 1 break if j == i: t = res j += 1 if error: return res return Res(t.subtree, res.pos)
class Lazy(Parser): def __init__(self, parser_func): self.parser_func = parser_func self.parser = None def __call__(self, tokens, pos = 0): if not self.parser: self.parser = self.parser_func() return self.parser(tokens, pos)
class LExp(Parser): def __init__(self, first, sep, parser): self.first = first self.sep = sep self.parser = parser def __call__(self, tokens, pos = 0): left_res = self.first(tokens, pos) if not left_res: return left_res error = 0 while True: sep_res = self.sep(tokens, left_res.pos) if not sep_res: break right_res = self.parser(tokens, sep_res.pos) if not right_res: error = 1 break sep_res.subtree.children.append(right_res.subtree) sep_res.subtree.children.insert(0, left_res.subtree) left_res = Res(sep_res.subtree, right_res.pos) if error: return right_res return left_res
Source: https://habr.com/ru/post/317304/
All Articles