You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

202 lines
5.6 KiB

# -*- 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):
11 months ago
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):
11 months ago
# 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)