将NFA碎片连接在一起(Thompson)

时间:2018-06-18 20:19:53

标签: python regex algorithm nfa

我已经阅读了很多关于NFA和DFA的内容,我想在Python中实现一个。我之所以选择Python,是因为它在模拟算法时非常有用。因此,使用Thompson的构造算法,我使用它们的转换实现了状态,并且还构建了表示正则表达式的不同部分的NFA片段。一个用于符号转换,一个用于连接。除了我被困在连接部分之外,因为我试图“粘合”在一起的状态不匹配,并且它们指向不同的对象。

Thompson's algorithm for concatenation

这应该是它,但对我来说q0的{​​{1}}起始节点没有转换到它的结束节点,即N(s)起始节点。

这是我的代码,为简单起见,所有文件都在一个文件中:

N(t)

输出:

class State(object):

def __init__(self, label, isfinish, trans):
    self.label = label
    self.trans = trans
    self.isfinish = isfinish
    self.id = label + str(id(self))

NFA_SIMULATE_RUN = False

class NFA(object):

    def __init__(self, tup):
        self.Q = tup[0]
        self.S = tup[1]
        self.start = tup[2]
        self.end = tup[3]
        self.table = {}

        for state in self.Q:
            trans_list = {}
            if not state.isfinish:
                for sym in state.trans.keys():
                    trans_list[sym] = state.trans[sym]
            self.table[state] = trans_list

    def move(self, state, sym):
        assert(state in self.Q),(state + " is not in state set")
        assert(sym in self.S),(sym + " is not in alphabet")
        if sym not in self.table.keys():
            if '' in self.table.keys():
                sym = ''
        possible_states = self.table[state][sym]
        if NFA_SIMULATE_RUN:
            i = random.randint(0, len(possible_states) - 1)
            chosen_state = possible_states[i]
            return chosen_state
        return possible_states

    def accepts(self, string):
        curstate = self.start
        for ch in string:
            curstate = self.move(curstate, ch)
        if curstate.isfinish:
            print(string + " accepted!")
        else:
            print(string + " rejected!")

class SymbolNFA(NFA):

    def __init__(self, sym):
        self.end = State('qf', True, {})
        self.start = State('q0', False, {
            sym: self.end
        })
        self.Q = [self.start, self.end]
        self.S = [sym]
        super(SymbolNFA, self).__init__((self.Q, self.S, self.start,                 self.end))

class ConcatNFA(NFA):

    def __init__(self, nfa1, nfa2):
        self.end = nfa2.end
        nfa1.end = nfa2.start
        self.start = nfa1.start
        self.Q = [self.start, nfa1.end, self.end]
        self.S = list(set(nfa1.S) | set(nfa2.S))
        super(ConcatNFA, self).__init__((self.Q, self.S, self.start,     self.end))



def main():
    nfa1 = SymbolNFA('a')
    nfa2 = SymbolNFA('b')
    nfa3 = ConcatNFA(nfa1, nfa2)
    print("NFA 1:\n" + str(nfa1.table))
    print("NFA 2:\n" + str(nfa2.table))
    print("NFA 3:\n" + str(nfa3.table))

if __name__ == '__main__':
    main()

(对不起对象打印,我还没弄清楚如何协调所有状态。)

正如您所看到的,对于前2个Nfa,符号片段,它们的开始状态通过符号正确转换到结束状态对象。但是当我连接它们时,在第一次转换后指定的状态(在这种情况下为'a')不是中间状态,(第一个nfa的结束,第二个nfa的开始)。它指向一些我无法找到的随机状态对象。 “b”转换后指定的状态是正确的,并正确指向整个nfa的结束状态。

为了更好地理解输出,只需将其解释为FA转换表。

任何帮助都表示赞赏,我会告诉您,这是我最初几次使用此类算法,所以我可能会遗漏一些东西。

0 个答案:

没有答案