已知文法G(S): S→L=R S→R L→*R L→i R→L 根据文法G利用LR(1)分析法设计一个简单语法分析程序。 基本要求:输入一个符号串,判断是否是该文法所能推导出来的句子。如果是,则输出“Yes”,并输出分析过程(格式参考教材85页表4.12);否则,输出“No”,并输出已经完成的分析过程。
时间: 2023-06-20 17:05:32 浏览: 482
LR(1)分析法是自底向上的语法分析方法,它使用一个叫做LR(1)自动机的状态机来记录当前的分析状态。下面是一个简单的LR(1)分析程序:
首先,我们需要定义文法G(S):
```
S -> L = R | R
L -> * R | i
R -> L
```
我们需要构建文法符号和状态的数据结构。其中,文法符号包括终结符和非终结符,状态包括状态号、状态符号、状态转移等信息。
```python
# 定义文法符号
class Symbol:
def __init__(self, symbol, is_terminal):
self.symbol = symbol
self.is_terminal = is_terminal
def __eq__(self, other):
return self.symbol == other.symbol and self.is_terminal == other.is_terminal
# 定义状态
class State:
def __init__(self, state_id, state_items, transitions=None):
self.state_id = state_id
self.state_items = state_items
self.transitions = transitions or {}
def __eq__(self, other):
return self.state_id == other.state_id
def __hash__(self):
return hash(self.state_id)
```
接下来,我们需要定义LR(1)分析表。它包括两个部分:action表和goto表。其中,action表记录在当前状态和读入符号情况下应该进行的操作,goto表记录在当前状态和遇到非终结符情况下应该转移到哪个状态。
```python
# 定义LR(1)分析表
class LRTable:
def __init__(self, action_table, goto_table):
self.action_table = action_table
self.goto_table = goto_table
```
然后,我们需要为文法G(S)构建LR(1)自动机。自动机的状态是由状态项(StateItem)组成的,其中状态项是由一个文法符号和一个扩展项组成的。扩展项是指已经匹配的符号和还未匹配的符号。
```python
# 定义状态项
class StateItem:
def __init__(self, production, dot, lookahead):
self.production = production
self.dot = dot
self.lookahead = lookahead
def __eq__(self, other):
return self.production == other.production and self.dot == other.dot and self.lookahead == other.lookahead
def __hash__(self):
return hash((self.production, self.dot, self.lookahead))
```
接着,我们需要实现状态项的闭包操作和状态项的转移操作。
```python
# 计算状态项闭包
def closure(state, grammar):
closure_items = set(state.state_items)
changed = True
while changed:
changed = False
for item in closure_items.copy():
if item.dot < len(item.production.right) and not item.production.right[item.dot].is_terminal:
for prod in grammar.productions:
if prod.left.symbol == item.production.right[item.dot].symbol:
lookahead = item.lookahead
if item.dot < len(item.production.right) - 1:
lookahead = grammar.compute_first(item.production.right[item.dot+1:], lookahead)
new_item = StateItem(prod, 0, lookahead)
if new_item not in closure_items:
closure_items.add(new_item)
changed = True
return closure_items
# 计算状态项转移
def goto(state, symbol, grammar):
new_items = set()
for item in state.state_items:
if item.dot < len(item.production.right) and item.production.right[item.dot] == symbol:
new_item = StateItem(item.production, item.dot+1, item.lookahead)
new_items.add(new_item)
return State(state.state_id, closure(new_items, grammar))
```
接下来,我们需要构建LR(1)自动机。自动机的起始状态是由文法的开始符号生成的闭包状态项集合。
```python
# 构建LR(1)自动机
def build_LR1_automaton(grammar):
automaton = {}
start_symbol = grammar.start_symbol
start_production = Production(Symbol('S\'', False), [start_symbol])
start_state = State(0, closure({StateItem(start_production, 0, Symbol('$', True))}, grammar))
automaton[start_state] = {}
queue = [start_state]
while queue:
state = queue.pop(0)
for item in state.state_items:
if item.dot < len(item.production.right):
symbol = item.production.right[item.dot]
goto_state = goto(state, symbol, grammar)
if goto_state.state_items:
if goto_state not in automaton:
goto_state.state_id = len(automaton)
automaton[goto_state] = {}
queue.append(goto_state)
if symbol.is_terminal:
automaton[state][symbol] = ('shift', goto_state)
else:
automaton[state][symbol] = ('goto', goto_state)
for item in state.state_items:
if item.dot == len(item.production.right):
if item.production.left == start_production.left:
automaton[state][Symbol('$', True)] = ('accept', None)
else:
for lookahead in item.lookahead:
automaton[state][lookahead] = ('reduce', item.production)
return automaton
```
最后,我们可以使用LR(1)分析表和LR(1)自动机进行语法分析。
```python
def parse_LR1(tokens, lr_table):
stack = [0]
position = 0
output = []
while True:
state = stack[-1]
token = tokens[position]
action = lr_table.action_table[state].get(token, None)
if action is None:
return False, output
action_type, action_data = action
if action_type == 'shift':
stack.append(action_data.state_id)
position += 1
output.append(('shift', token))
elif action_type == 'reduce':
production = action_data
for _ in range(len(production.right)):
stack.pop()
new_state = lr_table.goto_table[stack[-1]][production.left].state_id
stack.append(new_state)
output.append(('reduce', production))
elif action_type == 'accept':
output.append(('accept', None))
return True, output
```
下面是完整的代码实现:
阅读全文