LL(1)文法-------python实现

废话不多说直接开干!

对文法G的句子进行确定的自顶向下语法分析的充分必要条件是,G的任意两个具有相同左部的
产生式A—>α|β 满足下列条件:
(1)如果α、β均不能推导出ε,则 FIRST(α) ∩ FIRST(β) = ∅。
(2)α 和 β 至多有一个能推导出 ε。
(3)如果 β *═> ε,则 FIRST(α) ∩ FOLLOW(A) = ∅。
将满足上述条件的文法称为LL(1)文法。
 
 
概要
第一个L代表从左向右扫描输入符号串,第二个L代表产生最左推导,1代表在分析过程中执行每一步推导都要向前查看一个输入符号——当前正在处理的输入符号。
LL(1)文法既不是二义性的,也不含左递归,对LL(1)文法的所有句子均可进行确定的自顶向下语法分析。
需要注意的是,并不是所有的语言都可以用LL(1)文法来描述,而且不存在判定某语言是否是LL(1)文法的算法。也就是说,确定的自顶向下分析只能实现一部分上下文无关语言的分析,这就是LL(1)文法所产生的语言。另外,在上述LL(1)文法的条件中,要求:ε ∈ FIRST(α1),ε ∈ FIRST(α2),…ε ∈ FIRST(αn) 中至多有一个成立。——————来自百度百科
 
直接代码开搞,首先举个栗子!
处理好之后的文法:
 

 

 然后经过各种推到最后得到

 

 上面那个分析表

万事具备,开始制造东风

直接来个代码

  1 import copy
  2 
  3 strs = ['#', 'E']  # 当做栈来使用,栈是先进后出那我就从-1开始
  4 list1 = [['E->TE\'', '', '', '', '', 'E->TE\'', '', ''],
  5          ['', 'E\'->ATE\'', 'E\'->ATE\'', '', '', '', 'E\'->ε', 'E\'->ε'],
  6          ['T->FT\'', '', '', '', '', 'T->FT\'', '', ''],
  7          ['', 'T\'->ε', 'T\'->ε', 'T\'->MFT\'', 'T\'->MFT\'', '', 'T\'->ε', 'T\'->ε'],
  8          ['F->i', '', '', '', '', 'F->(E)', '', ''],
  9          ['', 'A->+', 'A->-', '', '', '', '', ''],
 10          ['', '', '', 'M->*', 'M->/', '', '', '']
 11          ]
 12 list2 = ['E', 'E\'', 'T', 'T\'', 'F', 'A', 'M']
 13 list3 = ['i', '+', '-', '*', '/', '(', ')', '#']
 14 s1 = ''  # 全局变量s1
 15 
 16 
 17 def out1():
 18     print("分析栈\t\t余留输入串\t\t分析表中产生式")
 19 
 20 
 21 def out2(str1, str2, str3, str4):
 22     print("%s\t\t%s\t\t%s %s" % (str1, str2, str3, str4))
 23 
 24 
 25 str1 = []
 26 str2 = []
 27 str3 = ''
 28 str4 = ''
 29 s1 = input("请输入要分析的字符串:")
 30 s1 += '#'
 31 for i in s1:
 32     str2.append(i)
 33 out1()
 34 
 35 for i in s1:
 36 
 37     while True:
 38         str1 = copy.copy(strs)
 39 
 40         sout = strs.pop()  # 取出最后一个元素
 41 
 42         str3 = 'M[' + sout + ',' + i + ']'
 43         try:
 44 
 45             num1 = list2.index(sout)
 46             num2 = list3.index(i)
 47             if list1[num1][num2] != '':
 48                 schan = list1[num1][num2]
 49                 if schan[-1] == 'ε':
 50                     # strs.pop()
 51                     strs.append(sout)
 52                     str1 = copy.copy(strs)
 53                     num1 = list2.index(strs[-1])
 54                     num2 = list3.index(i)
 55                     schan = list1[num1][num2]
 56                     str4 = schan
 57                     stop1 = 1
 58                     sums = ''
 59                     for j in schan[::-1]:
 60                         if j == '>':
 61                             break
 62                         elif j == '\'':
 63                             sums += j
 64                             stop1 = 2
 65                         else:
 66                             if stop1 == 1:
 67                                 strs.append(j)
 68                             else:
 69                                 sums = j + '\''
 70                                 strs.append(sums)
 71                                 sums = ''
 72                                 stop1 = 1
 73                 else:
 74                     str4 = schan
 75                     stop1 = 1
 76                     sums = ''
 77                     for j in schan[::-1]:
 78                         if j == '>':
 79                             break
 80                         elif j == '\'':
 81                             sums += j
 82                             stop1 = 2
 83                         else:
 84                             if stop1 == 1:
 85                                 strs.append(j)
 86                             else:
 87                                 sums = j + '\''
 88 
 89                                 strs.append(sums)
 90                                 sums = ''
 91                                 stop1 = 1
 92         except:
 93             if False:
 94                 str3 = ''
 95                 str4 = '成功'
 96                 out2(str1, str2, str3, str4)
 97                 break
 98             else:
 99                 str3 = 'Pop'
100                 str4 = 'Nextsym'
101                 strs.pop()
102                 if str1[-1] != 'ε':
103                     out2(str1, str2, str3, str4)
104                     str1.pop()
105                     strs = copy.copy(str1)
106 
107                     break
108                 else:
109                     str1.pop()
110                     str1.pop()
111                     strs = copy.copy(str1)
112         if str2[-1] == '#':
113             if str1[-1] == '#':
114                 str3 = ''
115                 str4 = '成功'
116                 out2(str1, str2, str3, str4)
117                 break
118             elif str1[-1] != '#':
119                 str3 = ''
120                 str4 = '失败'
121                 out2(str1, str2, str3, str4)
122                 break
123             else:
124                 str3 = ''
125                 if str4 != 'Nextsym':
126                     out2(str1, str2, str3, str4)
127         else:
128             out2(str1, str2, str3, str4)
129 
130     str2.pop(0)  # 移除第一个元素

运行结果:

 

 

 

 输出格式有需要的朋友可以自行修改一下!

 

 

里面使用了浅拷贝,为什么要使用浅拷贝呢?原因就是我使用深拷贝错了,关于python的深拷贝和浅拷贝,首先来个官方的介绍:

 

 反正我看的不咋明白,来个实例解释一下吧!开干!!!!

import copy

a = ['a','b','c','d']  # 首先我们定义了一个我们用于操作的数组

b = a  # 此时进行深拷贝

print("这是a的地址" + str(id(a)))
print("这是b的地址" + str(id(b)))
print("a的地址是否和b一样呢?" + str(id(a) == id(b)))

c = copy.copy(a) #此时进行浅拷贝

print("这是a的地址" + str(id(a)))
print("这是c的地址" + str(id(c)))
print("a的地址是否和c一样呢?" + str(id(a) == id(c)))
#然并软貌似看不出啥东西来,你以为这就结束了?醒醒快开学了
#下面来个我的验证方法,网上有好多将这个深拷贝和浅拷贝的但是我没看懂


#进入正题
a.pop()#现在我移除一下a中的最后一个元素
print("a中的元素:"+str(a))
print("深拷贝b中的元素:"+str(b))
print("浅拷贝c中的元素:"+str(c))

运行结果:

 

 

网上有些资料说copy方式复制的是浅拷贝,我也没有去看官方的文档,所以我从定夺,有资料的小伙伴可以发给我一下。

 

posted @ 2020-05-22 09:39  小白打卡  阅读(1883)  评论(8编辑  收藏  举报