读取文件 判断算符文法 并输出每个非终结符的FIRSTVT集和LASTVT集 同时构造并输出算符优先分析表 输入文法对给定表达式进行分析,对给定的表达式 python
时间: 2024-02-11 20:05:20 浏览: 86
好的,这是一个比较复杂的问题,需要分几步来完成。我尽量详细地回答你。
1. 读取文件并判断算符文法
首先,我们需要读取输入的文法并判断其是否为算符文法。算符文法的特点是,每个产生式的右部只有一个终结符或一个非终结符和一个终结符之间有一个算符。下面是一个算符文法的例子:
```
E -> E + T | T
T -> T * F | F
F -> ( E ) | id
```
读取文件可以使用 Python 内置的 `open()` 函数,代码如下:
```python
with open('grammar.txt', 'r') as f:
grammar = f.readlines()
```
这里假设输入的文法文件名为 `grammar.txt`,并将其读入到 `grammar` 变量中。接下来,我们需要判断文法是否为算符文法。可以使用正则表达式来匹配每个产生式,代码如下:
```python
import re
for line in grammar:
if not re.match(r'^[a-zA-Z]+\s*->\s*([a-zA-Z]+\s*[+\-*/]\s*)*[a-zA-Z]+$', line.strip()):
print('This is not an operator grammar!')
exit()
```
如果输入的文法不是算符文法,就输出错误信息并结束程序。
2. 计算 FIRSTVT 集和 LASTVT 集
接下来,我们需要计算每个非终结符的 FIRSTVT 集和 LASTVT 集。首先,我们需要将文法用 Python 的数据结构表示出来,比如使用字典来表示每个产生式的左部和右部:
```python
productions = {}
for line in grammar:
left, right = map(str.strip, line.split('->'))
right = right.split('|')
productions[left] = [r.split() for r in right]
```
然后,我们可以按照算符文法的规则计算每个非终结符的 FIRSTVT 集和 LASTVT 集。具体计算方法可以参考经典编译原理教材,这里简单介绍一下。
对于每个产生式 `A -> αBβ`,如果存在 `B -> ε` 或者 `α` 中的某个符号可以推导出空串,那么将 `FIRSTVT(B)` 中的元素加入到 `FIRSTVT(A)` 中。
对于每个产生式 `A -> αBβ`,如果存在 `B -> ε` 或者 `β` 中的某个符号可以推导出空串,那么将 `LASTVT(B)` 中的元素加入到 `LASTVT(A)` 中。
对于每个产生式 `A -> αB` 或者 `A -> Bβ`,将 `FIRSTVT(B)` 中的元素加入到 `FOLLOWVT(A)` 中。
根据上述规则,我们可以编写 Python 代码来计算每个非终结符的 FIRSTVT 集和 LASTVT 集,代码如下:
```python
# 计算 FIRSTVT 集
firstvt = {}
for symbol in productions.keys():
firstvt[symbol] = set()
while True:
updated = False
for left, right in productions.items():
for r in right:
if len(r) > 0 and r[0] not in productions:
if r[0] not in firstvt[left]:
firstvt[left].add(r[0])
updated = True
elif len(r) > 0 and r[0] in productions:
for s in firstvt[r[0]]:
if s not in firstvt[left]:
firstvt[left].add(s)
updated = True
if len(r) > 1 and r[-1] not in productions:
if r[-1] not in firstvt[left]:
firstvt[left].add(r[-1])
updated = True
elif len(r) > 1 and r[-1] in productions:
for s in firstvt[r[-1]]:
if s not in firstvt[left]:
firstvt[left].add(s)
updated = True
if not updated:
break
# 计算 LASTVT 集
lastvt = {}
for symbol in productions.keys():
lastvt[symbol] = set()
while True:
updated = False
for left, right in productions.items():
for r in right:
if len(r) > 0 and r[0] not in productions:
if r[0] not in lastvt[left]:
lastvt[left].add(r[0])
updated = True
elif len(r) > 0 and r[0] in productions:
for s in lastvt[r[0]]:
if s not in lastvt[left]:
lastvt[left].add(s)
updated = True
if len(r) > 1 and r[-1] not in productions:
if r[-1] not in lastvt[left]:
lastvt[left].add(r[-1])
updated = True
elif len(r) > 1 and r[-1] in productions:
for s in lastvt[r[-1]]:
if s not in lastvt[left]:
lastvt[left].add(s)
updated = True
if not updated:
break
```
3. 构造算符优先分析表
接下来,我们可以使用计算出的 FIRSTVT 集和 LASTVT 集来构造算符优先分析表。算符优先分析表是一个二维表格,行和列都是文法中的终结符和非终结符,每个单元格里的内容表示两个符号之间的优先关系。具体构造方法可以参考经典编译原理教材,这里也简单介绍一下。
对于每个产生式 `A -> αBβ`,将 `FIRSTVT(B)` 中的每个元素和 `FOLLOWVT(A)` 中的每个元素加入到 `M[A, a]` 中,其中 `a` 是 `FIRSTVT(β)` 中的每个元素。
对于每个产生式 `A -> β`,将 `FIRSTVT(β)` 中的每个元素和 `FOLLOWVT(A)` 中的每个元素加入到 `M[A, a]` 中,其中 `a` 是 `FIRSTVT(β)` 中的每个元素。
对于每个产生式 `A -> αB`,将 `LASTVT(B)` 中的每个元素和 `FOLLOWVT(A)` 中的每个元素加入到 `M[B, a]` 中,其中 `a` 是 `FIRSTVT(β)` 中的每个元素。
具体实现可以参考下面的 Python 代码:
```python
# 构造优先关系表
precedence_matrix = {}
for symbol in productions.keys():
precedence_matrix[symbol] = {}
for s in productions.keys():
precedence_matrix[symbol][s] = ''
for left, right in productions.items():
for r in right:
if len(r) > 0 and r[0] not in productions:
for a in firstvt[r[0]]:
precedence_matrix[left][a] = '<'
if len(r) > 1 and r[-1] not in productions:
for a in lastvt[r[-1]]:
precedence_matrix[r[-1]][a] = '>'
for i in range(len(r) - 1):
if r[i] not in productions and r[i+1] not in productions:
precedence_matrix[r[i]][r[i+1]] = '='
elif r[i] not in productions and r[i+1] in productions:
for a in firstvt[r[i+1]]:
precedence_matrix[r[i]][a] = '<'
elif r[i] in productions and r[i+1] not in productions:
for a in lastvt[r[i]]:
precedence_matrix[a][r[i+1]] = '>'
else:
for a in lastvt[r[i]]:
for b in firstvt[r[i+1]]:
precedence_matrix[a][b] = '='
```
4. 对给定表达式进行分析
最后,我们可以使用构造出的算符优先分析表来对给定的表达式进行分析。具体方法是,使用一个栈来保存符号,从左到右扫描表达式,如果遇到终结符就直接压入栈中,如果遇到非终结符,则根据算符优先分析表中对应单元格的内容来确定优先关系。如果栈顶符号优先级低于当前符号,就将当前符号压入栈中;否则,就弹出栈顶符号,直到栈顶符号优先级低于当前符号或者栈为空。如果最后栈中只剩下一个符号,且它是文法的起始符号,那么表达式就是合法的。
具体实现可以参考下面的 Python 代码:
```python
expression = 'a+b*c'
stack = []
i = 0
while i < len(expression):
if expression[i] in productions.keys():
if len(stack) == 0 or precedence_matrix[stack[-1]][expression[i]] == '<':
stack.append(expression[i])
i += 1
elif precedence_matrix[stack[-1]][expression[i]] == '>':
right = stack.pop()
left = stack.pop()
for left_, right_ in productions.items():
if [left, expression[i]] in right_:
stack.append(left_)
break
elif precedence_matrix[stack[-1]][expression[i]] == '=':
i += 1
else:
stack.append(expression[i])
i += 1
if len(stack) == 1 and stack[0] == 'E':
print('The expression is valid!')
else:
print('The expression is invalid!')
```
完整的代码如下所示:
阅读全文