Esempio n. 1
0
    def get(self, statediag, accepted=None):
        """
        Replaces complex state IDs as generated from the product operation,
        into simple sequencial numbers. A dictionaty is maintained in order
        to map the existed IDs.
        Args:
            statediag (list): The states of the PDA
            accepted (list): the list of DFA accepted states
        Returns:
            list:
        """
        count = 0
        statesmap = {}
        newstatediag = {}
        for state in statediag:

            # Simplify state IDs
            if statediag[state].id not in statesmap:
                statesmap[statediag[state].id] = count
                mapped = count
                count = count + 1
            else:
                mapped = statesmap[statediag[state].id]

            # Simplify transitions IDs

            transitions = {}
            for nextstate in statediag[state].trans:
                if nextstate not in statesmap:
                    statesmap[nextstate] = count
                    transmapped = count
                    count = count + 1
                else:
                    transmapped = statesmap[nextstate]
                transitions[transmapped] = statediag[state].trans[nextstate]
            newstate = PDAState()
            newstate.id = mapped
            newstate.type = statediag[state].type
            newstate.sym = statediag[state].sym
            newstate.trans = transitions
            newstatediag[mapped] = newstate
        newaccepted = None
        if accepted is not None:
            newaccepted = []
            for accepted_state in accepted:
                if (0, accepted_state) in statesmap:
                    newaccepted.append(statesmap[(0, accepted_state)])
        return newstatediag, count, newaccepted
Esempio n. 2
0
 def _generate_state(self, trans):
     """
     Creates a new POP state (type - 2) with the same transitions.
     The POPed symbol is the unique number of the state.
     Args:
         trans (dict): Transition dictionary
     Returns:
         Int: The state identifier
     """
     state = PDAState()
     state.id = self.nextstate()
     state.type = 2
     state.sym = state.id
     state.trans = trans.copy()
     self.toadd.append(state)
     return state.id
Esempio n. 3
0
    def get(self, statediag, dfaaccepted):
        """
        # - Remove all the POP (type - 2) transitions to state 0,non DFA accepted
        # for symbol @closing
        # - Generate the accepted transitions
        - Replace DFA accepted States with a push - pop symbol and two extra states
        Args:
            statediag (list): The states of the PDA
            dfaaccepted (list):The list of DFA accepted states
        Returns:
            list: A cleaned, smaller list of DFA states
        """

        newstatediag = {}

        newstate = PDAState()
        newstate.id = 'AI,I'  # BECAREFUL WHEN SIMPLIFYING...
        newstate.type = 1
        newstate.sym = '@wrapping'
        transitions = {}
        transitions[(0, 0)] = [0]
        newstate.trans = transitions
        i = 0
        newstatediag[i] = newstate
        # print 'accepted:'
        # print dfaaccepted
        for stateid in statediag:
            state = statediag[stateid]
            # print state.id
            if state.type == 2:
                for state2id in dfaaccepted:
                    # print state.id[1]
                    if state.id[1] == state2id:
                        # print 'adding...'
                        state.trans['AI,I'] = ['@wrapping']
                        # print state.trans
                        break
            i = i + 1
            newstatediag[i] = state
        return newstatediag
