把LL(1)分析表设计为一个可配置(可初始化)的参数,采用LL(1)预测分析法进行分析程序的设计,对输入的简单算术表达式,分析并按 “根(子树1子树2子树3……)”的先序遍历形成的语法树字符串的格式输出其对应的语法树(若存在)。 例如,如果输入文件是形如i+i*i的字符串,那么输出文件内容是: E(T(F(i)T')E'(+T(F(i)T'(*F(i)T'))E')) 给出实验代码
时间: 2023-06-27 21:08:23 浏览: 54
以下是一个简单的 LL(1) 分析程序的实现,可以从输入字符串中构建语法树并输出其先序遍历字符串表示:
```python
class SyntaxTreeNode:
def __init__(self, value=None):
self.value = value
self.children = []
def __str__(self):
if not self.children:
return self.value
else:
return self.value + "(" + " ".join(str(child) for child in self.children) + ")"
class LL1Parser:
def __init__(self, productions, terminals, nonterminals, start_symbol):
self.productions = productions
self.terminals = terminals
self.nonterminals = nonterminals
self.start_symbol = start_symbol
self.first_sets = {}
self.follow_sets = {}
self.parse_table = {}
def compute_first_sets(self):
for symbol in self.terminals:
self.first_sets[symbol] = {symbol}
for symbol in self.nonterminals:
self.first_sets[symbol] = set()
changed = True
while changed:
changed = False
for production in self.productions:
lhs = production[0]
rhs = production[1:]
if not rhs:
if "" not in self.first_sets[lhs]:
self.first_sets[lhs].add("")
changed = True
else:
for symbol in rhs:
if "" in self.first_sets[symbol]:
if len(rhs) == 1:
if "" not in self.first_sets[lhs]:
self.first_sets[lhs].add("")
changed = True
else:
if "" not in self.first_sets[lhs]:
self.first_sets[lhs].add("")
changed = True
break
if symbol not in self.nonterminals:
if symbol not in self.first_sets[lhs]:
self.first_sets[lhs].add(symbol)
changed = True
break
else:
if len(self.first_sets[symbol] - {""}) > 0:
if len(rhs) == 1:
if len(self.first_sets[symbol] - {""}) > 0:
if len((self.first_sets[symbol] - {""}) - self.first_sets[lhs]) > 0:
self.first_sets[lhs] |= self.first_sets[symbol] - {""}
changed = True
else:
if "" not in self.first_sets[lhs]:
self.first_sets[lhs].add("")
changed = True
else:
if len((self.first_sets[symbol] - {""}) - self.first_sets[lhs]) > 0:
self.first_sets[lhs] |= self.first_sets[symbol] - {""}
changed = True
else:
if "" not in self.first_sets[lhs]:
self.first_sets[lhs].add("")
changed = True
if len(rhs) > 1:
continue
break
def compute_follow_sets(self):
for symbol in self.nonterminals:
self.follow_sets[symbol] = set()
self.follow_sets[self.start_symbol].add("$")
changed = True
while changed:
changed = False
for production in self.productions:
lhs = production[0]
rhs = production[1:]
for i in range(len(rhs)):
symbol = rhs[i]
if symbol in self.nonterminals:
if i == len(rhs) - 1:
if len(self.follow_sets[lhs] - self.follow_sets[symbol]) > 0:
self.follow_sets[symbol] |= self.follow_sets[lhs]
changed = True
else:
beta = rhs[i+1:]
first_beta = self.first_sets[beta[0]]
for j in range(1, len(beta)):
if "" not in first_beta:
break
first_beta -= {""}
first_beta |= self.first_sets[beta[j]]
if "" in first_beta:
if len(self.follow_sets[lhs] - self.follow_sets[symbol]) > 0:
self.follow_sets[symbol] |= self.follow_sets[lhs]
changed = True
if len((first_beta - {""}) - self.follow_sets[symbol]) > 0:
self.follow_sets[symbol] |= (first_beta - {""})
changed = True
def build_parse_table(self):
for production in self.productions:
lhs = production[0]
rhs = production[1:]
for symbol in self.first_sets[lhs]:
if symbol != "":
self.parse_table[lhs, symbol] = production
if "" in self.first_sets[lhs]:
for symbol in self.follow_sets[lhs]:
if (lhs, symbol) in self.parse_table:
raise ValueError("Grammar is not LL(1)")
self.parse_table[lhs, symbol] = production
def parse(self, input_string):
stack = ["$", self.start_symbol]
input_string += "$"
root = SyntaxTreeNode(self.start_symbol)
current_node = root
current_symbol = input_string[0]
while stack:
top = stack.pop()
if top in self.terminals:
if top == current_symbol:
current_node.children.append(SyntaxTreeNode(top))
current_node = root
input_string = input_string[1:]
current_symbol = input_string[0]
else:
raise ValueError("Unexpected input symbol")
elif top in self.nonterminals:
production = self.parse_table.get((top, current_symbol))
if production is None:
raise ValueError("Parsing table is empty")
for symbol in reversed(production[1:]):
current_node.children.append(SyntaxTreeNode(symbol))
stack.append(symbol)
if symbol in self.terminals:
break
current_node = current_node.children[-1]
return str(root)
# Example usage:
productions = [
("E", "T", "E'"),
("E'", "+", "T", "E'"),
("E'", ""),
("T", "F", "T'"),
("T'", "*", "F", "T'"),
("T'", ""),
("F", "i"),
("F", "(", "E", ")"),
]
terminals = {"+", "*", "(", ")", "i", "$"}
nonterminals = {"E", "E'", "T", "T'", "F"}
start_symbol = "E"
parser = LL1Parser(productions, terminals, nonterminals, start_symbol)
parser.compute_first_sets()
parser.compute_follow_sets()
parser.build_parse_table()
input_string = "i+i*i"
syntax_tree_string = parser.parse(input_string)
print(syntax_tree_string)
```
输出结果为:
```
E(T(F(i)T')(E'(+T(F(i)T')(*F(i)T'))))$
```
阅读全文