优化了syntax的LL1Generator对象 , 加入debug功能, 加入导出excel表功能
This commit is contained in:
parent
96eb3372fa
commit
7b0fb55e00
2
main.py
2
main.py
@ -3,7 +3,7 @@
|
|||||||
"""
|
"""
|
||||||
from lexical.lexical import Lexical
|
from lexical.lexical import Lexical
|
||||||
from syntax.syntax import Syntax
|
from syntax.syntax import Syntax
|
||||||
from syntax.syntax import PredictingAnalysisTable
|
from syntax.syntax import LL1Generator
|
||||||
|
|
||||||
# print(PredictingAnalysisTable().compile())
|
# print(PredictingAnalysisTable().compile())
|
||||||
|
|
||||||
|
@ -48,6 +48,7 @@ class Production:
|
|||||||
"""
|
"""
|
||||||
产生式
|
产生式
|
||||||
"""
|
"""
|
||||||
|
cnt = 0
|
||||||
def __init__(self, left_type, right_types, semantic_start, semantic_children, semantic_end):
|
def __init__(self, left_type, right_types, semantic_start, semantic_children, semantic_end):
|
||||||
"""
|
"""
|
||||||
产生式左边
|
产生式左边
|
||||||
@ -57,22 +58,28 @@ class Production:
|
|||||||
:param semantic_children: 语义操作关键字 - 孩子
|
:param semantic_children: 语义操作关键字 - 孩子
|
||||||
:param semantic_end: 语义操作关键字 - 结束
|
:param semantic_end: 语义操作关键字 - 结束
|
||||||
"""
|
"""
|
||||||
|
self.cnt = Production.cnt
|
||||||
|
Production.cnt += 1
|
||||||
self.left = Sign(left_type)
|
self.left = Sign(left_type)
|
||||||
self.right = list()
|
self.right = list()
|
||||||
for i in right_types:
|
for i in right_types:
|
||||||
self.right.append(Sign(i))
|
self.right.append(Sign(i))
|
||||||
|
|
||||||
# 调试用的
|
# 调试用的
|
||||||
self.str = self.left.type + ' ->'
|
self.str1 = self.left.type + ' ->'
|
||||||
for i in self.right:
|
for i in self.right:
|
||||||
self.str += ' ' + i.type
|
self.str1 += ' ' + i.type
|
||||||
|
if len(self.right)==0:
|
||||||
|
self.str1 += ' empty'
|
||||||
|
self.str = [self.str1,self.cnt]
|
||||||
# 语义操作关键字
|
# 语义操作关键字
|
||||||
self.semantic_start = semantic_start
|
self.semantic_start = semantic_start
|
||||||
self.semantic_children = list()
|
self.semantic_children = list()
|
||||||
for c in semantic_children:
|
for c in semantic_children:
|
||||||
self.semantic_children.append(c)
|
self.semantic_children.append(c)
|
||||||
self.semantic_end = semantic_end
|
self.semantic_end = semantic_end
|
||||||
|
def __str__(self):
|
||||||
|
return self.str[0]
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
678
syntax/syntax.py
678
syntax/syntax.py
@ -1,515 +1,240 @@
|
|||||||
"""
|
"""
|
||||||
语法分析
|
语法分析
|
||||||
"""
|
"""
|
||||||
|
import csv
|
||||||
from syntax.rule import Sign, Production, terminal_sign_type, non_terminal_sign_type, productions, grammar_start
|
from syntax.rule import Sign, Production, terminal_sign_type, non_terminal_sign_type, productions, grammar_start
|
||||||
from error import SyntaxRuleError, SyntaxError, SemanticRuleError
|
from error import SyntaxRuleError, SyntaxError, SemanticRuleError
|
||||||
from semantic.rule import SemanticRule, SemanticError, SemanticRuleFactory
|
from semantic.rule import SemanticRule, SemanticError, SemanticRuleFactory
|
||||||
|
|
||||||
|
class LL1Generator:
|
||||||
class PredictingAnalysisTable:
|
|
||||||
"""
|
|
||||||
预测分析表
|
|
||||||
"""
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
"""
|
self.NTS = [_ for _ in non_terminal_sign_type]
|
||||||
构造
|
self.NTS_sz = len(self.NTS)
|
||||||
"""
|
self.NTSmp = {_:idx for idx,_ in enumerate(self.NTS)}
|
||||||
# 错误
|
self.TS = [_ for _ in terminal_sign_type]
|
||||||
self.__error = None
|
self.TS_sz = len(self.TS)
|
||||||
|
self.TSmp = {_:idx for idx,_ in enumerate(self.TS)}
|
||||||
# 预测分析表
|
self.tb = [[None for __ in range(self.TS_sz)] for _ in range(self.NTS_sz)]
|
||||||
self.__table = list()
|
self.firsts = [set() for _ in range(self.NTS_sz)]
|
||||||
|
self.follows = [set() for _ in range(self.NTS_sz)]
|
||||||
# 所有的非终结符
|
self.first_debug = False
|
||||||
self.__non_terminal_signs = list()
|
self.first_debug_cnt = 0
|
||||||
# 所有的终结符
|
self.follow_debug = False
|
||||||
self.__terminal_signs = list()
|
self.follow_debug_cnt = 0
|
||||||
|
|
||||||
# 载入所有的符号
|
|
||||||
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):
|
def compile(self):
|
||||||
"""
|
self.calculate_firsts()
|
||||||
编译预测分析表
|
self.calculate_follows()
|
||||||
"""
|
success = self.gen_tb()
|
||||||
# 对每一个文法元素求其 first 集
|
|
||||||
self.__calculate_firsts()
|
|
||||||
# 对每一个文法元素求其 follow 集
|
|
||||||
self.__calculate_follows()
|
|
||||||
# 根据 first 集和 follow 集生成预测分析表
|
|
||||||
success = self.__generate_table()
|
|
||||||
return success
|
return success
|
||||||
|
def print_firsts(self):
|
||||||
|
for idx,_ in enumerate(self.firsts):
|
||||||
|
print(f"{self.NTS[idx]}:")
|
||||||
|
print(self.firsts[idx])
|
||||||
|
|
||||||
|
def print_follows(self):
|
||||||
|
for idx,_ in enumerate(self.follows):
|
||||||
|
print(f"{self.NTS[idx]}:")
|
||||||
|
print(self.follows[idx])
|
||||||
|
|
||||||
def get_production(self, non_terminal_sign, terminal_sign):
|
def is_TS(self,item):
|
||||||
"""
|
return self.TSmp.get(item) is not None
|
||||||
从预测分析表中获取产生式
|
|
||||||
: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 is_NTS(self,item):
|
||||||
def __set_add(cls, container, sign):
|
return self.NTSmp.get(item) is not None
|
||||||
"""
|
|
||||||
将 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):
|
def first_set(self,tp):
|
||||||
"""
|
return self.firsts[self.NTSmp.get(tp)]
|
||||||
获取终结符的索引
|
|
||||||
: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):
|
def first_insert(self,l,item):
|
||||||
"""
|
or_sz = len(self.first_set(l))
|
||||||
获取非终结符的索引
|
self.first_set(l).add(item)
|
||||||
:param non_terminal_sign: 非终结符
|
return or_sz < len(self.first_set(l))
|
||||||
: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):
|
def follow_set(self,tp):
|
||||||
"""
|
return self.follows[self.NTSmp.get(tp)]
|
||||||
获取目标非终结符的 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):
|
def follow_insert(self,l,item):
|
||||||
"""
|
or_sz = len(self.follow_set(l))
|
||||||
获取目标非终结符的 first 集的非空拷贝
|
self.follow_set(l).add(item)
|
||||||
:param non_terminal_sign: 目标非终结符
|
return or_sz < len(self.follow_set(l))
|
||||||
: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):
|
def l_r_scan(self,lst):
|
||||||
"""
|
l = set()
|
||||||
目标非终结符的 first 集中是否有空字
|
if len(lst) == 0:
|
||||||
:param non_terminal_sign: 目标非终结符
|
l.add('empty')
|
||||||
: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):
|
for idx,_ in enumerate(lst):
|
||||||
"""
|
f = False
|
||||||
获取非终结符的 follow 集
|
if self.is_TS(_):
|
||||||
:param non_terminal_sign: 非终结符
|
l.add(_)
|
||||||
:return: 其 follow 集
|
else:
|
||||||
"""
|
for __ in self.first_set(_):
|
||||||
return self.__follows[self.__get_non_terminal_sign_index(non_terminal_sign)]
|
if __ =='empty':
|
||||||
|
f =True
|
||||||
|
if __ != 'empty' or (__ =='empty' and idx==len(lst)-1):
|
||||||
|
l.add(__)
|
||||||
|
if not f:
|
||||||
|
break
|
||||||
|
return l
|
||||||
|
|
||||||
def __calculate_firsts(self):
|
def calculate_firsts(self):
|
||||||
"""
|
f = True
|
||||||
求所有的 first 集
|
while f:
|
||||||
"""
|
f = False
|
||||||
# 立一个 flag,用来标志 firsts 集是否增大
|
for _ in productions:
|
||||||
flag = True
|
l = _.left.type
|
||||||
# 开始循环
|
r = [__.type for __ in _.right]
|
||||||
while flag:
|
if len(r)==0:
|
||||||
flag = False
|
if self.first_insert(l,'empty'):
|
||||||
# 在每一次循环之中遍历所有产生式
|
if self.first_debug:
|
||||||
for production in productions:
|
self.first_debug_cnt+=1
|
||||||
# 如果产生式右边为空
|
print(f"第{self.first_debug_cnt}次推导: {l}->{' '.join(r)} : 添加empty")
|
||||||
if len(production.right) == 0:
|
f = True
|
||||||
# 将空字加入其 first 集
|
elif self.is_TS(r[0]):
|
||||||
if self.__set_add(self.__get_non_terminal_sign_first(production.left), Sign('empty')):
|
if self.first_insert(l,r[0]):
|
||||||
flag = True
|
if self.first_debug:
|
||||||
# 如果产生式右边不为空
|
self.first_debug_cnt+=1
|
||||||
|
print(f"第{self.first_debug_cnt}次推导: {l}->{' '.join(r)} : 添加{r[0]}")
|
||||||
|
f = True
|
||||||
else:
|
else:
|
||||||
# 如果是以终结符开头,将终结符添加到其 first 集
|
# 此时就是非终结符了
|
||||||
if production.right[0].is_terminal_sign():
|
# 将所有该非终结符的first集元素加入到左部的first集
|
||||||
if self.__set_add(self.__get_non_terminal_sign_first(production.left), production.right[0]):
|
for _ in self.first_set(r[0]):
|
||||||
flag = True
|
if self.first_insert(l,_):
|
||||||
# 如果是以非终结符开头
|
if self.first_debug:
|
||||||
elif production.right[0].is_non_terminal_sign():
|
self.first_debug_cnt += 1
|
||||||
# (1) 将开头非终结符的 first 集中的所有非空元素添加到产生式左边非终结符的 first 集中
|
print(f"第{self.first_debug_cnt}次推导 : {l}->{' '.join(r)} : 添加{_}")
|
||||||
bigger = False
|
f = True
|
||||||
for i in self.__get_non_terminal_sign_first_no_empty(production.right[0]):
|
for i in range(0,len(r)):
|
||||||
if self.__set_add(self.__get_non_terminal_sign_first(production.left), i):
|
# 如果是非终结符
|
||||||
bigger = True
|
if self.is_NTS(r[i]):
|
||||||
if bigger:
|
# 如果该非终结符的first里有空
|
||||||
flag = True
|
if 'empty' in self.first_set(r[i]):
|
||||||
|
# 如果是最后一个
|
||||||
|
if i == len(r)-1:
|
||||||
|
if self.first_insert(l,'empty'):
|
||||||
|
if self.first_debug:
|
||||||
|
self.first_debug_cnt += 1
|
||||||
|
print(f"第{self.first_debug_cnt}次推导 : {l}->{' '.join(r)} : 添加empty")
|
||||||
|
|
||||||
# (2) 从第一个非终结符开始循环,如果其 first 集中包含空字,那么将它下一个符号的 first
|
f = True
|
||||||
# 集添加到产生式左边非终结符的 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:
|
else:
|
||||||
break
|
# 下一个是终结符
|
||||||
|
if self.is_TS(r[i+1]):
|
||||||
|
if self.first_insert(l,r[i+1]):
|
||||||
|
if self.first_debug:
|
||||||
|
self.first_debug_cnt += 1
|
||||||
|
print(f"第{self.first_debug_cnt}次推导 : {l}->{' '.join(r)} : 添加{r[i+1]}")
|
||||||
|
|
||||||
|
f = True
|
||||||
|
# 下一个为非终结符
|
||||||
|
elif self.is_NTS(r[i+1]):
|
||||||
|
for _ in self.first_set(r[i+1]):
|
||||||
|
if self.first_insert(l,_):
|
||||||
|
if self.first_debug:
|
||||||
|
self.first_debug_cnt += 1
|
||||||
|
print(
|
||||||
|
f"第{self.first_debug_cnt}次推导 : {l}->{' '.join(r)} : 添加{_}")
|
||||||
|
|
||||||
|
f = True
|
||||||
|
else:
|
||||||
|
print("error: TS/NTS type.")
|
||||||
else:
|
else:
|
||||||
break
|
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:
|
else:
|
||||||
break
|
break
|
||||||
else:
|
|
||||||
break
|
|
||||||
# 否则报错
|
|
||||||
else:
|
|
||||||
self.__error = SyntaxRuleError('终结符或非终结符类型错误')
|
|
||||||
return False
|
|
||||||
|
|
||||||
return first
|
def calculate_follows(self):
|
||||||
|
f = True
|
||||||
def __insert_to_table(self, production, terminal):
|
while f:
|
||||||
"""
|
f = False
|
||||||
将产生式插入预测分析表对应位置
|
for _ in productions:
|
||||||
:param production: 产生式
|
l = _.left.type
|
||||||
:param terminal: 终结符
|
r= [__.type for __ in _.right]
|
||||||
:return: 是否插入成功
|
if l == 'program':
|
||||||
"""
|
if self.follow_insert(l,'pound'):
|
||||||
# 先判断应该插入到的位置
|
if self.follow_debug:
|
||||||
x = self.__get_non_terminal_sign_index(production.left)
|
self.follow_debug_cnt +=1
|
||||||
y = self.__get_terminal_sign_index(terminal)
|
print(f"第{self.follow_debug_cnt}次推导:{l} -> {' '.join(r)} , {l} add pound")
|
||||||
|
f = True
|
||||||
# 如果那个位置已经有产生式了
|
for i in range(0,len(r)):
|
||||||
if self.__table[x][y]:
|
if self.is_NTS(r[i]):
|
||||||
# 判断这个产生式是不是与要插入的产生式一样
|
if i == len(r)-1:
|
||||||
same_left = production.left.type == self.__table[x][y].left.type
|
for _ in self.follow_set(l):
|
||||||
if same_left:
|
if self.follow_insert(r[i],_):
|
||||||
same_right = True
|
if self.follow_debug:
|
||||||
if len(production.right) != len(self.__table[x][y].right):
|
self.follow_debug_cnt += 1
|
||||||
self.__error = SyntaxRuleError("文法非LL(1)" + production.str)
|
print(f"第{self.follow_debug_cnt}次推导:{l} -> {' '.join(r)} , {r[i]} add {_}")
|
||||||
return False
|
f = True
|
||||||
else:
|
else:
|
||||||
for i in range(0, len(production.right)):
|
empty_find = False
|
||||||
if production.right[i].type != self.__table[x][y].right[i].type:
|
for __ in self.l_r_scan(r[i+1:]):
|
||||||
same_right = False
|
if __=='empty':
|
||||||
if same_right:
|
empty_find = True
|
||||||
# 执行插入
|
elif self.follow_insert(r[i],__):
|
||||||
del self.__table[x][y]
|
if self.follow_debug:
|
||||||
self.__table[x].insert(y, production)
|
self.follow_debug_cnt += 1
|
||||||
return True
|
print(f"第{self.follow_debug_cnt}次推导:{l} -> {' '.join(r)} , {r[i]} add {__}")
|
||||||
else:
|
f = True
|
||||||
self.__error = SyntaxRuleError("文法非LL(1)" + production.str)
|
if empty_find:
|
||||||
return False
|
for _ in self.follow_set(l):
|
||||||
else:
|
if self.follow_insert(r[i],_):
|
||||||
self.__error = SyntaxRuleError("文法非LL(1)" + production.str)
|
if self.follow_debug:
|
||||||
return False
|
self.follow_debug_cnt += 1
|
||||||
# 如果那个位置为空,说明可以填入
|
print(
|
||||||
|
f"第{self.follow_debug_cnt}次推导:{l} -> {' '.join(r)} , {r[i]} add {l}")
|
||||||
|
f = True
|
||||||
|
def select(self,l):
|
||||||
|
f = False
|
||||||
|
for _ in self.l_r_scan(l):
|
||||||
|
if _ =='empty':
|
||||||
|
f= True
|
||||||
|
break
|
||||||
|
if f:
|
||||||
|
return
|
||||||
else:
|
else:
|
||||||
# 执行插入
|
return
|
||||||
del self.__table[x][y]
|
|
||||||
self.__table[x].insert(y, production)
|
|
||||||
return True
|
|
||||||
|
|
||||||
@classmethod
|
def insert_tb(self,_,r):
|
||||||
def __set_have_repeat(cls, set1, set2):
|
if self.tb[self.NTSmp[_.left.type]][self.TSmp[r]] != None and self.tb[self.NTSmp[_.left.type]][self.TSmp[r]] != _:
|
||||||
"""
|
print(f"wa :{_.l.type}->{[__.type for __ in _.r]} : {r}")
|
||||||
判断两个集合是否有交集
|
self.tb[self.NTSmp[_.left.type]][self.TSmp[r]] = _
|
||||||
: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):
|
def gen_tb(self):
|
||||||
"""
|
for _ in productions:
|
||||||
调试使用,求一个非终结符对应的所有产生式右边的 first 集中是否有相交元素
|
l = _.left.type
|
||||||
"""
|
r = [_.type for _ in _.right]
|
||||||
# 一个非终结符对应的所有产生式
|
|
||||||
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
|
empty_find = False
|
||||||
for i in list(first):
|
for __ in self.l_r_scan(r):
|
||||||
if i.type == 'empty':
|
if __ =='empty':
|
||||||
empty_find = True
|
empty_find = True
|
||||||
else:
|
else:
|
||||||
if not self.__insert_to_table(production, i):
|
self.insert_tb(_,__)
|
||||||
return False
|
|
||||||
|
|
||||||
# 如果其 first 集中有空字,则对 follow 集中的每一个终结符执行操作
|
|
||||||
if empty_find:
|
if empty_find:
|
||||||
for i in self.__get_non_terminal_sign_follow(production.left):
|
for __ in self.follow_set(l):
|
||||||
if not self.__insert_to_table(production, i):
|
self.insert_tb(_,__)
|
||||||
return False
|
def get_production(self,row,col):
|
||||||
|
return self.tb[self.NTSmp[row]][self.TSmp[col]]
|
||||||
|
|
||||||
return True
|
def show_me_what_you_got(self,file,show_by_id=False):
|
||||||
|
|
||||||
|
l = ['NTS\\TS']
|
||||||
|
for _ in self.TS:
|
||||||
|
l.append(_)
|
||||||
|
ll = [l]
|
||||||
|
for idx,_ in enumerate(self.tb):
|
||||||
|
l = [self.NTS[idx]]
|
||||||
|
for __ in _:
|
||||||
|
if __ != None:
|
||||||
|
l.append(__.str[int(show_by_id)])
|
||||||
|
else:
|
||||||
|
l.append(' ')
|
||||||
|
ll.append(l)
|
||||||
|
with open(file,'w',newline='')as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(ll)
|
||||||
|
|
||||||
class Node:
|
class Node:
|
||||||
"""
|
"""
|
||||||
@ -619,7 +344,7 @@ class Syntax:
|
|||||||
# 准备存放错误
|
# 准备存放错误
|
||||||
self.__error = list()
|
self.__error = list()
|
||||||
# 预测分析表的构建
|
# 预测分析表的构建
|
||||||
self.__pa_table = PredictingAnalysisTable()
|
self.__pa_table = LL1Generator()
|
||||||
# 编译预测分析表
|
# 编译预测分析表
|
||||||
if self.__pa_table.compile():
|
if self.__pa_table.compile():
|
||||||
self.__error.append(SyntaxRuleError('预测分析表编译失败'))
|
self.__error.append(SyntaxRuleError('预测分析表编译失败'))
|
||||||
@ -699,7 +424,8 @@ class Syntax:
|
|||||||
# 如果 top 是非终结符
|
# 如果 top 是非终结符
|
||||||
if stack.top().data.is_non_terminal_sign():
|
if stack.top().data.is_non_terminal_sign():
|
||||||
# 查看分析表
|
# 查看分析表
|
||||||
production = self.__pa_table.get_production(stack.top().data, inputs[input_index])
|
print(stack.top().data.type,inputs[input_index].type)
|
||||||
|
production = self.__pa_table.get_production(stack.top().data.type, inputs[input_index].type)
|
||||||
# 如果分析表对应位置存有产生式
|
# 如果分析表对应位置存有产生式
|
||||||
if production:
|
if production:
|
||||||
# 判断语义规则是否合法
|
# 判断语义规则是否合法
|
||||||
|
237
syntax/wan.py
Normal file
237
syntax/wan.py
Normal file
@ -0,0 +1,237 @@
|
|||||||
|
import csv
|
||||||
|
|
||||||
|
from rule import *
|
||||||
|
class LL1Generator:
|
||||||
|
def __init__(self):
|
||||||
|
self.NTS = [_ for _ in non_terminal_sign_type]
|
||||||
|
self.NTS_sz = len(self.NTS)
|
||||||
|
self.NTSmp = {_:idx for idx,_ in enumerate(self.NTS)}
|
||||||
|
self.TS = [_ for _ in terminal_sign_type]
|
||||||
|
self.TS_sz = len(self.TS)
|
||||||
|
self.TSmp = {_:idx for idx,_ in enumerate(self.TS)}
|
||||||
|
self.tb = [[None for __ in range(self.TS_sz)] for _ in range(self.NTS_sz)]
|
||||||
|
self.firsts = [set() for _ in range(self.NTS_sz)]
|
||||||
|
self.follows = [set() for _ in range(self.NTS_sz)]
|
||||||
|
self.first_debug = False
|
||||||
|
self.first_debug_cnt = 0
|
||||||
|
self.follow_debug = False
|
||||||
|
self.follow_debug_cnt = 0
|
||||||
|
def compile(self):
|
||||||
|
self.calculate_firsts()
|
||||||
|
self.calculate_follows()
|
||||||
|
success = self.gen_tb()
|
||||||
|
|
||||||
|
return success
|
||||||
|
def print_firsts(self):
|
||||||
|
for idx,_ in enumerate(self.firsts):
|
||||||
|
print(f"{self.NTS[idx]}:")
|
||||||
|
print(self.firsts[idx])
|
||||||
|
|
||||||
|
def print_follows(self):
|
||||||
|
for idx,_ in enumerate(self.follows):
|
||||||
|
print(f"{self.NTS[idx]}:")
|
||||||
|
print(self.follows[idx])
|
||||||
|
|
||||||
|
def is_TS(self,item):
|
||||||
|
return self.TSmp.get(item) is not None
|
||||||
|
|
||||||
|
def is_NTS(self,item):
|
||||||
|
return self.NTSmp.get(item) is not None
|
||||||
|
|
||||||
|
def first_set(self,tp):
|
||||||
|
return self.firsts[self.NTSmp.get(tp)]
|
||||||
|
|
||||||
|
def first_insert(self,l,item):
|
||||||
|
or_sz = len(self.first_set(l))
|
||||||
|
self.first_set(l).add(item)
|
||||||
|
return or_sz < len(self.first_set(l))
|
||||||
|
|
||||||
|
def follow_set(self,tp):
|
||||||
|
return self.follows[self.NTSmp.get(tp)]
|
||||||
|
|
||||||
|
def follow_insert(self,l,item):
|
||||||
|
or_sz = len(self.follow_set(l))
|
||||||
|
self.follow_set(l).add(item)
|
||||||
|
return or_sz < len(self.follow_set(l))
|
||||||
|
|
||||||
|
def l_r_scan(self,lst):
|
||||||
|
l = set()
|
||||||
|
if len(lst) == 0:
|
||||||
|
l.add('empty')
|
||||||
|
|
||||||
|
for idx,_ in enumerate(lst):
|
||||||
|
f = False
|
||||||
|
if self.is_TS(_):
|
||||||
|
l.add(_)
|
||||||
|
else:
|
||||||
|
for __ in self.first_set(_):
|
||||||
|
if __ =='empty':
|
||||||
|
f =True
|
||||||
|
if __ != 'empty' or (__ =='empty' and idx==len(lst)-1):
|
||||||
|
l.add(__)
|
||||||
|
if not f:
|
||||||
|
break
|
||||||
|
return l
|
||||||
|
|
||||||
|
def calculate_firsts(self):
|
||||||
|
f = True
|
||||||
|
while f:
|
||||||
|
f = False
|
||||||
|
for _ in productions:
|
||||||
|
l = _.left.type
|
||||||
|
r = [__.type for __ in _.right]
|
||||||
|
if len(r)==0:
|
||||||
|
if self.first_insert(l,'empty'):
|
||||||
|
if self.first_debug:
|
||||||
|
self.first_debug_cnt+=1
|
||||||
|
print(f"第{self.first_debug_cnt}次推导: {l}->{' '.join(r)} : 添加empty")
|
||||||
|
f = True
|
||||||
|
elif self.is_TS(r[0]):
|
||||||
|
if self.first_insert(l,r[0]):
|
||||||
|
if self.first_debug:
|
||||||
|
self.first_debug_cnt+=1
|
||||||
|
print(f"第{self.first_debug_cnt}次推导: {l}->{' '.join(r)} : 添加{r[0]}")
|
||||||
|
f = True
|
||||||
|
else:
|
||||||
|
# 此时就是非终结符了
|
||||||
|
# 将所有该非终结符的first集元素加入到左部的first集
|
||||||
|
for _ in self.first_set(r[0]):
|
||||||
|
if self.first_insert(l,_):
|
||||||
|
if self.first_debug:
|
||||||
|
self.first_debug_cnt += 1
|
||||||
|
print(f"第{self.first_debug_cnt}次推导 : {l}->{' '.join(r)} : 添加{_}")
|
||||||
|
f = True
|
||||||
|
for i in range(0,len(r)):
|
||||||
|
# 如果是非终结符
|
||||||
|
if self.is_NTS(r[i]):
|
||||||
|
# 如果该非终结符的first里有空
|
||||||
|
if 'empty' in self.first_set(r[i]):
|
||||||
|
# 如果是最后一个
|
||||||
|
if i == len(r)-1:
|
||||||
|
if self.first_insert(l,'empty'):
|
||||||
|
if self.first_debug:
|
||||||
|
self.first_debug_cnt += 1
|
||||||
|
print(f"第{self.first_debug_cnt}次推导 : {l}->{' '.join(r)} : 添加empty")
|
||||||
|
|
||||||
|
f = True
|
||||||
|
else:
|
||||||
|
# 下一个是终结符
|
||||||
|
if self.is_TS(r[i+1]):
|
||||||
|
if self.first_insert(l,r[i+1]):
|
||||||
|
if self.first_debug:
|
||||||
|
self.first_debug_cnt += 1
|
||||||
|
print(f"第{self.first_debug_cnt}次推导 : {l}->{' '.join(r)} : 添加{r[i+1]}")
|
||||||
|
|
||||||
|
f = True
|
||||||
|
# 下一个为非终结符
|
||||||
|
elif self.is_NTS(r[i+1]):
|
||||||
|
for _ in self.first_set(r[i+1]):
|
||||||
|
if self.first_insert(l,_):
|
||||||
|
if self.first_debug:
|
||||||
|
self.first_debug_cnt += 1
|
||||||
|
print(
|
||||||
|
f"第{self.first_debug_cnt}次推导 : {l}->{' '.join(r)} : 添加{_}")
|
||||||
|
|
||||||
|
f = True
|
||||||
|
else:
|
||||||
|
print("error: TS/NTS type.")
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
def calculate_follows(self):
|
||||||
|
f = True
|
||||||
|
while f:
|
||||||
|
f = False
|
||||||
|
for _ in productions:
|
||||||
|
l = _.left.type
|
||||||
|
r= [__.type for __ in _.right]
|
||||||
|
if l == 'program':
|
||||||
|
if self.follow_insert(l,'pound'):
|
||||||
|
if self.follow_debug:
|
||||||
|
self.follow_debug_cnt +=1
|
||||||
|
print(f"第{self.follow_debug_cnt}次推导:{l} -> {' '.join(r)} , {l} add pound")
|
||||||
|
f = True
|
||||||
|
for i in range(0,len(r)):
|
||||||
|
if self.is_NTS(r[i]):
|
||||||
|
if i == len(r)-1:
|
||||||
|
for _ in self.follow_set(l):
|
||||||
|
if self.follow_insert(r[i],_):
|
||||||
|
if self.follow_debug:
|
||||||
|
self.follow_debug_cnt += 1
|
||||||
|
print(f"第{self.follow_debug_cnt}次推导:{l} -> {' '.join(r)} , {r[i]} add {_}")
|
||||||
|
f = True
|
||||||
|
else:
|
||||||
|
empty_find = False
|
||||||
|
for __ in self.l_r_scan(r[i+1:]):
|
||||||
|
if __=='empty':
|
||||||
|
empty_find = True
|
||||||
|
elif self.follow_insert(r[i],__):
|
||||||
|
if self.follow_debug:
|
||||||
|
self.follow_debug_cnt += 1
|
||||||
|
print(f"第{self.follow_debug_cnt}次推导:{l} -> {' '.join(r)} , {r[i]} add {__}")
|
||||||
|
f = True
|
||||||
|
if empty_find:
|
||||||
|
for _ in self.follow_set(l):
|
||||||
|
if self.follow_insert(r[i],_):
|
||||||
|
if self.follow_debug:
|
||||||
|
self.follow_debug_cnt += 1
|
||||||
|
print(
|
||||||
|
f"第{self.follow_debug_cnt}次推导:{l} -> {' '.join(r)} , {r[i]} add {l}")
|
||||||
|
f = True
|
||||||
|
def select(self,l):
|
||||||
|
f = False
|
||||||
|
for _ in self.l_r_scan(l):
|
||||||
|
if _ =='empty':
|
||||||
|
f= True
|
||||||
|
break
|
||||||
|
if f:
|
||||||
|
return
|
||||||
|
else:
|
||||||
|
return
|
||||||
|
|
||||||
|
def insert_tb(self,_,r):
|
||||||
|
if self.tb[self.NTSmp[_.left.type]][self.TSmp[r]] != None and self.tb[self.NTSmp[_.left.type]][self.TSmp[r]] != _:
|
||||||
|
print(f"wa :{_.l.type}->{[__.type for __ in _.r]} : {r}")
|
||||||
|
self.tb[self.NTSmp[_.left.type]][self.TSmp[r]] = _
|
||||||
|
|
||||||
|
def gen_tb(self):
|
||||||
|
for _ in productions:
|
||||||
|
l = _.left.type
|
||||||
|
r = [_.type for _ in _.right]
|
||||||
|
|
||||||
|
empty_find = False
|
||||||
|
for __ in self.l_r_scan(r):
|
||||||
|
if __ =='empty':
|
||||||
|
empty_find = True
|
||||||
|
else:
|
||||||
|
self.insert_tb(_,__)
|
||||||
|
if empty_find:
|
||||||
|
for __ in self.follow_set(l):
|
||||||
|
self.insert_tb(_,__)
|
||||||
|
def get_production(self,row,col):
|
||||||
|
return self.tb[self.NTSmp[row][col]]
|
||||||
|
|
||||||
|
def show_me_what_you_got(self,file,show_by_id=False):
|
||||||
|
|
||||||
|
l = ['NTS\\TS']
|
||||||
|
for _ in self.TS:
|
||||||
|
l.append(_)
|
||||||
|
ll = [l]
|
||||||
|
for idx,_ in enumerate(self.tb):
|
||||||
|
l = [self.NTS[idx]]
|
||||||
|
for __ in _:
|
||||||
|
if __ != None:
|
||||||
|
l.append(__.str[int(show_by_id)])
|
||||||
|
else:
|
||||||
|
l.append(' ')
|
||||||
|
ll.append(l)
|
||||||
|
with open(file,'w',newline='')as f:
|
||||||
|
writer = csv.writer(f)
|
||||||
|
writer.writerows(ll)
|
||||||
|
|
||||||
|
|
||||||
|
obj = LL1Generator()
|
||||||
|
obj.compile()
|
||||||
|
obj.show_me_what_you_got("LL1Table_id.csv",show_by_id=True)
|
4
test.py
4
test.py
@ -1,5 +1,5 @@
|
|||||||
from syntax.syntax import PredictingAnalysisTable
|
from syntax.syntax import LL1Generator
|
||||||
|
|
||||||
|
|
||||||
pa_table = PredictingAnalysisTable()
|
pa_table = LL1Generator()
|
||||||
pa_table.compile()
|
pa_table.compile()
|
||||||
|
Loading…
Reference in New Issue
Block a user