LL(1) 文法

本文介绍了一个用于处理LL(1)文法的Python程序,包括First集、Follow集的计算,LL(1)文法分析表的构造以及输入符号串的LL(1)文法分析。通过输入文法规则,程序可以求解非终结符的First集和Follow集,并判断文法是否为LL(1)文法。同时,程序还提供了文法分析表的构建和输入表达式的分析功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

  1. 问题描述:

    输入:文法的多个产生式或产生式选项

    输出:(1)    产生式中非终结符的First集和Follow集

         (2)    判断该文法是否是LL(1)文法

         (3)    建立LL(1)文法的分析表

         (4)    对输入的符号串进行LL(1)文法分析,并给出分析结果

    二、解决思路:

    (1)First集的求解:

    对G中每个文法符号XÎVT∪VN,构造 FIRST(X)。连续使用下述规则,直至每个FIRST集合不再增大:

    a、若XÎ VT,则FIRST(X)={X};

    b、若XÎ VN,且有产生式X®a…,则把a加入FIRST(X) ;若X®e也是一条产生式,则把e也加入

    c、若X®Y…是一个产生式且YÎ VN,则把FIRST(Y)中的所有非e元素都加入FIRST(X)中;若X®Y1Y2…Yk是一个产生式,Y1,Y2,…,Yi-1都是非终结符,而且,对任意j(1≤j≤i-1),FIRST(Yj)都含有e,则把FIRST(Yi)中的所有非e元素加入FIRST(X)中;特别是,若所有的FIRST(Yj)均含有e,j=1, 2, …,k, 则把e加入FIRST(X)中

    (2)Follow集的求解:

    对G中每个非终结符A,构造FOLLOW(A)。连续使用下述规则,直至每个FOLLOW不再增大:

    a、对文法的开始符号S,置$于FOLLOW(S)中;

    b、若A®aBb是一个产生式,则把FIRST(b)\{e}加入FOLLOW(B);

    c、若A®aB是一个产生式,或A®aBb是一个产生式而bÞe,则把FOLLOW (A)加入FOLLOW(B)

    (3) 构造M[A, a]

    a、对文法G的每个产生式A®a,执行第2步和第3步;

    b、对每个终结符aÎFIRST(a),把A®a加入M[A, a];

    c、若eÎFIRST(a),则对任何bÎFOLLOW(A)把A®a加入M[A,b]中

    d、所有无定义的M[A, a]标上“出错标志”。

    (4) 文法分析程序的过程:

    文法分析表是一个M[A, a]形式的矩阵,A为非终结符,a是终结符或“#” (结束符)。矩阵元素M[A, a]中存放着一条关于A的产生式,指出当A面临输入符号a时所采用的候选,M[A, a]中可能存放着一个“出错标志”,指出A根本不该面临输入符号a。栈STACK存放文法符号,栈底先放一个“#”,然后,放进文法开始符号,同时,假定输入串之后也总有一个“#”,标志输入串的结束。文法分析程序的总控程序在任何时候都是按STACK栈顶符号X和当前的输入符号a行事的。对于任何(X,a),总控程序每次都执行下面三中可能的动作之一:

    a、若X=a=‘#’,则分析成功,并停止分析过程

    b、若X=a¹‘#’,则把X从STACK栈顶逐出,让a指向下一个输入符号

    c、若X是一个非终结符,则查表M。若M[A,a]中存在产生式,则逐出X,然后把产生式右部符号串反序入栈,同时应做这个产生式相应的语义动作。若M[A,a]中存放出错标志,则调用ERROR。

     

    三、算法的设计与实现

    #!/usr/bin/env python

    # -*- coding:GBK  -*-

    NonTermSet = set() #非终结符集合

    TermSet = set() #终结符集合

    First = dict() #First集

    FirstA = dict() #First[a]集

    Follow = dict() #Follow集

    GramaDict = dict() #处理过的产生式

    AnalysisList = dict() #分析表

    StartSym = "" #开始符号

    Epsilon = "~" #由于没有epsilon符号用“~”代替

    EndSym = '#' 结束符号为“#“

    #获取First集

    def getFirst():

        global NonTermSet,TermSet, First, Follow, FirstA

        for A in NonTermSet:First[A] = set() #初始化非终结符First集为空

        for A in TermSet:First[A] = set(A)#初始化终结符First集为自己

        Change = True

        while Change: #当First集没有更新则算法结束

            Change = False

            for A inNonTermSet:

                for X inGramaDict[A]:

                    k = 0

                    FirstA[X]= set()

                    Continue= True

                    whileContinue and k < len(X): #FirstA[X] = FirstA[a]

                       FirstA[X] |= First[X[k]] - set(Epsilon)

                        ifnot First[X[k]] - set(Epsilon) <= First[A]:

                           First[A] |= First[X[k]] - set(Epsilon)

                           Change = True

                        ifEpsilon not in First[X[k]]: Continue = False

                        k +=1

                    ifContinue == True:

                       First[A] |= set(Epsilon)

                       FirstA[X] |= set(Epsilon)

     

    #构造Follow集

    def getFollow():

        global NonTermSet,TermSet, First, Follow, StartSym

        for A in NonTermSet:Follow[A] = set()

       Follow[StartSym].add(EndSym) #将结束符号加入Follow[开始符号]中

        Change = True

        while Change: #当Follow集没有更新算法结束

            Change = False

            for A inNonTermSet:

                for X inGramaDict[A]:

                    for i inxrange(len(X)):

                        ifX[i] in TermSet:continue

                        Flag= True

                        for jin xrange(i+1, len(X)):

                           if not First[X[j]] - set(Epsilon) <= Follow[X[i]]:

                               Follow[X[i]] |= First[X[j]] - set(Epsilon)

                               Change = True

                           if Epsilon not in First[X[j]]: Flag = False

                        ifFlag == True:

                           if not Follow[A] <= Follow[X[i]]:

                                Follow[X[i]] |= Follow[A]

                               Change = True

    def columnarDisplay(list, colwidth=17) :

        for item in list:

            print item + ''*(colwidth - len(item)),

        print ''

    #构造分析表

    def getAnalysisList():

        #global NonTermSet,TermSet, First, Follow, StartSym, AnalysisList

        for nt in NonTermSet:

            AnalysisList[nt]= dict()

            row =AnalysisList[nt]

            flag = True

            for X inGramaDict[nt]:

                for a inFirstA[X]:

                    ifrow.has_key(a):

                        print'error'

                       exit(0)  

                    row[a] ="%s"%(X)

                if Epsilon inFirstA[X] and flag:

                    flag =False

                    for a inFollow[nt]:

                        ifrow.has_key(a):

                           print 'error'

                           exit(0)  

                       row[a] = "%s"%(X)

    #分析表达式过程

    def Analysis():

        #global AnalysisList

        sta = []

        sta.append(EndSym)

        sta.append(StartSym)

        ss = raw_input("输入表达式:\n")

        head =["Stack","StackTop","Input","Action"]

        columnarDisplay(head)

        idx = 0

        sta_top = sta.pop()

        while sta_top !=EndSym and idx < len:

            if sta_top ==Epsilon:

                sta_top =sta.pop()         

            elif sta_top inTermSet and ss[idx] == sta_top:

                disp =[''.join(sta),sta_top,ss[idx:],"Accept "+sta_top]

               columnarDisplay(disp)

                idx += 1

                sta_top =sta.pop()

            elif sta_top inNonTermSet and ss[idx] in TermSet and AnalysisList[sta_top].has_key(ss[idx]):

                disp =[''.join(sta),sta_top,ss[idx:],sta_top+"->"+AnalysisList[sta_top][ss[idx]]]

               columnarDisplay(disp)

                for Xi inAnalysisList[sta_top][ss[idx]][::-1]:

                   sta.append(Xi)

                sta_top =sta.pop()

            else:

                break

        if sta_top == EndSymand ss[idx] == EndSym:

                print'Accept'

        else:

            print 'AnalysisError'

    #测试驱动

    def preCode():

        global NonTermSet,TermSet, First, Follow, StartSym, AnalysisList

        n = raw_input("输入规则个数:\n")

        n = int(n)

        print '输入规则\n'

        for i in xrange(n):

            A, X =raw_input().split('->')

            NonTermSet.add(A)

            X = X.split('|')

            for Xi in X:TermSet |= set(Xi)

            if not GramaDict.has_key(A):

                GramaDict[A]= set()

            GramaDict[A] |=set(X)

        TermSet -= NonTermSet

        print 'Nonterminalset:', NonTermSet

        print 'Terminalset:', TermSet - set(Epsilon)

        StartSym =raw_input("输入开始符号:\n")

        getFirst()

        getFollow()

        print "FIRSTSET"

        for k in NonTermSet:

            print k, ': ',First[k]

        print ''

        print "FOLLOWSET"

        for k, v inFollow.items():

            print k, ': ', v

        print ''

        getAnalysisList()

        TermSet -=set(Epsilon)

        TermSet |=set(EndSym)

        columnarDisplay(['']+list(TermSet), 10)

        for A in NonTermSet:

            disp = []

            disp.append(A)

            for a in TermSet:

                ifAnalysisList[A].has_key(a):

                   disp.append(A+'->'+AnalysisList[A][a])

                else :disp.append(" ")

           columnarDisplay(disp, 10)

        print ''

        Analysis()

    preCode()

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值