768 lines
30 KiB
Python
768 lines
30 KiB
Python
"""
|
||
语法分析
|
||
"""
|
||
from syntax.rule import Sign, Production, terminal_sign_type, non_terminal_sign_type, productions, grammar_start
|
||
from error import SyntaxRuleError, SyntaxError, SemanticRuleError
|
||
from semantic.rule import SemanticRule, SemanticError, SemanticRuleFactory
|
||
|
||
|
||
class PredictingAnalysisTable:
|
||
"""
|
||
预测分析表
|
||
"""
|
||
def __init__(self):
|
||
"""
|
||
构造
|
||
"""
|
||
# 错误
|
||
self.__error = None
|
||
|
||
# 预测分析表
|
||
self.__table = list()
|
||
|
||
# 所有的非终结符
|
||
self.__non_terminal_signs = list()
|
||
# 所有的终结符
|
||
self.__terminal_signs = list()
|
||
|
||
# 载入所有的符号
|
||
for i in non_terminal_sign_type:
|
||
self.__non_terminal_signs.append(Sign(i))
|
||
for i in terminal_sign_type:
|
||
self.__terminal_signs.append(Sign(i))
|
||
|
||
# 根据非终结符和终结符的数量为预测分析表分配空间,并且为每一个格子预先填上 None
|
||
for i in non_terminal_sign_type:
|
||
self.__table.append(list())
|
||
for i in range(0, len(non_terminal_sign_type)):
|
||
for j in terminal_sign_type:
|
||
self.__table[i].append(None)
|
||
|
||
# 为每一个非终结符建立 first 集和 follow 集
|
||
self.__firsts = list()
|
||
self.__follows = list()
|
||
|
||
# 为每一个非终结符的 first 集和 follow 集分配空间
|
||
for i in non_terminal_sign_type:
|
||
self.__firsts.append(list())
|
||
self.__follows.append(list())
|
||
|
||
def compile(self):
|
||
"""
|
||
编译预测分析表
|
||
"""
|
||
# 对每一个文法元素求其 first 集
|
||
self.__calculate_firsts()
|
||
# 对每一个文法元素求其 follow 集
|
||
self.__calculate_follows()
|
||
# 根据 first 集和 follow 集生成预测分析表
|
||
success = self.__generate_table()
|
||
return success
|
||
|
||
|
||
def get_production(self, non_terminal_sign, terminal_sign):
|
||
"""
|
||
从预测分析表中获取产生式
|
||
:param non_terminal_sign: 非终结符
|
||
:param terminal_sign: 终结符
|
||
:return: 产生式
|
||
"""
|
||
x = self.__get_non_terminal_sign_index(non_terminal_sign)
|
||
y = self.__get_terminal_sign_index(terminal_sign)
|
||
return self.__table[x][y]
|
||
|
||
@classmethod
|
||
def __set_add(cls, container, sign):
|
||
"""
|
||
将 sign 添加到 container 中并返回 True,如果其中已经有该元素了则返回 False
|
||
:param container: 要添加到的集合
|
||
:param sign: 符号
|
||
:return: 添加是否成功
|
||
"""
|
||
exist = False
|
||
for elem in container:
|
||
if elem.type == sign.type:
|
||
exist = True
|
||
if not exist:
|
||
container.append(sign)
|
||
return not exist
|
||
|
||
def __get_terminal_sign_index(self, terminal_sign):
|
||
"""
|
||
获取终结符的索引
|
||
:param terminal_sign: 终结符
|
||
:return: 索引(寻找失败返回 -1)
|
||
"""
|
||
for i in range(0, len(self.__terminal_signs)):
|
||
if terminal_sign.type == self.__terminal_signs[i].type:
|
||
return i
|
||
return -1
|
||
|
||
def __get_non_terminal_sign_index(self, non_terminal_sign):
|
||
"""
|
||
获取非终结符的索引
|
||
:param non_terminal_sign: 非终结符
|
||
:return: 索引(寻找失败返回 -1)
|
||
"""
|
||
for i in range(0, len(self.__non_terminal_signs)):
|
||
if non_terminal_sign.type == self.__non_terminal_signs[i].type:
|
||
return i
|
||
return -1
|
||
|
||
def __get_non_terminal_sign_first(self, non_terminal_sign):
|
||
"""
|
||
获取目标非终结符的 first 集的引用
|
||
:param non_terminal_sign: 目标非终结符
|
||
:return: 其 first 集的引用
|
||
"""
|
||
return self.__firsts[self.__get_non_terminal_sign_index(non_terminal_sign)]
|
||
|
||
def __get_non_terminal_sign_first_no_empty(self, non_terminal_sign):
|
||
"""
|
||
获取目标非终结符的 first 集的非空拷贝
|
||
:param non_terminal_sign: 目标非终结符
|
||
:return: 其 first 集的非空拷贝
|
||
"""
|
||
result = list()
|
||
for i in self.__get_non_terminal_sign_first(non_terminal_sign):
|
||
if not i.is_empty_sign():
|
||
result.append(i)
|
||
return result
|
||
|
||
def __is_empty_in_non_terminal_sign_first(self, non_terminal_sign):
|
||
"""
|
||
目标非终结符的 first 集中是否有空字
|
||
:param non_terminal_sign: 目标非终结符
|
||
:return: True/False
|
||
"""
|
||
for i in self.__get_non_terminal_sign_first(non_terminal_sign):
|
||
if i.is_empty_sign():
|
||
return True
|
||
return False
|
||
|
||
def __get_non_terminal_sign_follow(self, non_terminal_sign):
|
||
"""
|
||
获取非终结符的 follow 集
|
||
:param non_terminal_sign: 非终结符
|
||
:return: 其 follow 集
|
||
"""
|
||
return self.__follows[self.__get_non_terminal_sign_index(non_terminal_sign)]
|
||
|
||
def __calculate_firsts(self):
|
||
"""
|
||
求所有的 first 集
|
||
"""
|
||
# 立一个 flag,用来标志 firsts 集是否增大
|
||
flag = True
|
||
# 开始循环
|
||
while flag:
|
||
flag = False
|
||
# 在每一次循环之中遍历所有产生式
|
||
for production in productions:
|
||
# 如果产生式右边为空
|
||
if len(production.right) == 0:
|
||
# 将空字加入其 first 集
|
||
if self.__set_add(self.__get_non_terminal_sign_first(production.left), Sign('empty')):
|
||
flag = True
|
||
# 如果产生式右边不为空
|
||
else:
|
||
# 如果是以终结符开头,将终结符添加到其 first 集
|
||
if production.right[0].is_terminal_sign():
|
||
if self.__set_add(self.__get_non_terminal_sign_first(production.left), production.right[0]):
|
||
flag = True
|
||
# 如果是以非终结符开头
|
||
elif production.right[0].is_non_terminal_sign():
|
||
# (1) 将开头非终结符的 first 集中的所有非空元素添加到产生式左边非终结符的 first 集中
|
||
bigger = False
|
||
for i in self.__get_non_terminal_sign_first_no_empty(production.right[0]):
|
||
if self.__set_add(self.__get_non_terminal_sign_first(production.left), i):
|
||
bigger = True
|
||
if bigger:
|
||
flag = True
|
||
|
||
# (2) 从第一个非终结符开始循环,如果其 first 集中包含空字,那么将它下一个符号的 first
|
||
# 集添加到产生式左边非终结符的 first 集中去
|
||
for i in range(0, len(production.right)):
|
||
if production.right[i].is_non_terminal_sign():
|
||
# 如果包含空字
|
||
if self.__is_empty_in_non_terminal_sign_first(production.right[i]):
|
||
# 如果它是最后一个,将空字填入
|
||
if i == len(production.right) - 1:
|
||
if self.__set_add(self.__get_non_terminal_sign_first(production.left),
|
||
Sign('empty')):
|
||
flag = True
|
||
# 如果不是最后一个
|
||
else:
|
||
# 如果它之后是终结符
|
||
if production.right[i + 1].is_terminal_sign():
|
||
if self.__set_add(self.__get_non_terminal_sign_first(production.left),
|
||
production.right[i + 1]):
|
||
flag = True
|
||
# 如果它之后是非终结符
|
||
elif production.right[i + 1].is_non_terminal_sign():
|
||
bigger = False
|
||
for j in self.__get_non_terminal_sign_first_no_empty(
|
||
production.right[i + 1]):
|
||
if self.__set_add(
|
||
self.__get_non_terminal_sign_first(production.left), j):
|
||
bigger = True
|
||
if bigger:
|
||
flag = True
|
||
else:
|
||
self.__error = SyntaxRuleError('终结符或非终结符类型错误')
|
||
return False
|
||
# 如果不包含空字
|
||
else:
|
||
break
|
||
else:
|
||
break
|
||
# 否则报错
|
||
else:
|
||
self.__error = SyntaxRuleError('终结符或非终结符类型错误')
|
||
return False
|
||
|
||
def __calculate_follows(self):
|
||
"""
|
||
求所有的 follow 集
|
||
"""
|
||
first = list()
|
||
flag = True
|
||
while flag:
|
||
flag = False
|
||
# 遍历所有产生式
|
||
for production in productions:
|
||
# 如果产生式左边是开始符号
|
||
if production.left.type == grammar_start.type:
|
||
if self.__set_add(self.__get_non_terminal_sign_follow(production.left), Sign('pound')):
|
||
flag = True
|
||
|
||
# 遍历产生式右边
|
||
for i in range(0, len(production.right)):
|
||
# 如果是非终结符
|
||
if production.right[i].is_non_terminal_sign():
|
||
# 如果它是产生式最后一个符号
|
||
if i == len(production.right) - 1:
|
||
# 将产生式左边非终结符的 follow 集添加到这个符号的 follow 集中
|
||
bigger = False
|
||
for j in self.__get_non_terminal_sign_follow(production.left):
|
||
if self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]), j):
|
||
bigger = True
|
||
if bigger:
|
||
flag = True
|
||
# 否则观察其之后的元素
|
||
else:
|
||
# 求他之后所有符号集合的 first 集
|
||
first.clear()
|
||
first += self.__calculate_set_first(production.right[i + 1:])
|
||
# (1) 将 first 中所有非空元素填入 follow
|
||
empty_find = False
|
||
for f in first:
|
||
if not f.is_empty_sign():
|
||
self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]), f)
|
||
else:
|
||
empty_find = True
|
||
|
||
# (2) 如果 first 中含有空
|
||
if empty_find:
|
||
# 将产生式左边非终结符的 follow 集添加到这个符号的 follow 集中
|
||
bigger = False
|
||
for j in self.__get_non_terminal_sign_follow(production.left):
|
||
if self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]), j):
|
||
bigger = True
|
||
if bigger:
|
||
flag = True
|
||
|
||
# # 如果他后面是一个终结符
|
||
# if production.right[i + 1].is_terminal_sign():
|
||
# if self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]),
|
||
# production.right[i + 1]):
|
||
# flag = True
|
||
# # 如果他后面是一个非终结符
|
||
# elif production.right[i + 1].is_non_terminal_sign():
|
||
# # (1) 将后面非终结符的 first 集中的所有非空元素填入
|
||
# bigger = False
|
||
# for j in self.__get_non_terminal_sign_first_no_empty(production.right[i + 1]):
|
||
# if self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]), j):
|
||
# bigger = True
|
||
# if bigger:
|
||
# flag = True
|
||
#
|
||
# # (2) 如果后面所有的非终结符 first 集都包含空
|
||
# # 那么,则将产生式左边的 follow 集添加到该非终结符的 follow 集中去
|
||
# all_empty_in_first = True
|
||
# for j in range(i + 1, len(production.right)):
|
||
# if not self.__is_empty_in_non_terminal_sign_first(production.right[j]):
|
||
# all_empty_in_first = False
|
||
# break
|
||
# if all_empty_in_first:
|
||
# bigger = False
|
||
# for j in self.__get_non_terminal_sign_follow(production.left):
|
||
# if self.__set_add(self.__get_non_terminal_sign_follow(production.right[i]), j):
|
||
# bigger = True
|
||
# if bigger:
|
||
# flag = True
|
||
# # 否则报错
|
||
# else:
|
||
# self.__error = SyntaxRuleError('终结符或非终结符类型错误')
|
||
# return False
|
||
# 如果是终结符
|
||
elif production.right[i].is_terminal_sign():
|
||
continue
|
||
# 否则报错
|
||
else:
|
||
self.__error = SyntaxRuleError('终结符或非终结符类型错误')
|
||
return False
|
||
|
||
def __calculate_set_first(self, container):
|
||
"""
|
||
计算一系列符号的 first 集
|
||
:param container: 符号集合
|
||
:return: first 集
|
||
"""
|
||
first = list()
|
||
|
||
# 开始求 first 集
|
||
# 如果集合为空
|
||
first = list()
|
||
|
||
# 开始求 first 集
|
||
# 如果产生式右边为空
|
||
if len(container) == 0:
|
||
# 将空字加入其 first 集
|
||
self.__set_add(first, Sign('empty'))
|
||
# 如果产生式右边补位空
|
||
else:
|
||
# 如果是以终结符开头,将终结符添加到 first 集
|
||
if container[0].is_terminal_sign():
|
||
self.__set_add(first, container[0])
|
||
# 如果是以非终结符开头
|
||
elif container[0].is_non_terminal_sign():
|
||
# (1) 将开头非终结符的 first 集中的所有非空元素添加到 first 中
|
||
for i in self.__get_non_terminal_sign_first_no_empty(container[0]):
|
||
self.__set_add(first, i)
|
||
|
||
# (2) 从第一个非终结符开始循环,如果其 first 集中包含空字,那么将它的下一个符号的 first
|
||
# 集添加到 first 中
|
||
for i in range(0, len(container)):
|
||
if container[i].is_non_terminal_sign():
|
||
# 如果包含空字
|
||
if self.__is_empty_in_non_terminal_sign_first(container[i]):
|
||
# 如果它是最后一个,将空字填入
|
||
if i == len(container) - 1:
|
||
self.__set_add(first, Sign('empty'))
|
||
# 如果不是最后一个
|
||
else:
|
||
# 如果它之后是终结符
|
||
if container[i + 1].is_terminal_sign():
|
||
self.__set_add(first, container[i + 1])
|
||
# 如果它之后是非终结符
|
||
elif container[i + 1].is_non_terminal_sign():
|
||
for j in self.__get_non_terminal_sign_first_no_empty(container[i + 1]):
|
||
self.__set_add(first, j)
|
||
# 否则报错
|
||
else:
|
||
self.__error = SyntaxRuleError('终结符或非终结符类型错误')
|
||
return False
|
||
# 如果不含空字
|
||
else:
|
||
break
|
||
else:
|
||
break
|
||
# 否则报错
|
||
else:
|
||
self.__error = SyntaxRuleError('终结符或非终结符类型错误')
|
||
return False
|
||
|
||
return first
|
||
|
||
def __insert_to_table(self, production, terminal):
|
||
"""
|
||
将产生式插入预测分析表对应位置
|
||
:param production: 产生式
|
||
:param terminal: 终结符
|
||
:return: 是否插入成功
|
||
"""
|
||
# 先判断应该插入到的位置
|
||
x = self.__get_non_terminal_sign_index(production.left)
|
||
y = self.__get_terminal_sign_index(terminal)
|
||
|
||
# 如果那个位置已经有产生式了
|
||
if self.__table[x][y]:
|
||
# 判断这个产生式是不是与要插入的产生式一样
|
||
same_left = production.left.type == self.__table[x][y].left.type
|
||
if same_left:
|
||
same_right = True
|
||
if len(production.right) != len(self.__table[x][y].right):
|
||
self.__error = SyntaxRuleError("文法非LL(1)" + production.str)
|
||
return False
|
||
else:
|
||
for i in range(0, len(production.right)):
|
||
if production.right[i].type != self.__table[x][y].right[i].type:
|
||
same_right = False
|
||
if same_right:
|
||
# 执行插入
|
||
del self.__table[x][y]
|
||
self.__table[x].insert(y, production)
|
||
return True
|
||
else:
|
||
self.__error = SyntaxRuleError("文法非LL(1)" + production.str)
|
||
return False
|
||
else:
|
||
self.__error = SyntaxRuleError("文法非LL(1)" + production.str)
|
||
return False
|
||
# 如果那个位置为空,说明可以填入
|
||
else:
|
||
# 执行插入
|
||
del self.__table[x][y]
|
||
self.__table[x].insert(y, production)
|
||
return True
|
||
|
||
@classmethod
|
||
def __set_have_repeat(cls, set1, set2):
|
||
"""
|
||
判断两个集合是否有交集
|
||
:param set1: 集合1
|
||
:param set2: 集合2
|
||
:return: 是否有交集
|
||
"""
|
||
for i in set1:
|
||
for j in set2:
|
||
if i.type == j.type:
|
||
return True
|
||
return False
|
||
|
||
def __grammar_rule_debug(self):
|
||
"""
|
||
调试使用,求一个非终结符对应的所有产生式右边的 first 集中是否有相交元素
|
||
"""
|
||
# 一个非终结符对应的所有产生式
|
||
his_productions = list()
|
||
# 那些产生式对应的 first 集
|
||
firsts = list()
|
||
# 错误
|
||
errors = list()
|
||
|
||
# 对于所有的非终结符
|
||
for non_terminal_sign in self.__non_terminal_signs:
|
||
# 寻找他对应的所有产生式
|
||
his_productions.clear()
|
||
firsts.clear()
|
||
for production in productions:
|
||
if non_terminal_sign.type == production.left.type:
|
||
his_productions.append(production)
|
||
|
||
# 对于那些产生式,分别求 first 集
|
||
for production in his_productions:
|
||
firsts.append(self.__calculate_set_first(production.right))
|
||
|
||
|
||
|
||
# 是否有交集
|
||
have_repeat = False
|
||
# 查看这些产生式的 first 集两两之间是否有交集
|
||
for i in range(0, len(his_productions) - 1):
|
||
for j in range(i + 1, len(his_productions)):
|
||
|
||
if self.__set_have_repeat(firsts[i], firsts[j]):
|
||
have_repeat = True
|
||
break
|
||
|
||
|
||
# 如果有交集
|
||
if have_repeat:
|
||
errors.append('产生式 First 集重叠 ' + '非终结符: ' + non_terminal_sign.type)
|
||
|
||
# 如果非终结符的 First 集中包含空字
|
||
if self.__is_empty_in_non_terminal_sign_first(non_terminal_sign):
|
||
# 如果他的 First 集和 Follow 集有交集
|
||
if self.__set_have_repeat(self.__get_non_terminal_sign_first(non_terminal_sign),
|
||
self.__get_non_terminal_sign_follow(non_terminal_sign)):
|
||
errors.append('产生式 First 集和 Follow 集重叠 ' + '非终结符: ' + non_terminal_sign.type)
|
||
return
|
||
|
||
def __generate_table(self):
|
||
"""
|
||
根据 first 集和 follow 集生成预测分析表
|
||
:return: 是否生成成功
|
||
"""
|
||
# 调试
|
||
self.__grammar_rule_debug()
|
||
|
||
# 对每一条产生式应用规则
|
||
for production in productions:
|
||
# 先求出该产生式右边部分的 first 集
|
||
first = self.__calculate_set_first(production.right)
|
||
|
||
# 对每一个 first 集中的每一个终结符执行操作
|
||
empty_find = False
|
||
for i in list(first):
|
||
if i.type == 'empty':
|
||
empty_find = True
|
||
else:
|
||
if not self.__insert_to_table(production, i):
|
||
return False
|
||
|
||
# 如果其 first 集中有空字,则对 follow 集中的每一个终结符执行操作
|
||
if empty_find:
|
||
for i in self.__get_non_terminal_sign_follow(production.left):
|
||
if not self.__insert_to_table(production, i):
|
||
return False
|
||
|
||
return True
|
||
|
||
|
||
class Node:
|
||
"""
|
||
树节点
|
||
"""
|
||
def __init__(self, data):
|
||
"""
|
||
树节点
|
||
:param data: 节点数据
|
||
"""
|
||
self.data = data
|
||
self.str = data.type
|
||
self.children = list()
|
||
self.parent = None
|
||
|
||
# 属性
|
||
self.lexical = None
|
||
self.array = None
|
||
self.code = list()
|
||
self.type = None
|
||
self.id = None
|
||
self.length = None
|
||
self.fun = None
|
||
self.num = None
|
||
self.names = list()
|
||
self.bool = None
|
||
self.op = None
|
||
self.add = None
|
||
self.mul = None
|
||
|
||
def get_pre_brother(self, index):
|
||
"""
|
||
获取它前 index 位的兄弟
|
||
:param index: ..
|
||
:return: 兄弟
|
||
"""
|
||
self_index = 0
|
||
for i in range(0, len(self.parent.children)):
|
||
if self.parent.children[i] is self:
|
||
self_index = i
|
||
return self.parent.children[self_index - index]
|
||
|
||
|
||
class Tree:
|
||
"""
|
||
树
|
||
"""
|
||
def __init__(self, root):
|
||
"""
|
||
构造
|
||
:param root: 树的根节点
|
||
"""
|
||
self.root = root
|
||
|
||
|
||
class Stack:
|
||
"""
|
||
栈
|
||
"""
|
||
def __init__(self):
|
||
"""
|
||
构造
|
||
"""
|
||
self.__container = list()
|
||
|
||
def push(self, elem):
|
||
"""
|
||
入栈
|
||
:param elem: 入栈元素
|
||
"""
|
||
self.__container.append(elem)
|
||
|
||
def pop(self):
|
||
"""
|
||
将栈顶元素出栈
|
||
:return: 栈顶元素
|
||
"""
|
||
top = self.top()
|
||
self.__container.pop()
|
||
return top
|
||
|
||
def top(self):
|
||
"""
|
||
获取栈顶元素
|
||
:return: 栈顶元素
|
||
"""
|
||
return self.__container[-1]
|
||
|
||
def empty(self):
|
||
"""
|
||
栈是否为空
|
||
:return: 栈是否为空
|
||
"""
|
||
return len(self.__container) == 0
|
||
|
||
|
||
class Syntax:
|
||
"""
|
||
语法分析器
|
||
"""
|
||
def __init__(self):
|
||
"""
|
||
构造
|
||
"""
|
||
# 语法树的构建
|
||
self.__grammar_tree = None
|
||
# 准备存放错误
|
||
self.__error = list()
|
||
# 预测分析表的构建
|
||
self.__pa_table = PredictingAnalysisTable()
|
||
# 编译预测分析表
|
||
if self.__pa_table.compile():
|
||
self.__error.append(SyntaxRuleError('预测分析表编译失败'))
|
||
# 准备存放词法分析的结果
|
||
self.__source = list()
|
||
# 将词法分析产生的 token 转换成的终结符
|
||
self.__terminals = list()
|
||
|
||
def put_source(self, source):
|
||
"""
|
||
装填词法分析结果
|
||
:param source: 词法分析结果
|
||
"""
|
||
self.__source.clear()
|
||
self.__terminals.clear()
|
||
# 装填词法分析结果
|
||
for s in source:
|
||
self.__source.append(s)
|
||
# 将 tokens 转换成终结符
|
||
for s in self.__source:
|
||
self.__terminals.append(Sign(s.type, s.str, s.line))
|
||
# 在所有 tokens 的最后填入一个 #
|
||
self.__terminals.append(Sign('pound'))
|
||
|
||
def get_result(self):
|
||
"""
|
||
获取语法树
|
||
:return: 语法树
|
||
"""
|
||
return self.__grammar_tree
|
||
|
||
def get_error(self):
|
||
"""
|
||
获取错误
|
||
:return: 错误
|
||
"""
|
||
return self.__error
|
||
|
||
def execute(self):
|
||
"""
|
||
执行操作
|
||
:return: 语法分析是否成功
|
||
"""
|
||
# 新建栈
|
||
stack = Stack()
|
||
# 清空错误
|
||
self.__error = None
|
||
# 新建临时语法树
|
||
grammar_tree = Tree(Node(Sign(grammar_start.type)))
|
||
|
||
# 将 # 入栈
|
||
stack.push(Node(Sign('pound')))
|
||
# 将语法树根节点入栈
|
||
stack.push(grammar_tree.root)
|
||
|
||
# 拷贝转换之后的终结符到输入串
|
||
inputs = list()
|
||
for sign in self.__terminals:
|
||
inputs.append(sign)
|
||
# 设置当前输入符号索引
|
||
input_index = 0
|
||
|
||
# 立下 flag
|
||
flag = True
|
||
while flag:
|
||
|
||
# 如果栈顶是语义动作
|
||
if isinstance(stack.top(), SemanticRule):
|
||
stack.top().execute()
|
||
if len(stack.top().errors) > 0:
|
||
self.__error = stack.top().errors[-1]
|
||
break
|
||
else:
|
||
stack.pop()
|
||
# 如果栈顶是符号
|
||
else:
|
||
# 如果 top 是非终结符
|
||
if stack.top().data.is_non_terminal_sign():
|
||
# 查看分析表
|
||
production = self.__pa_table.get_production(stack.top().data, inputs[input_index])
|
||
# 如果分析表对应位置存有产生式
|
||
if production:
|
||
# 判断语义规则是否合法
|
||
if len(production.right) != len(production.semantic_children):
|
||
self.__error = SemanticRuleError('语义规则数量与产生式右边数量不一致 ' + production.str)
|
||
break
|
||
|
||
# 执行 start 语义
|
||
semantic_start = SemanticRuleFactory.get_instance(production.semantic_start, stack.top())
|
||
if semantic_start:
|
||
semantic_start.execute()
|
||
if len(semantic_start.errors) > 0:
|
||
self.__error = semantic_start.errors[-1]
|
||
break
|
||
|
||
# 将语法树按照产生式进行生长
|
||
for i in range(0, len(production.right)):
|
||
stack.top().children.append(Node(Sign(production.right[i].type)))
|
||
stack.top().children[i].parent = stack.top()
|
||
|
||
# 将 top 出栈
|
||
top = stack.pop()
|
||
|
||
# 将 end 语义规则入栈
|
||
semantic_end = SemanticRuleFactory.get_instance(production.semantic_end, top)
|
||
if semantic_end:
|
||
stack.push(semantic_end)
|
||
|
||
# 将 top 的孩子节点反序入栈
|
||
for i in range(len(production.right) - 1, -1, -1):
|
||
# for child in top.children[::-1]:
|
||
stack.push(top.children[i])
|
||
semantic_child = SemanticRuleFactory.get_instance(production.semantic_children[i],
|
||
top.children[i])
|
||
if semantic_child:
|
||
stack.push(semantic_child)
|
||
# 如果分析表中存放着错误信息
|
||
else:
|
||
self.__error = SyntaxError('语法错误 ' + inputs[input_index].str, inputs[input_index].line)
|
||
break
|
||
# 如果 top 是终结符
|
||
else:
|
||
# 如果 top = input
|
||
if stack.top().data.type == inputs[input_index].type:
|
||
# 如果 top = #,宣布分析成功
|
||
if stack.top().data.type == 'pound':
|
||
flag = False
|
||
# 如果 top != #
|
||
else:
|
||
# 计算 top 的 lexical 属性
|
||
stack.top().lexical = inputs[input_index].str
|
||
# 将 top 出栈,让 input_index 自增
|
||
stack.pop()
|
||
input_index += 1
|
||
# 如果 top != input
|
||
else:
|
||
self.__error = SyntaxError('语法错误 ' + inputs[input_index].str, inputs[input_index].line)
|
||
break
|
||
|
||
if self.__error:
|
||
return False
|
||
else:
|
||
self.__grammar_tree = grammar_tree
|
||
|
||
return True
|