def run(graph, program, address): threads = ThreadList(program) threads.add(Thread(0, address)) arc = Arc() while threads: thread = threads.current() address = thread.address op = program[thread.pc] optype = type(op) if optype is Char: if address: arc = graph.find_arc(address, op.c, arc) if arc: advance(thread, arc) threads.add(thread) elif optype is Lit: if address: c = op.c arc = graph.find_path(c, arc, address) if arc: advance(thread, arc, c) threads.add(thread) elif optype is Any: if address: sofar = thread.sofar pc = thread.pc + 1 for arc in graph.iter_arcs(address, arc): t = Thread(pc, arc.target, sofar + arc.label, arc.accept) threads.add(t) elif op is Match: if thread.accept: yield thread.sofar else: raise Exception("Don't know what to do with %r" % op)
def glob_graph_limit(graph, mode, pattern, address): low = mode == LO output = [] arc = Arc(target=address) for op in pattern: if arc.target is None: break code = op[0] if code == _STAR or code == _PLUS: while arc.target: if low: arc = graph.arc_at(arc.target, arc) else: for arc in graph.iter_arcs(arc.target, arc): pass output.append(arc.label) if low and arc.accept: break elif code == _QUEST: if low: arc = graph.arc_at(arc.target, arc) else: for arc in graph.iter_arcs(arc.target, arc): pass elif code == _LIT: labels = op[1] for label in labels: arc = graph.find_arc(arc.target, label) if arc is None: break output.append(label) if arc.target is None: break if arc is None: break elif code == _RANGE: chars = op[1] negate = op[2] newarc = None for a in graph.iter_arcs(arc.target): if (a.label in chars) ^ negate: newarc = a.copy() if low: break if newarc: output.append(newarc.label) arc = newarc else: break return emptybytes.join(output)
def regex_limit(graph, mode, program, address): low = mode == LO output = [] threads = ThreadList(program) threads.add(Thread(0, address)) arc = Arc() while threads: thread = threads.current() address = thread.address op = program[thread.pc] optype = type(op) if optype is Char: if address: arc = graph.find_arc(address, op.c, arc) if arc: if low and arc.accept: return thread.sofar + thread.label advance(thread, arc) threads.add(thread) elif optype is Lit: if address: labels = op.c for label in labels: arc = graph.find_arc(address, label) if arc is None: return thread.sofar elif thread.accept: return thread.sofar elif optype is Any: if address: if low: arc = graph.arc_at(address, arc) else: for arc in graph.iter_arcs(address): pass advance(thread, arc, arc.label) threads.add(thread) elif thread.accept: return thread.sofar elif op is Match: return thread.sofar else: raise Exception("Don't know what to do with %r" % op)
def glob(graph, pattern, address=None): """Yields a series of keys in the given graph matching the given "glob" string. This function implements the same glob features found in the `fnmatch` module in the Python standard library: ``*`` matches any number of characters, ``?`` matches any single character, `[abc]` matches any of the characters in the list, and ``[!abc]`` matches any character not in the list. (Use ``[[]`` to match an open bracket.) As ``fnmatch``, the star is greedy. :param graph: a :class:`GraphReader` object. :param pattern: a string specifying the glob to match, e.g. `"a*b?c[def]"`. """ address = address if address is not None else graph._root if not isinstance(pattern, list): pattern = parse_glob(pattern) # address, pos, sofar, accept states = [(address, 0, [], False)] seen = set() arc = Arc() times = 0 while states: ns = [] for address, pos, sofar, accept in states: times += 1 op = pattern[pos] code = op[0] if accept and code == _END: if sofar not in seen: yield sofar seen.add(sofar) if code == _END: continue # Zero width match if code == _STAR: ns.append((address, pos + 1, sofar, accept)) if address is None: continue if code == _STAR: for arc in graph.iter_arcs(address, arc): ns.append( (arc.target, pos + 1, sofar + [arc.label], arc.accept)) ns.append( (arc.target, pos, sofar + [arc.label], arc.accept)) elif code == _QUEST: for arc in graph.iter_arcs(address, arc): ns.append( (arc.target, pos + 1, sofar + [arc.label], arc.accept)) elif code == _LIT: labels = op[1] for label in labels: arc = graph.find_arc(address, label) address = arc.target if address is None: break if address is not None: ns.append((address, pos + 1, sofar + labels, arc.accept)) elif code == _RANGE: chars = op[1] negate = op[2] for arc in graph.iter_arcs(address, arc): take = (arc.label in chars) ^ negate if take: ns.append((arc.target, pos + 1, sofar + [arc.label], arc.accept)) else: raise ValueError(code) states = ns