Esempio n. 1
0
    def generateAP(self, string):
        stack = Stack()
        marker = True
        returnTransition = []
        returnProductions = []
        newTransition = ''
        newString = ''

        # Variables de graphviz
        arrayEdges = []
        nodeTemp = ''
        nodeParent = {}
        nodesParents = []
        dot = Digraph(comment=f"{self.getName()}", format="png")
        dot.attr(rankdir='TB', size='8,5')
        dot.attr('node', shape='circle')

        print(f"Cadena a evaluar: {string}")
        print(f"En la pila hay {stack.getItems()}")
        self.generateReport('epsilon', string, self.transitions[0]['string'])
        newString = string

        j = 65
        for transition in self.transitions:
            if transition["first"]["from"] == "p":
                stack.push(transition["last"]["input"])

                # Hacemos el grafo un estado inicial
                dot.node(chr(j), transition["last"]["input"])
                if stack.getLastItem() in self.getNonTerminals():
                    nodeParent['key'] = chr(j)
                    nodeParent['value'] = stack.getLastItem()
                    nodesParents.append(nodeParent)
                    nodeParent = {}
                nodeTemp = chr(j)
                j = j + 1

                break

        newTransition = transition['string']

        if ' ' in string:
            string = string.split(' ')

        i = 0
        for letter in string:
            indicator = False
            if i >= 2:
                string = string[1:]
                newString = list(string)
                if len(string) > 0:
                    newString.pop(0)

            if letter in self.terminals:
                for transition in self.transitions:
                    if transition["first"]["from"] == "q":
                        if stack.getLastItem(
                        ) == transition["first"]["output"]:
                            if letter == transition['last']['input'][0]:
                                newTransition = transition['string']
                                stack.pop()
                                word = transition["last"]["input"][::-1]
                                for l in word:
                                    indicator = True
                                    stack.push(l)

                                if stack.getItems() == 'epsilon':
                                    marker = False
                                    print("Cadena Invalida")
                                    returnTransition.append("Cadena Invalida")
                                    break
                            else:
                                continue
                        else:
                            for trans in self.transitions:
                                if (trans["first"]["output"] ==
                                        stack.getLastItem()):
                                    if (letter == trans["last"]["input"][0] or
                                            letter == trans["last"]["input"]):
                                        newTransition = trans['string']

                                        # Asignamos el siguiente contador a la letra y
                                        # lo metemos en el array concatenado a la letra temporal
                                        dot.node(chr(j), stack.getLastItem())
                                        # Guardamos los nodos padres clave: valor en un array
                                        if stack.getLastItem(
                                        ) in self.getNonTerminals():
                                            nodeParent['key'] = chr(j)
                                            nodeParent[
                                                'value'] = stack.getLastItem()
                                            nodesParents.append(nodeParent)
                                            nodeParent = {}
                                        # Agregamos un nuevo nodo al array de nodos
                                        arrayEdges.append(nodeTemp + chr(j))
                                        j = j + 1

                                        stack.pop()

                                        if len(letter) > 1:
                                            stack.push(letter)
                                        else:
                                            word = trans["last"]["input"][::-1]
                                            for l in word:
                                                stack.push(l)

                                        print(
                                            f"Pila actual: {stack.getItems()}")
                                        self.generateReport(
                                            stack.getItems(), newString,
                                            newTransition)
                                        returnTransition.append(
                                            stack.getLastItem())
                                        indicator = True
                                        break

                                    if trans["last"]["input"] == 'epsilon':

                                        # Mandamos un nodo con lo que sale
                                        dot.node(chr(j), letter)
                                        arrayEdges.append(nodeTemp + chr(j))
                                        # Termino de nodo

                                        newTransition = trans['string']
                                        self.generateReport(
                                            stack.getItems(), newString,
                                            newTransition)
                                        stack.pop()
                                        indicator = True
                                        break

                                    if trans["last"]["input"][
                                            0] in self.non_terminals:
                                        newTransition = trans['string']
                                        self.generateReport(
                                            stack.getItems(), newString,
                                            newTransition)
                                        stack.pop()
                                        for l in trans["last"]["input"][::-1]:
                                            stack.push(l)
                                        indicator = True
                                        break

                            if not indicator:
                                marker = False
                                break

                            if letter == stack.getLastItem():
                                break

                            if trans['first']['output'] == letter:
                                break

                    print(f"Pila actual: {stack.getItems()}")
                    returnTransition.append(stack.getLastItem())
                    # self.generateReport(stack.getItems(), newString, newTransition)

                    # if not indicator:
                    #     marker = False
                    #     break

                    if stack.getItems() == 'epsilon':
                        marker = False
                        print("Cadena Invalida")
                        returnTransition.append("Cadena Invalida")
                        break

                if marker == False:
                    break

                if letter == stack.getLastItem():
                    if stack.getLength() > 1:
                        nodeChild = letter
                        stack.pop()

                        for parent in nodesParents:
                            if stack.getLastItem() in parent['value']:
                                dot.node(chr(j), nodeChild)
                                arrayEdges.append(parent['key'] + chr(j))
                                nodeTemp = parent['key']
                                break

                if len(stack.getItems()) == 0:
                    break

            else:
                print(f"La letra {letter} no existe en el alfabeto")
                returnTransition.append("Cadena Invalida")
                break

            i = i + 1
            j = j + 1

        if marker:
            if len(stack.getItems()) > 0:
                while True:
                    if len(stack.getItems()) == 0:
                        break
                    for trans in self.transitions:

                        if (trans["first"]["output"] == stack.getLastItem()):
                            if trans['first']['readed'] == 'epsilon' or trans[
                                    'last']['input'] == 'epsilon':
                                print(f"Pila actual: {stack.getItems()}")
                                returnTransition.append(stack.getLastItem())
                                newTransition = trans['string']
                                self.generateReport(stack.getItems(),
                                                    '--------', newTransition)
                                stack.pop()
                                break

        if marker:
            print('Cadena Valida')
            returnTransition.append("Cadena Valida")

            if len(stack.getItems()) == 0:
                self.generateReport('epsilon', '---------',
                                    'q,epsilon,epsilon;f,epsilon')
                self.generateReport('-------', '---------', 'Aceptacion')
            else:
                self.generateReport(stack.getItems(), string, 'Aceptacion')
        else:
            print("Cadena Invalida")

        dot.edges(arrayEdges)
        dot.render(filename="three")
        return returnTransition