Files
BiPy/tokenEditor.py
T
2026-05-03 21:02:34 +07:00

153 lines
7.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import tkinter as tk
from tkinter import scrolledtext, messagebox, filedialog
import re
class TokenManager:
def __init__(self, root):
self.root = root
self.root.title("C++ Tokenizer Manager (Pro)")
self.root.geometry("1000x900")
self.root.configure(bg="#f5f5f5")
self.tokens = []
# --- Секция 1: Ввод и Загрузка ---
top_frame = tk.Frame(root, bg="#f5f5f5")
top_frame.pack(fill=tk.X, padx=15, pady=10)
tk.Label(top_frame, text="1. Управление токенами:", font=('Arial', 10, 'bold'), bg="#f5f5f5").pack(side=tk.LEFT)
btn_load_file = tk.Button(top_frame, text="📥 Загрузить и разбить датасет (.txt)",
command=self.load_dataset_file, bg="#FF9800", fg="white", font=('Arial', 9, 'bold'))
btn_load_file.pack(side=tk.RIGHT, padx=5)
self.input_area = scrolledtext.ScrolledText(root, height=6, font=('Consolas', 10))
self.input_area.pack(padx=15, pady=5, fill=tk.X)
self.input_area.insert(tk.END, "// Вставьте старый код конструктора сюда или используйте кнопку загрузки файла...")
btn_parse = tk.Button(root, text="Извлечь токены из кода выше", command=self.parse_input, bg="#2196F3", fg="white")
btn_parse.pack(pady=5)
# --- Секция 2: Средняя часть (Добавление и Список) ---
middle_frame = tk.Frame(root, bg="#f5f5f5")
middle_frame.pack(padx=15, pady=10, fill=tk.BOTH, expand=True)
# Левая колонка: Добавление
left_col = tk.LabelFrame(middle_frame, text="Добавить вручную", padx=10, pady=10)
left_col.pack(side=tk.LEFT, fill=tk.BOTH, expand=True, padx=(0, 10))
self.new_token_entry = tk.Entry(left_col, font=('Arial', 11))
self.new_token_entry.pack(fill=tk.X, pady=5)
self.new_token_entry.bind('<Return>', lambda e: self.add_single_token())
tk.Button(left_col, text="Добавить в список", command=self.add_single_token, bg="#4CAF50", fg="white").pack(fill=tk.X, pady=5)
# Правая колонка: Просмотр
self.right_col = tk.LabelFrame(middle_frame, text="Текущий список (0 токенов)", padx=10, pady=10)
self.right_col.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
list_scroll = tk.Scrollbar(self.right_col)
list_scroll.pack(side=tk.RIGHT, fill=tk.Y)
self.token_listbox = tk.Listbox(self.right_col, font=('Arial', 10), yscrollcommand=list_scroll.set, selectmode=tk.EXTENDED)
self.token_listbox.pack(side=tk.LEFT, fill=tk.BOTH, expand=True)
list_scroll.config(command=self.token_listbox.yview)
tk.Button(self.right_col, text="Удалить выбранные", command=self.delete_selected, bg="#F44336", fg="white").pack(fill=tk.X, pady=(5,0))
# --- Секция 3: Вывод результата ---
tk.Label(root, text="3. Готовый код для C++ (token.cpp):", font=('Arial', 10, 'bold'), bg="#f5f5f5").pack(pady=(10,0))
self.output_area = scrolledtext.ScrolledText(root, height=15, bg="#fafafa", font=('Consolas', 10), fg="#2e7d32")
self.output_area.pack(padx=15, pady=5, fill=tk.X)
# Нижняя панель
bottom_frame = tk.Frame(root, bg="#f5f5f5")
bottom_frame.pack(fill=tk.X, padx=15, pady=10)
self.status_label = tk.Label(bottom_frame, text="Количество токенов: 0", font=('Arial', 11, 'bold'), bg="#f5f5f5")
self.status_label.pack(side=tk.LEFT)
tk.Button(bottom_frame, text="📋 Копировать код", command=self.copy_to_clipboard, bg="#9E9E9E", fg="white", font=('Arial', 10, 'bold')).pack(side=tk.RIGHT)
def load_dataset_file(self):
"""Открывает файл и разбивает его на токены согласно правилам"""
file_path = filedialog.askopenfilename(filetypes=[("Text files", "*.txt"), ("All files", "*.*")])
if not file_path:
return
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
# РЕГУЛЯРНОЕ ВЫРАЖЕНИЕ:
# [a-zA-Zа-яА-Я0-9ёЁ-]+ --> Слова (включая цифры и дефисы внутри типа "что-то")
# [^\w\s] --> Любой символ, который не буква и не пробел (знаки препинания)
pattern = r"[a-zA-Zа-яА-Я0-9ёЁ-]+|[^\w\s]"
raw_tokens = re.findall(pattern, content)
new_count = 0
for t in raw_tokens:
if t not in self.tokens:
self.tokens.append(t)
new_count += 1
self.refresh_ui()
messagebox.showinfo("Загрузка завершена", f"Всего токенов найдено: {len(raw_tokens)}\nДобавлено новых уникальных: {new_count}")
except Exception as e:
messagebox.showerror("Ошибка", f"Не удалось прочитать файл:\n{str(e)}")
def parse_input(self):
text = self.input_area.get("1.0", tk.END)
found = re.findall(r'add\("(.*?)"\);', text)
if not found:
messagebox.showwarning("Внимание", "Используйте формат add(\"слово\");")
return
added = 0
for t in found:
if t not in self.tokens:
self.tokens.append(t)
added += 1
self.refresh_ui()
def add_single_token(self):
raw_input = self.new_token_entry.get().strip()
if not raw_input: return
if raw_input not in self.tokens:
self.tokens.append(raw_input)
self.refresh_ui()
self.new_token_entry.delete(0, tk.END)
def delete_selected(self):
indices = self.token_listbox.curselection()
to_remove = [self.token_listbox.get(i) for i in indices]
for val in to_remove:
self.tokens.remove(val)
self.refresh_ui()
def refresh_ui(self):
self.token_listbox.delete(0, tk.END)
for t in self.tokens:
self.token_listbox.insert(tk.END, t)
self.right_col.config(text=f"Текущий список ({len(self.tokens)} токенов)")
self.output_area.delete("1.0", tk.END)
code = "Tokenizer() {\n"
# Группируем по 6 для красоты в C++
for i in range(0, len(self.tokens), 6):
line = self.tokens[i:i+6]
code += " " + " ".join([f'add("{t}");' for t in line]) + "\n"
code += " }"
self.output_area.insert(tk.END, code)
self.status_label.config(text=f"Количество токенов: {len(self.tokens)}")
def copy_to_clipboard(self):
self.root.clipboard_clear()
self.root.clipboard_append(self.output_area.get("1.0", tk.END))
messagebox.showinfo("ОК", "Код скопирован")
if __name__ == "__main__":
root = tk.Tk()
app = TokenManager(root)
root.mainloop()