Esempio n. 4
0
    def _mkpda(self,
               nonterms,
               productions,
               productions_struct,
               terminals,
               splitstring=1):
        """
        This function generates a PDA from a CNF grammar as described in:
          -  http://www.oit.edu/faculty/sherry.yang/CST229/Lectures/7_pda.pdf
          -  http://www.eng.utah.edu/~cs3100/lectures/l18/pda-notes.pdf

        If all of the grammar productions are in the Chomsky Normal Form,
        then follow the template for constructing a pushdown symautomata:

        1. Start
        2. Push S
        3. Pop
        4. Case:
            Nonterminal A: For every production rule of this form: A: BC, Push C and then Push B

        Args:
             nonterms (list): Non terminals list
             productions (dict): productions in the CNF form:
                                    A -> a or A -> b0b1, or S -> e
             productions_struct (dict):  productions in the CNF form in structure form
                                    object.a for A -> a,
                                    object.b0 and object.b1 for A -> b0b1
                                    and object.type where type is
                                        1 for A-->a and 2 for A-->b0b1
             terminals (list): All terminals
             splitstring (bool): If enabled an extra space is added after each symbol.
        Returns:
            PDA: The generated PDA
        """
        pda = PDA(self.alphabet)
        pda.nonterminals = nonterms
        pda.terminals = terminals

        pda.s[pda.n] = PDAState()
        pda.s[pda.n].id = pda.n
        pda.s[pda.n].sym = '@closing'
        pda.s[pda.n].type = 1
        pda.s[pda.n].trans[1] = [0]

        pda.n = pda.n + 1
        pda.s[pda.n] = PDAState()
        pda.s[pda.n].id = pda.n
        pda.s[pda.n].type = 1
        pda.s[pda.n].sym = nonterms[0]
        pda.s[pda.n].trans[2] = [0]

        pda.n = pda.n + 1
        pda.s[pda.n] = PDAState()
        pda.s[pda.n].id = pda.n
        pda.s[pda.n].type = 2
        pda.s[pda.n].trans[0] = ['@closing']

        counter = 0
        i = 0
        while i < len(nonterms):
            j = 0
            while j < len(productions[nonterms[i]]):
                if productions_struct[counter].type == 1:
                    # ADD AND CONNECT STATE
                    pda.n = pda.n + 1
                    pda.s[pda.n] = PDAState()
                    pda.s[pda.n].id = pda.n
                    if pda.n not in pda.s[2].trans:
                        pda.s[2].trans[pda.n] = []
                    pda.s[2].trans[pda.n].append(nonterms[i])

                    if splitstring == 0:

                        # FILL NEW STATE  READ
                        pda.s[pda.n].type = 3
                        pda.s[pda.n].trans[2] = [productions_struct[counter].a]

                    else:
                        # THE FOLLOWIN SWITCH IS DUE TO THE REQUIREMENT OF
                        # HAVING STRINGS SPLITTED TO SYMBOLS AND CAN INTERSECT
                        # WITH DFA

                        if productions_struct[counter].a not in terminals or \
                                        len(productions_struct[counter].a) == 1:
                            # FILL NEW STATE  READ
                            pda.s[pda.n].type = 3
                            pda.s[pda.n].trans[pda.n + 1] = [
                                productions_struct[counter].a.lower()
                            ]
                            pda.n = pda.n + 1
                            pda.s[pda.n] = PDAState()
                            pda.s[pda.n].id = pda.n
                            pda.s[pda.n].type = 3
                            pda.s[pda.n].trans[2] = [' ']

                        else:
                            pda.s[pda.n].type = 3
                            pda.s[pda.n].trans[pda.n + 1] = \
                                [productions_struct[counter].a[0].lower()]
                            k = 1
                            while k < len(productions_struct[counter].a) - 1:
                                pda.n = pda.n + 1
                                pda.s[pda.n] = PDAState()
                                pda.s[pda.n].id = pda.n
                                pda.s[pda.n].type = 3
                                pda.s[pda.n].trans[pda.n +1] = \
                                    [productions_struct[counter].a[k].lower()]
                                k = k + 1
                            pda.n = pda.n + 1
                            pda.s[pda.n] = PDAState()
                            pda.s[pda.n].id = pda.n
                            pda.s[pda.n].type = 3

                            pda.s[pda.n].trans[pda.n + 1] = \
                                [productions_struct[counter].a[-1].lower()]
                            pda.n = pda.n + 1
                            pda.s[pda.n] = PDAState()
                            pda.s[pda.n].id = pda.n
                            pda.s[pda.n].type = 3
                            pda.s[pda.n].trans[2] = [' ']

                else:
                    # ADD AND CONNECT PUSH STATE
                    pda.n = pda.n + 1
                    pda.s[pda.n] = PDAState()
                    pda.s[pda.n].id = pda.n
                    if pda.n not in pda.s[2].trans:
                        pda.s[2].trans[pda.n] = []
                    pda.s[2].trans[pda.n].append(nonterms[i])

                    # FILL NEW STATE
                    pda.s[pda.n].type = 1
                    pda.s[pda.n].sym = productions_struct[counter].b1
                    pda.s[pda.n].trans[(pda.n) + 1] = [0]

                    # ADD AND CONNECT PUSH STATE (ALREADY CONNECTED)
                    pda.n = pda.n + 1
                    pda.s[pda.n] = PDAState()
                    pda.s[pda.n].id = pda.n

                    # FILL NEW STATE
                    pda.s[pda.n].type = 1
                    pda.s[pda.n].sym = productions_struct[counter].b0
                    pda.s[pda.n].trans[2] = [0]

                j = j + 1
                counter = counter + 1

            i = i + 1
        return pda
