Example #1
0
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)
Example #2
0
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)
Example #3
0
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)
Example #4
0
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