Example #1
0
def nfa_to_dfa(nfa):

    dfa = DFA(set(nfa.alphabet))

    def e_colsure(state_set):
        # 能够从NFA状态T开始只通过ε转换到达的NFA状态集合
        if not isinstance(state_set, set):
            raise Exception('state_set must be set')
        queue = list(state_set)
        result = set(state_set)
        while queue:
            h = queue.pop(0)
            for state in h.get_transfer(Epsilon):
                if state not in result:
                    result.add(state)
                    queue.append(state)
        return result

    def move(state_set, symbol):
        result = set()
        for s in state_set:
            result = result.union(set(s.get_transfer(symbol)))
        return result
    state_set_to_node = {}
    start = tuple(e_colsure(set([nfa.S])))
    state_set_to_node[start] = dfa.S
    queue = [start]
    while queue:
        h = queue.pop(0)
        for symbol in nfa.alphabet:
            new_set = tuple(e_colsure(move(set(h), symbol)))
            if not new_set:
                continue
            if new_set not in state_set_to_node:
                node = dfa.create_node()
                node.data['token'] = set()
                state_set_to_node[new_set] = node
                for state in new_set:
                    # if state in nfa.final_state:
                    if state.data:
                        node.data['token'].add(state.data['token'])
                queue.append(new_set)
            dfa.add_transfer(state_set_to_node[h], symbol,
                             state_set_to_node[new_set])

    return dfa
Example #2
0
def create_lr_dfa(final, syntaxs, vn, vt):
    if vn.intersection(vt):
        raise Exception('VN and VT has intersection')
    else:
        alptabet = list(vn) + list(vt)
    productions = {}
    for syntax in syntaxs:
        if syntax[0] not in productions:
            productions[syntax[0]] = []
        productions[syntax[0]].append(syntax)
    # print 'productions:'
    # print productions
    items_set_to_node = {}  # tuple to Node
    first = {}
    nullable = {}

    getting_nullable = set()

    def get_nullable(item):  # 判断一个非终结符是否可以为Epsilon
        if not isinstance(item, str):
            raise Exception('item is not str')
        if item not in vn:
            raise Exception('item not in vn')
        if item in nullable:
            return nullable[item]
        if item in getting_nullable:
            nullable[item] = False
            return nullable[item]
        getting_nullable.add(item)
        nullable[item] = False
        for production in productions[item]:
            _nullable = True
            for t in production[1:]:
                if t in vt:
                    _nullable = False
                else:
                    _nullable &= get_nullable(t)
            nullable[item] |= _nullable
        getting_nullable.remove(item)
        return nullable[item]

    getting_first = set()

    def get_first(item):  # 获取first集,返回set
        if not isinstance(item, tuple):
            raise Exception('item is not tuple')
        if item in first:
            return first[item]
        getting_first.add(item)
        first[item] = set()
        for t in item:
            if t in vt:
                first[item].add(t)
                break
            else:
                for production in productions[t]:
                    if production[0] in vt:
                        first[item].add(production[0])
                    elif production[1:] not in getting_first:
                        first[item] = first[item].union(
                            get_first(production[1:]))
            if not get_nullable(t):
                break
        getting_first.remove(item)
        return first[item]

    def closure(item, item_set):
        pos, production, ahead = item
        # print 'pos,production,ahead:'
        # print pos,production,ahead
        right_part = production[pos + 1:]
        # print right_part
        if not right_part or right_part[0] not in vn:
            return
        for production in productions[right_part[0]]:
            new_set = set()
            for t in ahead:
                new_set = new_set.union(get_first(right_part[1:] + (t,)))
            new_item = (0, production, tuple(new_set))
            if new_item not in item_set:
                item_set.add(new_item)
                closure(new_item, item_set)

    # create the start Node
    init_item = (0, (final + '\'', final), ('#',))
    init_set = set()
    init_set.add(init_item)
    closure(init_item, init_set)
    dfa = DFA(set(alptabet))
    dfa.S.data = tuple(init_set)
    items_set_to_node[dfa.S.data] = dfa.S

    # start to build dfa
    queue = [dfa.S]
    while queue:
        head = queue.pop(0)
        # print 'head %4d' % head.index
        for symbol in alptabet:
            # print symbol
            new_set = set()
            for item in head.data:
                pos, production, ahead = item
                # print 'production, production[pos + 1: pos + 2]:'
                # print production, production[pos + 1]
                if (pos + 1 < len(production) and
                        production[pos + 1] == symbol):
                    new_item = (pos + 1, production, ahead)
                    new_set.add(new_item)
                    closure(new_item, new_set)

            new_set = tuple(new_set)
            if not new_set:
                continue
            if new_set not in items_set_to_node:
                node = dfa.create_node()
                node.data = new_set
                items_set_to_node[new_set] = node
                queue.append(node)
            dfa.add_transfer(head, symbol, items_set_to_node[new_set])
            print "%d ----%10s---->%d" % (head.index, symbol,
                                          items_set_to_node[new_set].index)

    # print '-----------items_set--------------'
    # for item in dfa.states[6].data:
    #     print item
    # raise Exception('')
    return dfa