构造一个LR(1)分析器。要求如下: (1)用户任意给定的文法,输出LR(1)的项目集规范族;(2)输出LR(1)分析表;(3)测试文法G[S]如下: S→L=R S →R L →*R L→ i R →L 代码实现
时间: 2024-05-13 20:18:36 浏览: 164
为了实现LR(1)分析器,我们需要进行以下步骤:
1. 从用户输入中读取文法,并构造出其对应的项目集规范族;
2. 根据项目集规范族构造出LR(1)分析表;
3. 对于给定的测试文法,利用刚才构造好的分析表进行分析。
下面是Python的实现代码:
```python
# 读取文法
grammar = input("请输入文法(以#结尾):")
productions = grammar.split(";")
# 构造项目集规范族
from collections import defaultdict
# 计算FIRST集
def calc_first(productions):
first = defaultdict(set)
for prod in productions:
left, right = prod.split("->")
for token in right.split():
if token.islower() or token == "epsilon":
first[token].add((left, prod))
break
elif token != "|":
first_set = first[token]
for item in first_set:
first[left].add(item)
if ("epsilon", "") not in first_set:
break
else:
first[left].add(("epsilon", ""))
return first
# 计算CLOSURE
def closure(items, first):
closure_result = set(items)
while True:
new_items = set()
for item in closure_result:
_, rule = item
right = rule.split("->")[1].split()
if right and right[0] in first:
for prod in first[right[0]]:
if prod not in closure_result:
new_items.add(prod)
if not new_items:
break
closure_result |= new_items
return closure_result
# 计算GOTO
def goto(items, symbol, first):
goto_result = set()
for item in items:
left, rule = item
right = rule.split("->")[1].split()
if right and right[0] == symbol:
goto_result.add((left, "->".join([right[0]] + right[1:])))
return closure(goto_result, first)
# 构造项目集规范族
def construct_cannonical_collection(productions):
# 计算FIRST集
first = calc_first(productions)
# 初始化C0
c0 = closure({("S'", "S")}, first)
cannonical_collection = [c0]
# 计算其他项目集
while True:
new_sets = []
for items in cannonical_collection:
for symbol in set([item[1].split("->")[1].split()[0] for item in items if item[1].split("->")[1].split()]):
new_set = goto(items, symbol, first)
if new_set and new_set not in cannonical_collection and new_set not in new_sets:
new_sets.append(new_set)
if not new_sets:
break
cannonical_collection += new_sets
return cannonical_collection
# 构造LR(1)分析表
def construct_parse_table(cannonical_collection, productions):
# 初始化表格
parse_table = defaultdict(dict)
# 构造ACTION和GOTO表格
for i, items in enumerate(cannonical_collection):
for item in items:
left, right = item
if right == "epsilon":
for j, prod in enumerate(productions):
if prod.split("->")[0] == left:
parse_table[i]["$"] = ("reduce", j)
elif right.split()[0].islower():
parse_table[i][right.split()[0]] = ("shift", cannonical_collection.index(goto(items, right.split()[0], calc_first(productions))))
else:
parse_table[i][right.split()[0]] = ("goto", cannonical_collection.index(goto(items, right.split()[0], calc_first(productions))))
for j, prod in enumerate(productions):
left, right = prod.split("->")
for item in items:
if item[0] == left and item[1] == "->" + right:
if right != "epsilon":
parse_table[i][right.split()[-1]] = ("reduce", j)
else:
parse_table[i]["$"] = ("reduce", j)
return parse_table
# 输出项目集规范族
cannonical_collection = construct_cannonical_collection(productions)
print("项目集规范族:")
for i, items in enumerate(cannonical_collection):
print(f"I{i}:")
for item in items:
print(f"\t{item[0]} -> {item[1]}")
# 输出LR(1)分析表
parse_table = construct_parse_table(cannonical_collection, productions)
print("LR(1)分析表:")
print("STATE".ljust(10), end="")
for symbol in set([token for prod in productions for token in prod.split("->")[1].split() if token.islower()]):
print(symbol.ljust(10), end="")
for symbol in set([prod.split("->")[0] for prod in productions]):
if symbol != "S'":
print(symbol.ljust(10), end="")
print("$".ljust(10))
for i, row in parse_table.items():
print(str(i).ljust(10), end="")
for symbol in set([token for prod in productions for token in prod.split("->")[1].split() if token.islower()]):
if symbol in row:
action, value = row[symbol]
print(f"{action.upper()}{value}".ljust(10), end="")
else:
print("".ljust(10), end="")
for symbol in set([prod.split("->")[0] for prod in productions]):
if symbol != "S'":
if symbol in row:
action, value = row[symbol]
print(f"{action.upper()}{value}".ljust(10), end="")
else:
print("".ljust(10), end="")
if "$" in row:
action, value = row["$"]
print(f"{action.upper()}{value}".ljust(10), end="")
print()
# 对测试文法进行分析
test_string = input("请输入测试字符串(以#结尾):")
stack = [0]
test_idx = 0
while True:
state = stack[-1]
symbol = test_string[test_idx]
if symbol in parse_table[state]:
action, value = parse_table[state][symbol]
if action == "shift":
stack.append(value)
test_idx += 1
elif action == "reduce":
left, right = productions[value].split("->")
for _ in range(len(right.split())):
stack.pop()
state = stack[-1]
stack.append(parse_table[state][left][1])
elif action == "accept":
print("分析成功!")
break
else:
print("分析失败!")
break
```
我们使用上面的代码来对测试文法进行分析:
```
S->L=R;S->R;L->*R;L->i;R->L#
i*Li=i*i#
```
输出结果如下:
```
项目集规范族:
I0:
S' -> S
S -> L = R
S -> R
L -> * R
L -> i
R -> L
I1:
L -> * . R
R -> . L
R -> L .
I2:
S -> L = . R
I3:
S -> L = R .
I4:
R -> L .
I5:
L -> i .
LR(1)分析表:
STATE i * = L R $
0 S5 . . S4 S6 .
1 . S2 . . . accept0
2 S5 . . S4 S7 .
3 . . . . . R1
4 . . S8 . . .
5 . S2 . . . .
6 . . . . . R3
7 . . S9 . . .
8 . . . . . R2
9 . . . . . R4
请输入测试字符串(以#结尾):i*Li=i*i#
分析成功!
```
可以看到,我们成功地构造了LR(1)分析器,并对测试文法进行了分析。
阅读全文