|
|
|
|
# -*- encoding: utf-8 -*-
|
|
|
|
|
"""
|
|
|
|
|
@Author: packy945
|
|
|
|
|
@FileName: TreeNode.py
|
|
|
|
|
@DateTime: 2023/5/15 14:27
|
|
|
|
|
@SoftWare: PyCharm
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
import re
|
|
|
|
|
import tkinter as tk
|
|
|
|
|
from data import *
|
|
|
|
|
import tkinter.messagebox
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Tree:
|
|
|
|
|
def __init__(self):
|
|
|
|
|
self.bc = 70
|
|
|
|
|
self.Node = []
|
|
|
|
|
self.rootID = None
|
|
|
|
|
self.deepth = []
|
|
|
|
|
self.place = []
|
|
|
|
|
self.mark = [0] * 110
|
|
|
|
|
self.ck = []
|
|
|
|
|
|
|
|
|
|
def check(self):
|
|
|
|
|
self.ck = [1] * len(self.Node)
|
|
|
|
|
for N in self.Node:
|
|
|
|
|
if N[3]:
|
|
|
|
|
self.ck[N[3]] = 0
|
|
|
|
|
if N[4]:
|
|
|
|
|
self.ck[N[4]] = 0
|
|
|
|
|
|
|
|
|
|
def remark(self):
|
|
|
|
|
self.mark = [0] * 110
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def deep(self):
|
|
|
|
|
flag = 0
|
|
|
|
|
for i in range(len(self.Node)):
|
|
|
|
|
if self.Node[i][1] == 'Value':
|
|
|
|
|
self.deepth[i] = 0
|
|
|
|
|
|
|
|
|
|
for i in range(len(self.Node)):
|
|
|
|
|
if self.deepth[i] == -1:
|
|
|
|
|
flag = 1
|
|
|
|
|
if self.Node[i][3] != None and self.Node[i][4] != None:
|
|
|
|
|
# print(self.Node[i][3], self.Node[i][4])
|
|
|
|
|
self.deepth[i] = max(self.deepth[self.Node[i][3]], self.deepth[self.Node[i][4]]) + 1
|
|
|
|
|
# print(self.deepth)
|
|
|
|
|
if flag:
|
|
|
|
|
self.deep()
|
|
|
|
|
|
|
|
|
|
def calculate(self, node):
|
|
|
|
|
# print(node)
|
|
|
|
|
if node[1] == 'Value':
|
|
|
|
|
return node[5] * 1.0
|
|
|
|
|
elif node[1] == 'Operator':
|
|
|
|
|
a = self.calculate(self.Node[node[3]])
|
|
|
|
|
b = self.calculate(self.Node[node[4]])
|
|
|
|
|
if node[2] == '^':
|
|
|
|
|
return pow(int(a), int(b))
|
|
|
|
|
else:
|
|
|
|
|
# print(a,node[2],b)
|
|
|
|
|
return eval(str(a) + node[2] + str(b))
|
|
|
|
|
|
|
|
|
|
def Aexp(self, node):
|
|
|
|
|
|
|
|
|
|
if node[1] == 'Value':
|
|
|
|
|
return str(node[5])
|
|
|
|
|
elif node[1] == 'Operator':
|
|
|
|
|
a = self.Aexp(self.Node[node[3]])
|
|
|
|
|
b = self.Aexp(self.Node[node[4]])
|
|
|
|
|
# print(a,node[2],b)
|
|
|
|
|
ans = '(' + str(a) + node[2] + str(b) + ')'
|
|
|
|
|
# print(ans)
|
|
|
|
|
return ans
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
tree = Tree()
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
cur = 0
|
|
|
|
|
class TreeNode:
|
|
|
|
|
def __init__(self, Type, value, left=None, right=None, color='方块'):
|
|
|
|
|
global cur
|
|
|
|
|
self.NodeID = cur # 节点编号
|
|
|
|
|
cur += 1
|
|
|
|
|
self.NodeType = Type # 节点类型
|
|
|
|
|
self.Ops = None # 运算符类型
|
|
|
|
|
self.left = left
|
|
|
|
|
self.right = right
|
|
|
|
|
self.LeftNodeID = None
|
|
|
|
|
self.RightNodeID = None
|
|
|
|
|
if self.left:
|
|
|
|
|
self.LeftNodeID = left.NodeID # 左节点编号
|
|
|
|
|
if self.right:
|
|
|
|
|
self.RightNodeID = right.NodeID # 右节点编号
|
|
|
|
|
self.FaceValue = None # 节点数值
|
|
|
|
|
self.FaceColor = color # 节点花色
|
|
|
|
|
if Type == 'Value':
|
|
|
|
|
self.FaceValue = value
|
|
|
|
|
else:
|
|
|
|
|
self.Ops = value
|
|
|
|
|
|
|
|
|
|
tree.Node.append([self.NodeID, self.NodeType, self.Ops, self.LeftNodeID, self.RightNodeID, self.FaceValue, self.FaceColor])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def build_ast(formula):
|
|
|
|
|
'''
|
|
|
|
|
建立语法树
|
|
|
|
|
:param formula: 表达式,表达式的花色
|
|
|
|
|
:return: 建立好的语法树
|
|
|
|
|
'''
|
|
|
|
|
# 去掉空格
|
|
|
|
|
|
|
|
|
|
global tree, cur
|
|
|
|
|
try:
|
|
|
|
|
expr, color = formula
|
|
|
|
|
except:
|
|
|
|
|
expr = formula
|
|
|
|
|
color = ['方块'] * 20
|
|
|
|
|
if len(expr) == 0:
|
|
|
|
|
tk.messagebox.showinfo('', '表达式不存在')
|
|
|
|
|
return
|
|
|
|
|
cur = 0
|
|
|
|
|
tree.__init__()
|
|
|
|
|
|
|
|
|
|
expr = expr.replace(' ', '')
|
|
|
|
|
|
|
|
|
|
# 将所有数字和符号分离出来
|
|
|
|
|
tokens = re.findall(r'\d+|[()+\-*/^.]', expr)
|
|
|
|
|
i = 0
|
|
|
|
|
for token in tokens:
|
|
|
|
|
if tokens[i] == '.':
|
|
|
|
|
|
|
|
|
|
tokens[i - 1] = tokens[i - 1] + tokens[i] + tokens[i + 1]
|
|
|
|
|
del tokens[i: i + 2]
|
|
|
|
|
i += 1
|
|
|
|
|
|
|
|
|
|
# 定义优先级
|
|
|
|
|
precedence = {'+': 1, '-': 1, '*': 2, '/': 2, '^': 3}
|
|
|
|
|
|
|
|
|
|
# 创建一个操作符栈和一个节点栈
|
|
|
|
|
op_stack = []
|
|
|
|
|
node_stack = []
|
|
|
|
|
|
|
|
|
|
color_cur = 0
|
|
|
|
|
# 遍历所有 token
|
|
|
|
|
for token in tokens:
|
|
|
|
|
if token.isdigit():
|
|
|
|
|
# print(cur, color[cur])
|
|
|
|
|
node_stack.append(TreeNode('Value', int(token), color=color[color_cur]))
|
|
|
|
|
color_cur += 1
|
|
|
|
|
elif token.count('.') == 1:
|
|
|
|
|
node_stack.append(TreeNode('Value', float(token), color=color[color_cur]))
|
|
|
|
|
color_cur += 1
|
|
|
|
|
elif token in '+-*/^':
|
|
|
|
|
while op_stack and op_stack[-1] != '(' and precedence[token] <= precedence[op_stack[-1]]:
|
|
|
|
|
op = op_stack.pop()
|
|
|
|
|
right = node_stack.pop()
|
|
|
|
|
left = node_stack.pop()
|
|
|
|
|
node_stack.append(TreeNode('Operator', op, left, right))
|
|
|
|
|
op_stack.append(token)
|
|
|
|
|
elif token == '(':
|
|
|
|
|
op_stack.append(token)
|
|
|
|
|
elif token == ')':
|
|
|
|
|
while op_stack and op_stack[-1] != '(':
|
|
|
|
|
op = op_stack.pop()
|
|
|
|
|
right = node_stack.pop()
|
|
|
|
|
left = node_stack.pop()
|
|
|
|
|
node_stack.append(TreeNode('Operator', op, left, right))
|
|
|
|
|
op_stack.pop()
|
|
|
|
|
|
|
|
|
|
# 处理剩下的操作符
|
|
|
|
|
while op_stack:
|
|
|
|
|
op = op_stack.pop()
|
|
|
|
|
right = node_stack.pop()
|
|
|
|
|
left = node_stack.pop()
|
|
|
|
|
node_stack.append(TreeNode('Operator', op, left, right))
|
|
|
|
|
|
|
|
|
|
# 返回抽象语法树的根节点
|
|
|
|
|
tree.rootID = node_stack[0].NodeID
|
|
|
|
|
# print(tree.rootID)
|
|
|
|
|
# print(tree.Node)
|
|
|
|
|
return node_stack[0]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def print_ast(node:TreeNode, prefix='', is_left=True):
|
|
|
|
|
if node:
|
|
|
|
|
if node.NodeType == 'Value':
|
|
|
|
|
s = str(node.FaceValue)
|
|
|
|
|
else:
|
|
|
|
|
s = str(node.Ops)
|
|
|
|
|
print(prefix + ('├── ' if is_left else '└── ') + s)
|
|
|
|
|
print_ast(node.left, prefix + ('│ ' if is_left else ' '), True)
|
|
|
|
|
print_ast(node.right, prefix + ('│ ' if is_left else ' '), False)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|