view pyrect/pyrect/regexp/callgraph.py @ 9:493c96d030c0

add pyrect
author nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
date Tue, 14 Jun 2011 17:24:03 +0900
parents
children
line wrap: on
line source

#!/usr/bin/env python
# -*- encoding: utf-8 -*-

import copy
from pyrect.regexp.parser import Parser
from pyrect.regexp.nfa_translator import NFATranslator
from pyrect.regexp.dfa_translator import DFATranslator
from pyrect.regexp.dfa import DFA
from pyrect.regexp.nfa import NFA
from pyrect.regexp.ast import Character

# create call graph (as dictionary)
class CallGraph(object):
    """CallGraph is State Transition Diagram.
    it's can be create from DFA or DFA.
    >>> prs = Parser()
    >>> dfat = DFATranslator()
    >>> cg = CallGraph(dfat.translate(prs.parse('(argv|argc|args|あれ|これ)')))
    """

    def __init__(self, fa):
        self.fa = fa
        if isinstance(fa, DFA):
            self.type = "DFA"
        else:
            self.type = "NFA"
        self.start = str(self.fa.start)
        self.states = map(str, self.fa.states)
        self.accepts = map(str, self.fa.accepts)
        self.inputs = set()
        self.map = self.create_call_graph(self.fa)

    def create_call_graph(self, fa):
        transitionCases = dict()
        # transitionCases is hash table that binds a state and inputs,
        # it's useful for transition definition
        # fa is dfa or nfa
        # dfa.map => {(1, 'C'): 2, (3, 'C'): 2, (0, 'A'): 1, ...}
        #             : 1 x 'C' -> 2
        # nfa.map => {(6, ''): set([5, 7]), (1, 'A'): set([2]),   ....}
        #             : 6 x '' -> set([5, 7])

        for (state, input) in fa.map.iterkeys():
            slot = transitionCases.setdefault(state, set())
            slot.add(input)

        callGraph = dict()

        # create CallGraph
        for state in self.states:
            callGraph[str(state)] = dict()

        for (state, input) in transitionCases.iteritems():
            caseMap = dict()

            for case in input:
                self.inputs.add(case)
                if self.type == "DFA":
                    caseMap[case] = str(fa.map[state, case])
                else:
                    caseMap[case] = map(str, fa.map[state, case])
            callGraph[str(state)] = caseMap
        return callGraph

def test():
    import doctest
    doctest.testmod()

if __name__ == "__main__": test()