实验二 LL(1)语法分析法设计与实现
一、实验目的
加深对LL(1)语法分析器工作过程的理解;加强对预测分析法实现语法分析程序的掌握;能够采用一种编程语言实现简单的语法分析程序;能够使用自己编写的分析程序对简单的程序段进行语法翻译。
二、实验内容
用预测分析法编制语法分析程序,语法分析程序的实现可以采用C、Java或python编程语言和工具。
三、实验要求:
其相应文法为:
E—>TG
T—>FS
G—>+TG|ε
S—>*FS|ε
F—>(E)|i
1、根据LL(1)分析法总控流程图,编写一个语法分析程序,该语法分析程序实现LL(1)算法的分析过程。可根据自己的能力情况,选择以下其中一项作为分析算法的输入:
(1)直接输入根据已知文法构造的分析表M。
(2)输入已知文法的集合FIRST(x)和FOLLOW(U),由程序自动生成该文法的分析表M。
(3)输入已知文法,由程序自动生成该文法的分析表M。
2.展示i+i*i语句的识别过程
四、实验步骤
- 定义目标语言的语法规则;
- 求解预测分析方法需要的符号集和分析表;
- 根据预测分析的方法进行语法分析,直到源程序结束;
本文的中心思想就是定义好两个字典FIRST,FOLLOW集合,用这两个字典去装我们的FIRST集合与FOLLOW集合.后面就是定义相应的函数求解给定文法的FIRST集合与FOLLOW集合。这两个集合我们都进行了去重操作,把集合的重复元素给去了。其实还是应该说就是根据求FIRST集合与FOLLOW集合的原理去求,定义相应的函数,最后把结果放入相应的集合,去重!
FIRST={} FOLLOW={} sentence=[ 'E—>TG', 'T—>FS', 'G—>+TG', 'G—>ε', 'S—>*FS', 'S—>ε', 'F—>(E)', 'F—>i' ] #初始化first集和follow集合字典的键值对中的值位空 def initail(): for str in sentence: part_begin=str.split("—>")[0]#文法前部 part_end=str.split("—>")[1]#文法后部 FIRST[part_begin]=""#文法前部位为字典键,值为空【first集】 FOLLOW[part_begin]="#"#文法前部为字典键,值为#【follow集】 #求first集中第一部分针对->直接推出第一个字符为终结符部分 def getFirst():#first集 for str in sentence: part_begin = str.split("—>")[0] # 文法前部 part_end = str.split("—>")[1] # 文法后部 if not part_end[0].isupper():#判断文法后部开头是否为非终结符 FIRST[part_begin]=FIRST.get(part_begin)+part_end[0]#其实就是初始化的时候给了初始值空字符,现在加上真实first元素 #关键将A->1等,将1写入A的first集合 #求first第二部分针对A->B类型,把B的first集加到A的first集合中去 def getFirst2(): for str in sentence: part_begin='' part_end='' part_begin+=str.split("—>")[0] part_end += str.split("—>")[1] #如果型如A->B 则把B的first集合加入到A的first集合中去 if part_end[0].isupper(): FIRST[part_begin]=FIRST.get(part_begin)+FIRST.get(part_end[0]) #关键如A-》B,则将B的first集加入到A中,【如果B为”“,则A为""】 def getFirst_3(): while(1): test=FIRST getFirst2() #去除重复项 for i,j in FIRST.items(): temp="" for word in list(set(j)): temp+=word FIRST[i]=temp if test==FIRST: break def get_Follow():#首先文法开始符号FOLLOW集合{#} for str in sentence: if str==sentence[0]: continue else: part_begin = str.split("—>")[0] # 文法前部 part_end = str.split("—>")[1] # 文法后部 FOLLOW[part_begin]=FOLLOW[part_begin].replace("#","")#将FOLLOW中含有原有#全清空,仅仅剩下开始符号含有# def bigORsmall(char): bigLIST=[] for i in range(65,91): #print(chr(i)) bigLIST.append(chr(i))#将A-Z加入到大写字典列表 if char in bigLIST: return True else: return False def get_Follow2(): for str in sentence: part_begin = str.split("—>")[0] # 文法前部 part_end = str.split("—>")[1] # 文法后部 length=len(part_end)#文法长度 if length==1: if bigORsmall(part_end):#A->【B】 FOLLOW[part_end]=FOLLOW.get(part_begin)+FOLLOW.get(part_end) else:#A->c continue else:#长度不为1 for i in range(length):#遍历 if i != length-1:#当前不为最后1元素 nowChar=part_end[i] nextChar=part_end[i+1] if bigORsmall(nowChar):#当前元素为大写A->AB if bigORsmall(nextChar):#当前元素为小写A->AB if 'ε' in FIRST.get(nextChar): FOLLOW[nowChar]=FOLLOW.get(nowChar)+FIRST.get(nextChar).replace('ε',"") FOLLOW[nowChar]=FOLLOW.get(nowChar)+FOLLOW.get(part_begin) else: FOLLOW[nowChar] = FOLLOW.get(nowChar)+FIRST.get(nextChar) else:#当前元素为小写A->Ab FOLLOW[nowChar]=FOLLOW.get(nowChar)+nextChar else:#当前元素为A->a if bigORsmall(nextChar):#当前元素为小写A->aB pass else:#A->ab pass else:#当前元素为最后一个元素 nowChar = part_end[i] if bigORsmall(nowChar):#A->XXXC FOLLOW[nowChar]=FOLLOW.get(nowChar)+FOLLOW.get(part_begin) else:#A->xxxc pass def getFOLLOW_3():#此函数是为了去FOLLOW集有重复元素 for key,value in FOLLOW.items(): str='' lists=[] length=len(value) for i in range(length): nowChar=value[i] if nowChar not in lists: lists.append(nowChar) str+=nowChar else: pass FOLLOW[key]=str if __name__ == '__main__': initail() getFirst() getFirst2() getFirst_3() print('FIRST集合为:',FIRST) get_Follow() print('FOLLOW集合为:',FOLLOW) get_Follow2() get_Follow2()#调用两次为了解决有时候开始文法还没完成,又要给到其它FOLLOW集 print('FOLLOW2集合:', FOLLOW) getFOLLOW_3() print('FOLLOW3集合:',FOLLOW)