view pyrect/translator/dot_translator.py @ 99:e327e93aeb3a

remove callgraph and use Transition.
author Ryoma SHINYA <shinya@firefly.cr.ie.u-ryukyu.ac.jp>
date Sun, 12 Dec 2010 23:09:19 +0900
parents d23f12ce0369
children
line wrap: on
line source

#!/usr/bin/env python

import re

from translator import Translator
from pyrect.regexp import Regexp
from pyrect.regexp.dfa import SuffixDFA, DFA

class DotTranslator(Translator):
    """
    DotToranslator
    This Class can translate from DFA or NFA into Dot
    Dot is Graph-generater using TeX.
    --code/graph/makepdf.sh is generate graph script.
    >>> string = \"(A|B)*C\"
    >>> reg = Regexp(string)
    >>> DotTranslator(reg, 'DFA').translate()
    >>> DotTranslator(reg, 'NFA').translate()
    """
    def __init__(self, regexp, fa="DFA"):
        Translator.__init__(self, regexp)
        if fa == "NFA":
            self.fa = regexp.nfa
        else:
            self.fa = regexp.dfa
        self.fill_color = "lightsteelblue1"
        self.frame_color = "navyblue"

    def state_name(self, name):
        return "q"+str(name)

    def emit_from_callgraph(self):
        color = "fillcolor=%s, style=filled, color = %s" % (self.fill_color, self.frame_color)
        self.emiti('digraph G{')
        self.emit(  'rankdir=LR')
        self.emit(  'regex [shape=plaintext, label="%s"]' % self.regexp.regexp)

        # emit transition
        for state in self.fa.states:
            if state in self.fa.accepts:
                self.emit("%s [shape=doublecircle, %s]" % (self.state_name(state), color))
            else:
                self.emit("%s [shape=circle, %s]" % (self.state_name(state), color))

        # edge to start state
        self.emit("start [shape=point]")
        self.emit("start -> %s" % self.state_name(self.fa.start), 2)

        for cur_state, trans in self.fa.transition.iteritems():
            for input, next_states in trans.iteritems():
                if type(self.fa) == DFA:
                    next_states = [next_states]
                for next_state in next_states:
                    self.emit("%s -> %s [label=\"%s\"]"
                              % (self.state_name(cur_state), self.state_name(next_state), input))

        if type(self.fa) == SuffixDFA:
            sdfa = self.fa
            pdfa = sdfa.pdfa
            color = "fillcolor=\"#99cc99\", style=filled, color = \"#000000\""
            arrowstyle = "arrowhead = odot, dir = both"
            for s in sdfa.states:
                s_is = sdfa.assoc[s] & set(pdfa.states)
                self.emit("%s_is [shape=box,label=\"%s\", %s, %s]"
                          % (self.state_name(str(s)), ", ".join(map(self.state_name, map(str, s_is))), color, arrowstyle))
                self.emit("%s -> %s_is [label=\"is\"]" % (self.state_name(str(s)), (self.state_name(str(s)))))

            color = "fillcolor=\"#cc9999\", style=filled, color = \"#000000\""
            arrowstyle = "arrowhead = odot, dir = both"
            for s in sdfa.acceptable.iterkeys():
                msg = list()
                def pretty(hist, s):
                    def p1 (s):
                        return self.state_name(str(s))
                    def p2 (s):
                        return "p"+str(s)
                    return " -> ".join(map(p1, hist)) + " := " + ", ".join(map(p2, s))
                for hist, ss in sdfa.acceptable[s].iteritems():
                    msg.append(pretty(hist, ss))
                self.emit("%s_accept [shape=box,label=\"%s\", %s, %s]" % (self.state_name(str(s)), "\\n".join(msg), color, arrowstyle))
                self.emit("%s -> %s_accept [label=\"acceptable\"]" % (self.state_name(str(s)), (self.state_name(str(s)))))

        self.demit("}", 2)

def test():
    import doctest
    doctest.testmod()
    '''
    reg = Regexp("(A|B)*C")
    ct = CTranslator(reg.regexp, CallGraph(reg.dfa))
    ct.translate()
    '''

if __name__ == '__main__' : test()