对于任意的上下文无关文法,编写一个Python程序,读入该文法,判断该文法是否为LL (1)文法:如果是LL (1)文法,则构造并输出该文法的LL (1)分析表
时间: 2024-03-13 11:43:19 浏览: 185
上下无关文法
以下是一个简单的Python程序实现:
```python
# 输入文法
grammar = input("请输入文法(每个产生式一行,用->表示产生式):\n")
# 分离非终结符和终结符
non_terminals = set()
terminals = set()
productions = []
for production in grammar.split('\n'):
if not production:
continue
left, right = production.split('->')
non_terminals.add(left.strip())
for symbol in right.split():
if symbol.isupper():
non_terminals.add(symbol)
elif symbol != 'ε':
terminals.add(symbol)
productions.append((left.strip(), right.split()))
# 计算FIRST集合
first = {}
for symbol in non_terminals | terminals:
first[symbol] = set()
for symbol in terminals:
first[symbol].add(symbol)
for symbol in non_terminals:
first[symbol] = set()
while True:
updated = False
for left, right in productions:
for symbol in right:
if symbol in terminals:
if symbol not in first[left]:
first[left].add(symbol)
updated = True
break
for f in first[symbol]:
if f != 'ε' and f not in first[left]:
first[left].add(f)
updated = True
if 'ε' not in first[symbol]:
break
else:
if 'ε' not in first[left]:
if 'ε' not in first.get('', set()):
first[''].add('ε')
updated = True
if 'ε' not in first[left]:
first[left].add('ε')
updated = True
if not updated:
break
# 计算FOLLOW集合
follow = {symbol: set() for symbol in non_terminals}
follow[grammar[0]] = {'$'}
while True:
updated = False
for left, right in productions:
for i, symbol in enumerate(right):
if symbol in terminals:
continue
rest = set(right[i + 1:])
if not rest or 'ε' in first[rest]:
for f in follow[left]:
if f not in follow[symbol]:
follow[symbol].add(f)
updated = True
for f in first[rest]:
if f != 'ε' and f not in follow[symbol]:
follow[symbol].add(f)
updated = True
if not updated:
break
# 构造LL(1)分析表
table = {}
for left, right in productions:
for symbol in first[right]:
if symbol != 'ε':
table[left, symbol] = right
if 'ε' in first[right]:
for symbol in follow[left]:
table[left, symbol] = right
for symbol in terminals | {'$'}:
table['', symbol] = [('synch',)]
# 判断是否为LL(1)文法
ll1 = True
for left1, right1 in productions:
for left2, right2 in productions:
if left1 != left2:
continue
for symbol1 in first[right1]:
if symbol1 == 'ε':
continue
if (left1, symbol1) in table and table[left1, symbol1] != right1:
ll1 = False
elif (left1, symbol1) not in table:
table[left1, symbol1] = ('synch',)
for symbol2 in first[right2]:
if symbol2 == 'ε':
continue
if (left1, symbol2) in table and table[left1, symbol2] != right2:
ll1 = False
elif (left1, symbol2) not in table:
table[left1, symbol2] = ('synch',)
# 输出结果
if ll1:
print("该文法是LL(1)文法,LL(1)分析表如下:")
print(" " * 7, end='')
for symbol in terminals | {'$'}:
print(f"{symbol:^10}", end='')
print()
for symbol in non_terminals:
print(f"{symbol:5} ->", end='')
for t in terminals | {'$'}:
if (symbol, t) in table:
print(f" {symbol:5} -> {' '.join(table[symbol, t]):5}", end='')
else:
print(" " * 10, end='')
print()
else:
print("该文法不是LL(1)文法!")
```
该程序先读入文法,然后进行文法分析,得到非终结符集合、终结符集合、产生式集合等信息。接着,根据LL(1)文法的定义,依次计算FIRST集合和FOLLOW集合,并根据它们构造出LL(1)分析表。最后,判断该文法是否为LL(1)文法,并输出LL(1)分析表。
阅读全文