美文网首页
编译原理正规文法与有限自动机转换

编译原理正规文法与有限自动机转换

作者: 吃茶的武士 | 来源:发表于2019-06-24 10:50 被阅读0次

    截图不想放了,我累了。python代码是正确的

    【实验名称】                正规文法与有限自动机的转换    

    【实验目的】

     从文件打开,若文本内为正规文法,则转化为有限自动机,若是合法自动机,则转化为正规文法。

    【实验原理】

     1.文法转自动机

    (1)自动机的字母表与文法的终结符集相同。

    (2)为文法中的每个非终结符生成自动机的一个状态,文法的开始符是S,自动机的开始状态S。

    (3)增加一个新状态Z,作为自动机的终态。

    (4)对文法中的形如A→aB的规则,构造自动机f(A,t)=B。

    (5)对文法中形如A→t的产生式,构造自动机f(A,t)=Z。

    -----------------------------------------------

    2.自动机转文法

    对自动机f(A,t)=B,可写成一个产生式:A→tB

    对终止状态Z,增加一个产生式:Z→ε

    【实验内容】

    1.文法的分割(再上一次实验中也有)

    #按照“|”语法分割

    def splitgram(gram,K,W):

        length=len(gram)

        left=''

        index=0

        while index<length:

            gramindex=gram[index]

            lens=len(gramindex)

            if gramindex[0] not in K:

                K.append(gramindex[0])

                del gram[index]

                j=3

                while j<lens:

                    if gramindex[j]!='|':

                        left=left+gramindex[j]

                    if gramindex[j]=='|':

                        strs=gramindex[0]+'->'+left

                        gram.insert(index,strs)

                        left=''

                    j=j+1

                if  left!='':

                    strs=gramindex[0]+'->'+left

                    gram.insert(index,strs)

                    left=''

            index=index+1

            length=len(gram)

    2.DFA的打印

    def scangram(gram,K,W):

        Kindex=0

        Wdict=dict()

        print('对应的DFA如下:')

        while len(gram)>0:

            gram0=gram[0]

            if gram0[3] not in W:

                W.append(gram0[3])

            if len(gram0)==5:

                printres(gram0[0],gram0[3],gram0[4])

            else:

                if gram0[3] in Wdict:

                    strs=Wdict[gram0[3]]

                    printres(gram0[0],gram0[3],strs)

                else:

                    strs=Klist[Kindex]

                    Kindex=Kindex+1

                    Wdict[gram0[3]]=strs

                    printres(gram0[0],gram0[3],strs)

            del gram[0]

    3.自动机转文法

    def splitFA(FA,Vt,Vn):

        length=len(FA)

        index=0

        while index<length:

            FAindex=FA[index]

            if FAindex[2] not in Vt:

                Vt.append(FAindex[2])

            del FA[index]

            left=FAindex[2]

            right=FAindex[4]+FAindex[7]

            strs=left+'->'+right

            FA.insert(index,strs)

            index=index+1

            length=len(FA)

    #这时候的FA实际上已经由上一步存储为文法了

    def scanFA(FA,Vt,Vn):

        length=len(FA)

        index=0

        while index<length:

            FAindex=FA[index]

            if FAindex[3] not in Vn:

                Vn.append(FAindex[3])

            if len(FAindex)>4 and FAindex[4] not in Vt:

                strs=FAindex[0]+'->'+FAindex[3]

                del FA[index]

                FA.insert(index,strs)

            else:

                index=index+1

            length=len(FA)

    4.合并文法中有相同终结符号的语句

    def combineFA(FA):

        length=len(FA)

        indexi=0

        while indexi<length:

            FAKi=FA[indexi][0]

            lens=len(FA[indexi])-3

            strsi=''

            for i in range(lens):

               strsi=strsi+FA[indexi][3+i]

            indexj=0

            while indexj<length:

                FAKj=FA[indexj][0]

                if indexi!=indexj and FAKi==FAKj:

                    lens=len(FA[indexj])-3

                    strsj=''

                    for j in range(lens):

                        strsj=strsj+FA[indexj][3+j]

                    del FA[indexj]

                    strs=FAKi+'->'+strsi+'|'+strsj

                    del FA[indexi]

                    FA.insert(indexi,strs)

                    length=len(FA)

                    lens=len(FA[indexi])-3

                    strsi=''

                    for i in range(lens):

                        strsi=strsi+FA[indexi][3+i]

                else:

                    indexj=indexj+1

            indexi=indexi+1

    5.打印

    def printFA(FA,Vt,Vn):

        print('对应的左线性RG如下:')

        length=len(FA)

        for i in range(length):

            print(FA[i])

        print('其中终结符集Vt为:')

        print(Vt)

        print('其中非终结符集Vn为:')

        print(Vn)

    【小结或讨论】

    这次的实验和上课的要求还是有很多不一样的,上课的要求比较高,要求进行自动机的确定化,最小化。在实验中都使用了左线性文法,没有考虑比较困难的情况。核心内容就是两个部分的转换:一个是形如“A->aB”到“f(A,a)=B”的转换,另一个是自动机的读取转回为文法。

    【实验截图】

    [if !supportLists]1.  [endif]txt文件中的内容

    [if !supportLists]2.  [endif]功能演示

    [if !supportLists]3.  [endif]代码

    # -*- coding:

    utf-8 -*-

    """

    Created on Sat

    May 25 20:55:21 2019

    @author: 培风

    """

    '''

    1.RG转FA

    (1)M的字母表与G的终结符集相同。

    (2)为G中的每个非终结符生成M的一个状态,G的开始符S是M的开始状态S。

    (3)增加一个新状态Z,作为M的终态。

    (4)对G中的形如A→tB的规则,构造M的一个转换函数f(A,t)=B。

    (5)对G中形如A→t的产生式,构造M的一个转换函数f(A,t)=Z。

    -----------------------------------------------

    2.FA转RG

    对转换函数f(A,t)=B,可写成一个产生式:A→tB

    对可接受状态Z,增加一个产生式:Z→ε

    '''

    Klist=['A']

    #按照“|”语法分割

    def splitgram(gram,K,W):

        length=len(gram)

        left=''

        index=0

        while index<length:

            gramindex=gram[index]

            lens=len(gramindex)

            if gramindex[0] not in K:

                K.append(gramindex[0])

                del gram[index]

                j=3

                while j<lens:

                    if gramindex[j]!='|':

                        left=left+gramindex[j]

                    if gramindex[j]=='|':

                        strs=gramindex[0]+'->'+left

                        gram.insert(index,strs)

                        left=''

                    j=j+1

                if  left!='':

                    strs=gramindex[0]+'->'+left

                    gram.insert(index,strs)

                    left=''

            index=index+1

            length=len(gram)

    #DFA打印为形如f(A,b)->B类型

    def printres(X,Y,Z):

        print('f(%s,%s)=%s'%(X,Y,Z))

    #字典存储打印DFA 

    def scangram(gram,K,W):

        Kindex=0

        Wdict=dict()

        print('对应的DFA如下:')

        while len(gram)>0:

            gram0=gram[0]

            if gram0[3] not in W:

                W.append(gram0[3])

            if len(gram0)==5:

                printres(gram0[0],gram0[3],gram0[4])

            else:

                if gram0[3] in Wdict:

                    strs=Wdict[gram0[3]]

                    printres(gram0[0],gram0[3],strs)

                else:

                    strs=Klist[Kindex]

                    Kindex=Kindex+1

                    Wdict[gram0[3]]=strs

                    printres(gram0[0],gram0[3],strs)

            del gram[0]

    #列表存储自动机“f(S,a)=A”               

    def splitFA(FA,Vt,Vn):

        length=len(FA)

        index=0

        while index<length:

            FAindex=FA[index]

            if FAindex[2] not in Vt:

                Vt.append(FAindex[2])

            del FA[index]

            left=FAindex[2]

            right=FAindex[4]+FAindex[7]

            strs=left+'->'+right

            FA.insert(index,strs)

            index=index+1

            length=len(FA)

    #这时候的FA实际上已经由上一步存储为文法了

    def scanFA(FA,Vt,Vn):

        length=len(FA)

        index=0

        while index<length:

            FAindex=FA[index]

            if FAindex[3] not in Vn:

                Vn.append(FAindex[3])

            if len(FAindex)>4 and FAindex[4] not in Vt:

                strs=FAindex[0]+'->'+FAindex[3]

                del FA[index]

                FA.insert(index,strs)

            else:

                index=index+1

            length=len(FA)

    #合并有相同非终结符的

    def combineFA(FA):

        length=len(FA)

        indexi=0

        while indexi<length:

            FAKi=FA[indexi][0]

            lens=len(FA[indexi])-3

            strsi=''

            for i in range(lens):

               strsi=strsi+FA[indexi][3+i]

            indexj=0

            while indexj<length:

                FAKj=FA[indexj][0]

                if indexi!=indexj and FAKi==FAKj:

                    lens=len(FA[indexj])-3

                    strsj=''

                    for j in range(lens):

                        strsj=strsj+FA[indexj][3+j]

                    del FA[indexj]

                    strs=FAKi+'->'+strsi+'|'+strsj

                    del FA[indexi]

                    FA.insert(indexi,strs)

                    length=len(FA)

                    lens=len(FA[indexi])-3

                    strsi=''

                    for i in range(lens):a

                        strsi=strsi+FA[indexi][3+i]

                else:

                    indexj=indexj+1

            indexi=indexi+1

    #打印自动机

    def printFA(FA,Vt,Vn):

        print('对应的左线性RG如下:')

        length=len(FA)

        for i in range(length):

            print(FA[i])

        print('其中终结符集Vt为:')

        print(Vt)

        print('其中非终结符集Vn为:')

        print(Vn)

    #功能选择:1.正规文法转自动机 2.自动机转正规文法

    n=int(input('选择1.左线性RG转FA 2.FA转左线性RG\n'))

    if n==1:

        fp=open('grammar.txt','r')

        print('读入的左线性正规文法为:')

        gram=[]

        while True:

            line=fp.readline()

            line=line.strip('\n')

            if line=='':

                break

            else:

                gram.append(line)

                print(line)

        K=[] #终结符

        W=[] #非终结符

        splitgram(gram,K,W)

        scangram(gram,K,W) #打印DFA

        print('其中终结符集K为:')

        print(K)

        print('其中非终结符集W为:')

        print(W)

    elif n==2:

        fp=open('FA.txt','r')

        print('读入的FA为:')

        FA=[]

        while True:

            line=fp.readline()

            line=line.strip('\n')

            if line=='':

                break

            else:

                FA.append(line)

                print(line)

        Vt=[]

        Vn=[]

        splitFA(FA,Vt,Vn)

        scanFA(FA,Vt,Vn)

        combineFA(FA)

        printFA(FA,Vt,Vn)

    else:

        print("输入无效")

    相关文章

      网友评论

          本文标题:编译原理正规文法与有限自动机转换

          本文链接:https://www.haomeiwen.com/subject/xgrnqctx.html