Ошибка заполнения стека Python. Отбрасывание только одного персонажа - PullRequest
0 голосов
/ 31 марта 2019

Я пишу программу, которая превращает инфикс в постфиксную нотацию и компилирует ее, чтобы превратить в недетерминированные конечные автоматы. Я получаю сообщение об ошибке, в котором говорится, что я пытаюсь получить доступ из пустого стека, но я не знаю, почему он не заполняется должным образом. Извините, если это глупый вопрос, я новичок в Python, но любая помощь будет высоко ценится. Спасибо!

class state:
    label, edge1, edge2 = None, None, None

class NFA:
    initial, accept = None, None

    def __init__(self, initial, accept):
      self.initial, self.accept = initial, accept

# convert infix notation to postfix
def shunt(infix):
    operators = {'*': 30, '+': 30, '?': 30, '.': 20, '|': 10}
    postfix, stack = ' ', ' '

    for c in infix:
        # open brackets are pushed straight to stack
        if c == '(': 
            stack += c
        # discard closing bracket, print inside brackets
        elif c == ')':
            while stack[-1] != '(':
                postfix += stack[-1]
                stack = stack[:-1]
            stack = stack[:-1]
        # operators get pushed to stack
        elif c in operators:
            # pushes operator with higher precedence on the stack
            while stack and operators.get(c, 0) <= operators.get(stack[-1], 0):
                postfix += stack[-1]
                stack = stack[:-1]
            stack += c
        else:
            postfix += c
    # copied from above to run if stack is not empty
    while stack:
        postfix += stack[-1]
        stack = stack[:-1]       
    return postfix

# regular expression compiler
def compile(postfix):
    nfaStack = []

    for c in postfix:
        # join the initial and accept states together to create a loop for your characters
        if c == '*':
            nfa = nfaStack.pop()
            initial, accept = state(), state()

            initial.edge1, nfa.accept.edge1 = nfa.initial, nfa.initial
            initial.edge2, nfa.accept.edge2 = accept, accept
            nfaStack.append(NFA(initial, accept))
        # merge the two automata by linking 1's accept to 2's initial states
        elif c == '.': 
            nfa2, nfa1 = nfaStack.pop(), nfaStack.pop()
            nfa1.accept.edge1 = nfa2.initial
            nfaStack.append(NFA(nfa1.initial, nfa2.accept))       
        # create new initial and accept states and use them to link nfa1 and nfa2
        elif c == '|':
            nfa2, nfa1 = nfaStack.pop(), nfaStack.pop()
            initial, accept = state(), state()
            initial.edge1, initial.edge2 = nfa1.initial, nfa2.initial
            # both old accept states now point to our new accept state
            nfa1.accept.edge1, nfa2.accept.edge1 = accept, accept
            nfaStack.append(NFA(initial, accept))      
        # creates new states and edges; labels each edge with what the current non-special character is
        else:
            initial, accept = state(), state()
            initial.label = c
            initial.edge1 = accept
            # create instance of class nfa()
            nfaStack.append(NFA(initial, accept))   
    # should only ever have one nfa in the stack
    return nfaStack.pop()

print(compile("a|b*"))

compile () должен возвращать адрес памяти, где хранится вновь созданный nfa, но вместо этого он сообщает мне, что стек пуст после того, как вытолкнул только один символ.

...