### Navigation

- index
- modules |
- FAdo 1.2 documentation »
- Module code »

# Source code for fio

    # -*- coding: utf-8 -*-
    """**In/Out.**

    FAdo IO.

    .. *Authors:* Rogério Reis & Nelma Moreira

    .. *This is part of FAdo project*   http://fado.dcc.fc.up.pt.

    .. *Copyright:* 2014 Rogério Reis & Nelma Moreira {rvr,nam}@dcc.fc.up.pt

    .. This program is free software; you can redistribute it and/or
       modify it under the terms of the GNU General Public License as published
       by the Free Software Foundation; either version 2 of the License, or
       (at your option) any later version.

       This program is distributed in the hope that it will be useful,
       but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
       or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
       for more details.

       You should have received a copy of the GNU General Public License along
       with this program; if not, write to the Free Software Foundation, Inc.,
       675 Mass Ave, Cambridge, MA 02139, USA."""

    from yappy_parser import Yappy, grules

    from common import Epsilon, DFAerror, TRError
    from fa import DFA, NFA, statePP
    from transducers import SFT, GFT, Transducer

    class ParserFAdo(Yappy):
        """A parser for FAdo standard automata descriptions

        .. inheritance-diagram:: ParserFAdo"""

        def __init__(self, no_table=1, table=".tableFAdo"):
            tokenizer = [("\n+", lambda x: ("EOL", "EOL")),
                         ("#.*", ""),
                         ("\s+", ""),
                         #("@epsilon", lambda x: ("ids", "@epsilon")),
                         ("@epsilon", lambda x: ("ids", Epsilon)),
                         ("@NFA", lambda x: ("NFA", "NFA")),
                         ("@DFA", lambda x: ("DFA", "DFA")),
                         ("@TDFA", lambda x: ("TDFA", "TDFA")),
                         ("@Transducer", lambda x: ("TRANS", "TRANS")),
                         ("\*", lambda x: ("SEP", "SEP")),
                         ("\$", lambda x: ("DOLLAR", "DOLLAR")),
                         ("\^", lambda x: ("CARET", "CARET")),
                         ("<", lambda x: ("mv", "LEFT")),
                         (">", lambda x: ("mv", "RIGHT")),
                         ('"[A-Za-z0-9\(\)\[\]\{\}:\.,_-]+"', lambda x: ("id", x[1:-1])),
                         ("[A-Za-z0-9]+", lambda x: ("id", x))]
            grammar = grules([("r -> d r", self.defaultSemRule),
                              ("r -> n r", self.defaultSemRule),
                              ("r -> td r", self.defaultSemRule),
                              ("r -> tr r", self.defaultSemRule),
                              ("r -> dummy r", self.emptySemRule),
                              ("r -> ", self.emptySemRule),
                              ("d -> DFA l t1", self.startDFASemRule),
                              ("n -> NFA l t1n", self.startNFASemRule),
                              ("n -> NFA l1 i tn", self.startNFASemRule),
                              ("td -> TDFA l tt1", self.startTDFASemRule),
                              ("tr -> TRANS l5 ttr", self.startTRANSSemRule),
                              ("tr -> TRANS l3 ttri", self.startTRANSSemRule),
                              ("idt -> id", self.defaultSemRule),
                              ("idt -> ids", self.defaultSemRule),
                              ("l -> id l", self.finalSemRule),
                              ("l -> DOLLAR l2", self.emptySemRule),
                              ("l -> EOL", self.emptySemRule),
                              ("l1 -> id l1", self.finalSemRule),
                              ("l1 -> SEP", self.emptySemRule),
                              ("l2 -> id l2 ", self.addAlphabet),
                              ("l2 -> EOL", self.emptySemRule),
                              ("i -> id i", self.initialSemRule),
                              ("i -> DOLLAR l2", self.emptySemRule),
                              ("i -> EOL", self.emptySemRule),
                              ("l5 -> id l5", self.finalSemRule),
                              ("l5 -> DOLLAR it", self.emptySemRule),
                              ("l5 -> EOL", self.emptySemRule),
                              ("l3 -> id l3", self.finalSemRule),
                              ("l3 -> SEP l4", self.emptySemRule),
                              ("l4 -> id l4", self.initialSemRule),
                              ("l4 -> DOLLAR it", self.emptySemRule),
                              ("l4 -> EOL", self.emptySemRule),
                              ("it -> id it", self.addAlphabet),
                              ("it -> DOLLAR ot", self.emptySemRule),
                              ("it -> EOL", self.emptySemRule),
                              ("ot -> id ot ", self.addAlphabetOut),
                              ("ot -> EOL", self.emptySemRule),
                              ("t1 -> EOL t1", self.emptySemRule),
                              ("t1 -> id EOL t", self.firstDeclareState),
                              ("t1 -> id id id EOL t", self.firstTransitionSemRule),
                              ("t1 -> ", self.emptySemRule),
                              ("tt1 -> EOL tt1", self.emptySemRule),
                              ("tt1 - id EOL tt", self.firstDeclareState),
                              ("tt1 -> id ids id mv tt", self.firstTTransitionSemRule),
                              ("tt1 -> id id id mv tt", self.firstTTransitionSemRule),
                              ("tt1 -> id DOLLAR id mv tt", self.firstTTransitionSemRule),
                              ("tt1 -> id CARET id mv tt", self.firstTTransitionSemRule),
                              ("tt1 -> ", self.emptySemRule),
                              ("tt -> id EOL tt", self.declareState),
                              ("tt -> id ids is mv EOL tt", self.transitionTSemRule),
                              ("tt -> id id is mv EOL tt", self.transitionTSemRule),
                              ("tt -> id DOLLAR is mv EOL tt", self.transitionTSemRule),
                              ("tt -> id CARET is mv EOL tt", self.transitionTSemRule),
                              ("tt -> EOL tt", self.emptySemRule),
                              ("tt -> ", self.emptySemRule),
                              ("t1n -> EOL t1n", self.emptySemRule),
                              ("t1n -> id EOL tn", self.firstDeclareState),
                              ("t1n -> id id id EOL tn", self.firstTransitionSemRule),
                              ("t1n -> id ids id EOL tn", self.firstTransitionESemRule),
                              ("t1n -> ", self.emptySemRule),
                              ("t -> id EOL t", self.declareState),
                              ("t -> id id id EOL t", self.transitionSemRule),
                              ("t -> EOL t", self.emptySemRule),
                              ("t -> ", self.emptySemRule),
                              ("tn - EOL tn", self.emptySemRule),
                              ("tn -> id EOL tn", self.declareState),
                              ("tn -> id id id EOL tn", self.transitionSemRule),
                              ("tn -> id ids id EOL tn", self.transitionESemRule),
                              ("tn -> EOL tn", self.emptySemRule),
                              ("tn -> ", self.emptySemRule),
                              ("ttr - EOL ttr", self.emptySemRule),
                              ("ttr -> id EOL ttr", self.declareState),
                              ("ttr -> id idt idt id EOL ttrs", self.firstTransitionTransSemRule),
                              ("ttr -> ", self.emptySemRule),
                              ("ttrs -> id EOL ttrs", self.declareState),
                              ("ttrs -> id idt idt id EOL ttrs", self.transitionTransSemRule),
                              ("ttrs -> EOL ttrs", self.emptySemRule),
                              ("ttrs -> ", self.emptySemRule),
                              ("ttri - EOL ttri", self.emptySemRule),
                              ("ttri -> id EOL ttri", self.declareState),
                              ("ttri -> id idt idt id EOL ttri", self.transitionTransSemRule),
                              ("ttri -> EOL ttri", self.emptySemRule),
                              ("ttri -> ", self.emptySemRule),
                              ("dummy -> EOL", self.emptySemRule)
                              ])

            self.theList = []
            self.transitions = []
            self.initials = []
            self.states = set()
            self.finals = []
            self.alphabet = set()
            self.alphabetOut = set()
            self.TRtype = None
            Yappy.__init__(self, tokenizer, grammar, table, no_table)

        def initLocal(self):
            """Starts local structures for a new automata"""
            self.transitions = []
            self.initials = []
            self.states = set()
            self.finals = []
            self.alphabet = set()
            self.alphabetOut = set()

        # noinspection PyUnusedLocal
        @staticmethod
        def defaultSemRule(lst, context=None):
            """Defines the default semantic rule for Yappy
            :param list lst: list of the arguments semantics
            :param dict context: context for the semantic rules
            :returns: first argument semantics"""
            return lst[0]

        # noinspection PyUnusedLocal
        @staticmethod
        def emptySemRule(lst, context=None):
            """Defines the empty semantic rule for Yappy
            :param lst: lst of the arguments semantics
            :param dict context: context for the semantic rules
            :returns: empty list"""
            return []

        # noinspection PyUnusedLocal
        def startDFASemRule(self, lst, context=None):
            """

            :param context:
            :param lst:
            :param context:"""
            new = DFA()
            while self.states:
                x = self.states.pop()
                new.addState(x)
            new.Sigma = self.alphabet
            x = self.initials.pop()
            new.setInitial(new.stateIndex(x))
            while self.finals:
                x = self.finals.pop()
                new.addFinal(new.stateIndex(x))
            while self.transitions:
                (x1, x2, x3) = self.transitions.pop()
                new.addTransition(new.stateIndex(x1), x2, new.stateIndex(x3))
            self.theList.append(new)
            self.initLocal()

        # noinspection PyUnusedLocal
        def startTDFASemRule(self, lst, context=None):
            """

            :param lst:
            :param context:
            """
            pass

        # noinspection PyUnusedLocal
        def startNFASemRule(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            new = NFA()
            new.Sigma = self.alphabet
            while self.states:
                x = self.states.pop()
                new.addState(x)
            while self.initials:
                x = self.initials.pop()
                new.addInitial(new.stateIndex(x))
            while self.finals:
                x = self.finals.pop()
                new.addFinal(new.stateIndex(x))
            while self.transitions:
                (x1, x2, x3) = self.transitions.pop()
                new.addTransition(new.stateIndex(x1), x2, new.stateIndex(x3))
            self.theList.append(new)
            self.initLocal()

        # noinspection PyUnusedLocal
        def startTRANSSemRule(self, lst, context=None):
                """

                :param lst:
                :param context:"""
                if self.TRtype is None:
                    new = SFT()
                elif self.TRtype == "GFT":
                    new = GFT()
                else: raise TRError
                new.Sigma = self.alphabet
                new.Output = self.alphabetOut
                while self.states:
                    x = self.states.pop()
                    new.addState(x)
                while self.initials:
                    x = self.initials.pop()
                    new.addInitial(new.stateIndex(x))
                while self.finals:
                    x = self.finals.pop()
                    new.addFinal(new.stateIndex(x))
                while self.transitions:
                    (x1, x2, x3, x4) = self.transitions.pop()
                    new.addTransition(new.stateIndex(x1), x2, x3, new.stateIndex(x4))
                self.theList.append(new)
                self.initLocal()

        # noinspection PyUnusedLocal
        def finalSemRule(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            self.finals.append(lst[0])
            self.states.add(lst[0])

        # noinspection PyUnusedLocal
        def initialSemRule(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            self.initials.append(lst[0])
            self.states.add(lst[0])

        # noinspection PyUnusedLocal
        def firstTransitionSemRule(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            self.initials.append(lst[0])
            self.states.add(lst[0])
            self.states.add(lst[2])
            self.transitions.append((lst[0], lst[1], lst[2]))

        # noinspection PyUnusedLocal
        def firstTTransitionSemRule(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            pass

        # noinspection PyUnusedLocal
        def firstTransitionTransSemRule(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            self.initials.append(lst[0])
            self.states.add(lst[0])
            self.states.add(lst[3])
            if self.TRtype is None and (lst[1] != Epsilon and len(lst[1]) > 1) or (lst[2] != Epsilon and len(lst[2]) > 1):
                self.TRtype = "GFT"
            self.transitions.append((lst[0], lst[1], lst[2], lst[3]))

        # noinspection PyUnusedLocal
        def firstDeclareState(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            self.states.add(lst[0])
            self.initials.append(lst[0])

        # noinspection PyUnusedLocal
        def addAlphabet(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            self.alphabet.add(lst[0])

        # noinspection PyUnusedLocal
        def addAlphabetOut(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            self.alphabetOut.add(lst[0])

        # noinspection PyUnusedLocal
        def declareState(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            self.states.add(lst[0])

        # noinspection PyUnusedLocal
        def firstTransitionESemRule(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            self.transitions.append((lst[0], Epsilon, lst[2]))
            self.initials.append(lst[0])
            self.states.add(lst[0])
            self.states.add(lst[2])

        # noinspection PyUnusedLocal
        def transitionSemRule(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            self.transitions.append((lst[0], lst[1], lst[2]))
            self.states.add(lst[0])
            self.states.add(lst[2])

        # noinspection PyUnusedLocal
        def transitionTransSemRule(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            if self.TRtype is None and (lst[1] != Epsilon and len(lst[1]) > 1) or (lst[2] != Epsilon and len(lst[2]) > 1):
                self.TRtype = "GFT"
            self.transitions.append((lst[0], lst[1], lst[2], lst[3]))
            self.states.add(lst[0])
            self.states.add(lst[3])

        # noinspection PyUnusedLocal
        def transitionTSemRule(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            pass

        # noinspection PyUnusedLocal
        def transitionESemRule(self, lst, context=None):
            """

            :param lst:
            :param context:"""
            self.transitions.append((lst[0], Epsilon, lst[2]))
            self.states.add(lst[0])
            self.states.add(lst[2])

        def result(self):
            """

            :return:"""
            return self.theList

    def readOneFromFile(fileName):
        """ Read the first of the FAdo objects from File

        :param fileName: name of the file
        :type fileName: str
        :rtype: DFA|FA|STF"""
        return readFromFile(fileName)[0]

    def readFromFile(FileName):
        """Reads list of finite automata definition from a file.

        :param FileName: file name
        :type FileName: str
        :rtype: list

        The format of these files must be the as simple as possible:

        .. hlist::
           :columns: 1

           * ``#`` begins a comment
           * ``@DFA`` or ``@NFA`` begin a new automata (and determines its type) and must be followed by the list of the
             final states separated by blanks
           * fields are separated by a blank and transitions by a CR: ``state`` ``symbol`` ``new state``
           * in case of a NFA declaration, the "symbol" @epsilon is interpreted as a epsilon-transition
           * the source state of the first transition is the initial state
           * in the case of a NFA, its declaration ``@NFA``  can, after the declaration of the final states,
             have a ``*`` followed by the list of initial states
           * both, NFA and DFA, may have a declaration of alphabet starting with a ``$`` followed by the symbols of the
             alphabet
           * a line with a sigle name, decrares a state

        .. productionlist:: Fado Format
           FAdo: FA | FA CR FAdo
           FA: DFA | NFA | Transducer
           DFA: "@DFA" LsStates Alphabet CR dTrans
           NFA: "@NFA" LsStates Initials Alphabet CR nTrans
           Transducer: "@Transducer" LsStates Initials Alphabet Output CR tTrans
           Initials: "*" LsStates | \epsilon
           Alphabet: "$" LsSymbols | \epsilon
           Output: "$" LsSymbols | \epsilon
           nSymbol: symbol | "@epsilon"
           LsStates: stateid | stateid , LsStates
           LsSymbols: symbol | symbol , LsSymbols
           dTrans: stateid symbol stateid |
            :| stateid symbol stateid CR dTrans
           nTrans: stateid nSymbol stateid |
            :| stateid nSymbol stateid CR nTrans
           tTrans: stateid nSymbol nSymbol stateid |
            :| stateid nSymbol nSymbol stateid CR nTrans
        .. note::
           If an error occur, either syntactic or because of a violation of the declared automata type,
           an exception is raised

        .. versionchanged:: 0.9.6
        .. versionchanged:: 1.0"""

        parser = ParserFAdo()
        parser.inputfile(FileName)
        return parser.result()

    def readOneFromString(s):
        """Reads one finite automata definition from a file.

        .. seealso::
            readFromFile for description of format

        :param str s: the string
        :rtype: DFA|NFA|SFT"""
        parser = ParserFAdo()
        parser.input(s)
        return parser.result()[0]

    def saveToFile(FileName, fa, mode="a"):
        """ Saves a list finite automata definition to a file using the input format

        .. versionchanged:: 0.9.5
        .. versionchanged:: 0.9.6
        .. versionchanged:: 0.9.7 New format with quotes and alphabet

        :param FileName: file name
        :type FileName: str
        :param fa: the FA
        :type fa: list of FA
        :param mode: writing mode
        :type mode: str """

        #TODO: write the complete information into file according with the new format
        def _save_SFTransducer(tr):
            """Writes transducer to a file

            :param tr: the transducer
            :type tr: Transducer"""
            f.write("@Transducer ")
            for s in tr.Final:
                f.write("{0:>s} ".format(statePP(tr.States[s])))
            f.write("* ")
            for s in tr.Initial:
                f.write("{0:>s} ".format(statePP(fa.States[s])))
            f.write("\n")
            for sin in tr.delta:
                for syin in tr.delta[sin]:
                    for (syout, sout) in tr.delta[sin][syin]:
                        f.write("{0:>s} {1:>s} {2:>s} {3:>s}\n".format(statePP(tr.States[sin]), str(syin), str(syout),
                                                                       statePP(tr.States[sout])))
            f.write("\n")

        def _saveFA(aut):
            """Writes one fa to a file

            :param aut: the automaton
            :type aut: FA or list"""
            if isinstance(aut, DFA):
                f.write("@DFA ")
                NFAp = False
            elif isinstance(aut, NFA):
                f.write("@NFA ")
                NFAp = True
            else:
                raise DFAerror()
            if not NFAp and aut.Initial != 0:
                foo = {0: aut.Initial, aut.Initial: 0}
                aut.reorder(foo)
            for sf in aut.Final:
                f.write("{0:>s} ".format(statePP(aut.States[sf])))
            if NFAp:
                f.write(" * ")
                for sf in aut.Initial:
                    f.write("{0:>s} ".format(statePP(aut.States[sf])))
            f.write("\n")
            for s in xrange(len(aut.States)):
                if s in aut.delta:
                    for a in aut.delta[s].keys():
                        if isinstance(aut.delta[s][a], set):
                            for s1 in aut.delta[s][a]:
                                f.write(
                                    "{0:>s} {1:>s} {2:>}\n".format(statePP(aut.States[s]), str(a), statePP(aut.States[s1])))
                        else:
                            f.write("{0:>s} {1:>s} {2:>s}\n".format(statePP(aut.States[s]), str(a),
                                                                    statePP(aut.States[aut.delta[s][a]])))
                else:
                    f.write("{0:>s} \n".format(statePP(aut.States[s])))

        try:
            f = open(FileName, mode)
        except IOError:
            raise DFAerror()
        if type(fa) == list:
            for d in fa:
                if isinstance(d, Transducer):
                    _save_SFTransducer(d)
                else:
                    _saveFA(d)
        else:
            if isinstance(fa, Transducer):
                _save_SFTransducer(fa)
            else:
                _saveFA(fa)
        f.close()

    def _exportToTeX(FileName, fa):
        """ Saves a finite automatom definition to a latex tabular. Saves a finite automata definition to a file using
        the input format

        .. versionchanged:: 0.9.4

        :param FileName: file name
        :type FileName: str
        :param fa: the FA
        :type fa: FA
        :raises DFAerror: if a file error occurs"""
        try:
            f = open(FileName, "w")
        except IOError:
            raise DFAerror()
            #initial is the first one
        if fa.Initial:
            foo = {0: fa.Initial, fa.Initial: 0}
            fa.reorder(foo)
        f.write("$$\\begin{array}{r|")
        for i in xrange(len(fa.Sigma)):
            f.write("|c")
        f.write("}\n")
        for c in fa.Sigma:
            f.write("&{0:>s}".format(str(c)))
        f.write(" \\\\\hline\n")
        for s in xrange(len(fa.States)):
            if s in fa.delta:
                if fa.Initial == s:
                    f.write("\\rightarrow")
                if s in fa.Final:
                    f.write("\\star")
                f.write("{0:>s}".format(str(s)))
                for a in fa.delta[s].keys():
                    if isinstance(fa.delta[s][a], set):
                        f.write("&\{")
                        for s1 in fa.delta[s][a]:
                            f.write("{0:>s} ".format(str(s1)))
                        f.write("\}")
                    else:
                        s1 = fa.delta[s][a]
                        f.write("&{0:>s}".format(str(s1)))
                f.write("\\\\\n")
        f.write("\end{array}$$")
        f.close()

### Navigation

- index
- modules |
- FAdo 1.2 documentation »
- Module code »