LR0分析程序的设计与实现代码
时间: 2023-08-13 19:08:31 浏览: 52
以下是一个简单的 LR(0) 分析程序的设计与实现代码,用 Python 语言实现:
```python
# LR(0) 分析程序
# 标识符常量
SHIFT = 1
REDUCE = 2
ACCEPT = 3
ERROR = 4
# 产生式类
class Production:
def __init__(self, head, body):
self.head = head
self.body = body
# 项目类
class Item:
def __init__(self, production, dot):
self.production = production
self.dot = dot
def __eq__(self, other):
return self.production == other.production and self.dot == other.dot
def __hash__(self):
return hash(str(self.production) + str(self.dot))
# LR(0) 分析表类
class LR0Table:
def __init__(self, grammar):
self.grammar = grammar
self.actions = {}
self.gotos = {}
# 构造项目集规范族
self.canonical_collection = self.build_canonical_collection()
# 构造 LR(0) 分析表
self.build_table()
# 构造项目集规范族
def build_canonical_collection(self):
# 第一步:初始化
start_production = self.grammar.productions[0]
start_item = Item(start_production, 0)
closure = self.closure(set([start_item]))
current_state = frozenset(closure)
canonical_collection = {current_state: closure}
# 第二步:循环直到项目集规范族没有变化
while True:
for item in current_state:
# 对于每个项目 A -> α·Bβ,进行 GOTO 操作
if not item.dot == len(item.production.body):
symbol = item.production.body[item.dot]
goto = self.goto(current_state, symbol)
if not goto in canonical_collection:
closure = self.closure(goto)
canonical_collection[goto] = closure
# 如果项目集规范族没有变化,则退出循环
if len(canonical_collection) == len(current_state):
break
else:
current_state = list(canonical_collection.keys())[-1]
return canonical_collection
# 求闭包
def closure(self, items):
closure = set(items)
while True:
new_items = set()
for item in closure:
# 对于每个项目 A -> α·Bβ,将 B -> γ 加入 new_items
if not item.dot == len(item.production.body):
symbol = item.production.body[item.dot]
if symbol in self.grammar.non_terminals:
for production in self.grammar.productions:
if production.head == symbol:
new_item = Item(production, 0)
if not new_item in closure:
new_items.add(new_item)
if not new_items:
break
closure |= new_items
return closure
# 求 GOTO(A -> α·Bβ, b)
def goto(self, items, symbol):
goto = set()
for item in items:
if not item.dot == len(item.production.body) and item.production.body[item.dot] == symbol:
goto.add(Item(item.production, item.dot + 1))
return frozenset(self.closure(goto))
# 构造 LR(0) 分析表
def build_table(self):
for i, state in enumerate(self.canonical_collection):
# 对于每个项目 A -> α·,将 ACTION[s, a] 设为 SHIFT(t),其中 t = GOTO[s, a]
for item in state:
if item.dot == len(item.production.body):
if item.production.head == self.grammar.start_symbol:
self.actions[(i, '$')] = (ACCEPT, None)
else:
for symbol in self.grammar.follow(item.production.head):
self.actions[(i, symbol)] = (REDUCE, item.production)
else:
symbol = item.production.body[item.dot]
goto = self.goto(state, symbol)
if symbol in self.grammar.terminals:
self.actions[(i, symbol)] = (SHIFT, goto)
else:
self.gotos[(i, symbol)] = goto
# 执行 LR(0) 分析
def parse(self, input):
stack = [0]
output = []
while True:
state = stack[-1]
symbol = input[0]
if (state, symbol) in self.actions:
action, arg = self.actions[(state, symbol)]
if action == SHIFT:
stack.append(arg)
input = input[1:]
elif action == REDUCE:
head = arg.head
body = arg.body
output.append(arg)
for i in range(len(body)):
stack.pop()
state = stack[-1]
stack.append(self.gotos[(state, head)])
elif action == ACCEPT:
output.append(arg)
return output
else:
raise Exception('Syntax error')
else:
raise Exception('Syntax error')
```
此代码实现了 LR(0) 分析程序的主要功能,包括构造项目集规范族、构造 LR(0) 分析表和执行 LR(0) 分析。使用时需要提供一个文法对象(包括产生式和起始符号)和一个输入串。输出为分析树或语法错误。