annotate 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
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
9
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
1 #!/usr/bin/env python
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
2 # -*- encoding: utf-8 -*-
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
3
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
4 import copy
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
5 from pyrect.regexp.parser import Parser
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
6 from pyrect.regexp.nfa_translator import NFATranslator
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
7 from pyrect.regexp.dfa_translator import DFATranslator
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
8 from pyrect.regexp.dfa import DFA
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
9 from pyrect.regexp.nfa import NFA
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
10 from pyrect.regexp.ast import Character
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
11
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
12 # create call graph (as dictionary)
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
13 class CallGraph(object):
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
14 """CallGraph is State Transition Diagram.
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
15 it's can be create from DFA or DFA.
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
16 >>> prs = Parser()
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
17 >>> dfat = DFATranslator()
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
18 >>> cg = CallGraph(dfat.translate(prs.parse('(argv|argc|args|あれ|これ)')))
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
19 """
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
20
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
21 def __init__(self, fa):
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
22 self.fa = fa
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
23 if isinstance(fa, DFA):
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
24 self.type = "DFA"
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
25 else:
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
26 self.type = "NFA"
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
27 self.start = str(self.fa.start)
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
28 self.states = map(str, self.fa.states)
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
29 self.accepts = map(str, self.fa.accepts)
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
30 self.inputs = set()
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
31 self.map = self.create_call_graph(self.fa)
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
32
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
33 def create_call_graph(self, fa):
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
34 transitionCases = dict()
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
35 # transitionCases is hash table that binds a state and inputs,
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
36 # it's useful for transition definition
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
37 # fa is dfa or nfa
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
38 # dfa.map => {(1, 'C'): 2, (3, 'C'): 2, (0, 'A'): 1, ...}
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
39 # : 1 x 'C' -> 2
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
40 # nfa.map => {(6, ''): set([5, 7]), (1, 'A'): set([2]), ....}
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
41 # : 6 x '' -> set([5, 7])
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
42
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
43 for (state, input) in fa.map.iterkeys():
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
44 slot = transitionCases.setdefault(state, set())
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
45 slot.add(input)
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
46
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
47 callGraph = dict()
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
48
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
49 # create CallGraph
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
50 for state in self.states:
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
51 callGraph[str(state)] = dict()
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
52
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
53 for (state, input) in transitionCases.iteritems():
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
54 caseMap = dict()
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
55
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
56 for case in input:
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
57 self.inputs.add(case)
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
58 if self.type == "DFA":
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
59 caseMap[case] = str(fa.map[state, case])
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
60 else:
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
61 caseMap[case] = map(str, fa.map[state, case])
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
62 callGraph[str(state)] = caseMap
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
63 return callGraph
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
64
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
65 def test():
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
66 import doctest
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
67 doctest.testmod()
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
68
493c96d030c0 add pyrect
nobuyasu <dimolto@cr.ie.u-ryukyu.ac.jp>
parents:
diff changeset
69 if __name__ == "__main__": test()