Esempio n. 5
0
    def _intesect(self):
        """The intesection of a PDA and a DFA"""
        p1automaton = self.mma
        p2automaton = self.mmb
        p3automaton = PDA(self.alphabet)
        self._break_terms()
        p1counter = 0
        p3counter = 0
        p2states = list(p2automaton.states)
        print 'PDA States: ' + repr(p1automaton.n)
        print 'DFA States: ' + repr(len(list(p2states)))
        ignorechars = p1automaton.nonterminals + [0] + ['@closing']
        del (ignorechars[ignorechars.index('S')])
        while p1counter < p1automaton.n + 1:
            p1state = p1automaton.s[p1counter]
            p2counter = 0
            while p2counter < len(list(p2states)):
                p2state = p2states[p2counter]
                tempstate = PDAState()
                tempstate.id = (p1state.id, p2state.stateid)
                tempstate.sym = p1state.sym
                tempstate.type = p1state.type
                tempstate.trans = {}
                found = 0
                for char in self.alphabet:
                    if char in ignorechars:
                        continue
                    # DFA has single destination from a state
                    p2dest = self._delta(p2automaton, p2state, char)
                    # PDA may have multiple destinations from a state
                    # print p1state.trans
                    if p2dest is not None:
                        for potential in p1state.trans:
                            if char in p1state.trans[potential]:
                                found = 1
                                p1dest = potential
                                if (p1dest,
                                        p2dest.stateid) not in tempstate.trans:
                                    tempstate.trans[(p1dest,
                                                     p2dest.stateid)] = []
                                    # print 'Appending A Transition to
                                    # ('+`p1dest`+','+`p2dest.stateid`+') for
                                    # input '+`char`
                                tempstate.trans[(p1dest,
                                                 p2dest.stateid)].append(char)

                                # THEN THE NONTERMINALS + 0 3 transitions
                                # print p1state.trans
                                #               print p1automaton.nonterminals
                if found == 0 and p1state.type == 3 and len(p1state.trans) > 0:
                    assert 1==1,'Check Failed: A READ state with transitions' \
                                ' did not participate in the cross product'
                if p2dest is not None:
                    for nonterm in p1automaton.nonterminals + \
                            [0] + ['@closing']:
                        for potential in p1state.trans:
                            if nonterm in p1state.trans[potential]:
                                p1dest = potential
                                if (p1dest, p2state.stateid
                                    ) not in tempstate.trans:
                                    tempstate.trans[(p1dest,
                                                     p2state.stateid)] = []
                                # print 'Appending B Transition to
                                # ('+`p1dest`+','+`p2state.stateid`+') for
                                # input '+`nonterm`
                                tempstate.trans[(
                                    p1dest, p2state.stateid)].append(nonterm)
                p3automaton.s[p3counter] = tempstate
                p3counter = p3counter + 1
                p2counter = p2counter + 1
            p1counter = p1counter + 1
        # print 'Total States Appended '+`len(p3automaton.input_string)`
        p3automaton.n = p3counter - 1

        p3automaton.accepted = []
        for state in p2automaton.states:
            if state.final != TropicalWeight(float('inf')):
                p3automaton.accepted.append(state.stateid)
        return p3automaton
Esempio n. 6
0
    def _break_terms(self):
        counter = len(self.mma.s)
        for state in self.mma.s.keys():
            if self.mma.s[state].type == 3:
                for transition in self.mma.s[state].trans.keys():
                    for transition in self.mma.s[state].trans.keys():
                        for record in self.mma.s[state].trans[transition]:
                            if len(record) > 1:
                                value = record
                                i = self.mma.s[state].trans[transition].index(
                                    record)
                                del self.mma.s[state].trans[transition][i]
                                if len(self.mma.s[state].trans[transition]
                                       ) == 0:
                                    del self.mma.s[state].trans[transition]
                                tempstate = PDAState()
                                tempstate.id = counter
                                tempstate.sym = 0
                                tempstate.type = 3
                                tempstate.trans = {}
                                tempstate.trans[transition] = [value[-1]]
                                self.mma.s[counter] = tempstate
                                counter = counter + 1
                                for character in reversed(value[1:-1]):
                                    tempstate = PDAState()
                                    tempstate.id = counter
                                    tempstate.sym = 0
                                    tempstate.type = 3
                                    tempstate.trans = {}
                                    tempstate.trans[counter - 1] = [character]
                                    self.mma.s[counter] = tempstate
                                    counter = counter + 1

                                self.mma.s[state].trans[counter -
                                                        1] = [value[0]]
        self.mma.n = counter - 1
Esempio n. 7
0
    def _combine_push_rest(self):
        """Combining Push and Rest"""
        new = []
        change = 0
        # DEBUG
        # logging.debug('Combining Push and Rest')
        i = 0
        examinetypes = self.quickresponse_types[1]
        for state in examinetypes:
            if state.type == 1:
                for nextstate_id in state.trans.keys():
                    found = 0
                    # if nextstate_id != state.id:
                    if nextstate_id in self.quickresponse:
                        examines = self.quickresponse[nextstate_id]
                        for examine in examines:
                            if examine.id == nextstate_id and examine.type == 3:
                                temp = PDAState()
                                temp.type = 1
                                temp.sym = state.sym
                                temp.id = state.id
                                for nextnextstate_id in examine.trans:
                                    # if nextnextstate_id != examine.id :
                                    for x_char in state.trans[nextstate_id]:
                                        for z_char in examine.trans[
                                                nextnextstate_id]:
                                            if nextnextstate_id not in temp.trans:
                                                temp.trans[
                                                    nextnextstate_id] = []
                                            if x_char != 0 and z_char != 0:
                                                temp.trans[
                                                    nextnextstate_id].append(
                                                        x_char + z_char)
                                                # DEBUGprint 'transition is now
                                                # '+x_char +' + '+ z_char
                                            elif x_char != 0 and z_char == 0:
                                                temp.trans[
                                                    nextnextstate_id].append(
                                                        x_char)
                                                # DEBUGprint 'transition is now
                                                # '+x_char
                                            elif x_char == 0 and z_char != 0:
                                                temp.trans[
                                                    nextnextstate_id].append(
                                                        z_char)
                                                # DEBUGprint 'transition is now
                                                # '+z_char
                                            elif x_char == 0 and z_char == 0:
                                                temp.trans[
                                                    nextnextstate_id].append(0)
                                                # DEBUGprint 'transition is now
                                                # empty'
                                            else:
                                                pass
                                found = 1
                                new.append(temp)

                    if found == 1:
                        # DEBUGprint 'Lets combine one with id
                        # '+`state.id`+'(push) and one with id
                        # '+`nextstate_id`+'(rest)'
                        change = 1
                        del state.trans[nextstate_id]
            i = i + 1
        if change == 0:
            return []
        else:
            return new
Esempio n. 8
0
    def _combine_push_pop(self):
        """Combining Push and Pop"""
        new = []
        change = 0
        # DEBUG
        # logging.debug('Combining Push and Pop')
        i = 0
        examinetypes = self.quickresponse_types[1]
        for state in examinetypes:
            if state.type == 1:
                found = 0
                for nextstate_id in state.trans.keys():
                    # if nextstate_id != state.id:
                    if nextstate_id in self.quickresponse:
                        examines = self.quickresponse[nextstate_id]
                        for examine in examines:
                            secondfound = 0
                            if examine.id == nextstate_id and examine.type == 2:
                                temp = PDAState()
                                temp.type = 3
                                temp.sym = 0
                                temp.id = state.id
                                if examine.sym == 0:
                                    for nextnextstate_id in examine.trans:
                                        # if nextnextstate_id != examine.id :
                                        for z_char in examine.trans[
                                                nextnextstate_id]:
                                            if state.sym == z_char:
                                                for x_char in state.trans[
                                                        nextstate_id]:
                                                    # DEBUGprint state.sym+' vs
                                                    # '+z_char
                                                    if nextnextstate_id not in temp.trans:
                                                        temp.trans[
                                                            nextnextstate_id] = []
                                                    if x_char != 0:
                                                        temp.trans[
                                                            nextnextstate_id].append(
                                                                x_char)
                                                        # DEBUGprint
                                                        # 'transition is now
                                                        # '+x_char
                                                    else:
                                                        temp.trans[
                                                            nextnextstate_id].append(
                                                                0)
                                                        # DEBUGprint
                                                        # 'transition is now
                                                        # empty'

                                                    secondfound = 1

                                elif state.sym == examine.sym:
                                    for nextnextstate_id in examine.trans:
                                        # if nextnextstate_id != examine.id :
                                        for x_char in state.trans[
                                                nextstate_id]:
                                            for z_char in examine.trans[
                                                    nextnextstate_id]:
                                                if nextnextstate_id not in temp.trans:
                                                    temp.trans[
                                                        nextnextstate_id] = []
                                                if x_char != 0 and z_char != 0:
                                                    temp.trans[
                                                        nextnextstate_id].append(
                                                            x_char + z_char)
                                                    # DEBUGprint 'transition is
                                                    # now '+x_char +' + '+ z_char
                                                elif x_char != 0 and z_char == 0:
                                                    temp.trans[
                                                        nextnextstate_id].append(
                                                            x_char)
                                                    # DEBUGprint 'transition is
                                                    # now '+x_char
                                                elif x_char == 0 and z_char != 0:
                                                    temp.trans[
                                                        nextnextstate_id].append(
                                                            z_char)
                                                    # DEBUGprint 'transition is
                                                    # now '+z_char
                                                elif x_char == 0 and z_char == 0:
                                                    temp.trans[
                                                        nextnextstate_id].append(
                                                            0)
                                                    # DEBUGprint 'transition is
                                                    # now empty'
                                                else:
                                                    pass
                                                secondfound = 1

                                if secondfound == 1:
                                    new.append(temp)
                                    found = 1
                    if found == 1:
                        # DEBUGprint 'Lets combine one with id
                        # '+`state.id`+'(push) and one with id
                        # '+`nextstate_id`+'(pop)'
                        change = 1
                        # DEBUGprint 'delete '+`nextstate_id`+' from
                        # '+`state.id`
                        del state.trans[nextstate_id]
            i = i + 1
        if change == 0:
            return []
        else:
            return new