141 lines
5.2 KiB
Python
141 lines
5.2 KiB
Python
|
|
#!/usr/bin/env python3
|
|||
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
|
|||
|
|
"""
|
|||
|
|
Третий проход КВС
|
|||
|
|
- Читает AST для получения констант
|
|||
|
|
- Заменяет имена констант в 'исходная_команда' на их числовые значения
|
|||
|
|
- Записывает результат в колонку 'команда_со_значениями'
|
|||
|
|
- Поддерживает константы в операндах (как непосредственные значения)
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import sys
|
|||
|
|
import csv
|
|||
|
|
|
|||
|
|
|
|||
|
|
def read_ast(ast_file):
|
|||
|
|
"""Читает AST файл и извлекает константы"""
|
|||
|
|
symbols = {} # имя константы -> значение
|
|||
|
|
|
|||
|
|
with open(ast_file, 'r', encoding='utf-8') as f:
|
|||
|
|
for line in f:
|
|||
|
|
line = line.strip()
|
|||
|
|
if not line:
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
parts = line.split(':')
|
|||
|
|
if parts[0] == "DIRECTIVE" and len(parts) >= 4:
|
|||
|
|
directive = parts[1]
|
|||
|
|
if directive == '.константа':
|
|||
|
|
name = parts[2]
|
|||
|
|
value_str = parts[3]
|
|||
|
|
if value_str.startswith('0x') or value_str.startswith('0X'):
|
|||
|
|
value = int(value_str, 16)
|
|||
|
|
else:
|
|||
|
|
value = int(value_str)
|
|||
|
|
symbols[name] = value
|
|||
|
|
print(f" константа: {name} = {value}")
|
|||
|
|
|
|||
|
|
return symbols
|
|||
|
|
|
|||
|
|
|
|||
|
|
def read_csv(csv_file):
|
|||
|
|
"""Читает CSV файл и возвращает список записей и заголовки"""
|
|||
|
|
entries = []
|
|||
|
|
headers = []
|
|||
|
|
|
|||
|
|
with open(csv_file, 'r', encoding='utf-8') as f:
|
|||
|
|
reader = csv.reader(f, delimiter=';')
|
|||
|
|
headers = next(reader)
|
|||
|
|
for row in reader:
|
|||
|
|
entries.append(row)
|
|||
|
|
|
|||
|
|
return headers, entries
|
|||
|
|
|
|||
|
|
|
|||
|
|
def substitute_constants(entries, headers, symbols):
|
|||
|
|
"""Заменяет константы в исходной команде на их значения"""
|
|||
|
|
try:
|
|||
|
|
source_idx = headers.index('исходная_команда')
|
|||
|
|
source_with_values_idx = headers.index('команда_со_значениями')
|
|||
|
|
except ValueError as e:
|
|||
|
|
print(f"Ошибка: не найдена нужная колонка в CSV: {e}")
|
|||
|
|
sys.exit(1)
|
|||
|
|
|
|||
|
|
substituted_count = 0
|
|||
|
|
|
|||
|
|
for row in entries:
|
|||
|
|
source = row[source_idx].strip()
|
|||
|
|
if not source:
|
|||
|
|
continue
|
|||
|
|
|
|||
|
|
# Копируем исходную команду
|
|||
|
|
new_source = source
|
|||
|
|
|
|||
|
|
# Заменяем константы в команде
|
|||
|
|
for name, value in symbols.items():
|
|||
|
|
if name in new_source:
|
|||
|
|
# Заменяем имя константы на её значение
|
|||
|
|
new_source = new_source.replace(name, str(value))
|
|||
|
|
|
|||
|
|
# Если команда изменилась, записываем в колонку команда_со_значениями
|
|||
|
|
if new_source != source:
|
|||
|
|
row[source_with_values_idx] = new_source
|
|||
|
|
substituted_count += 1
|
|||
|
|
|
|||
|
|
return substituted_count
|
|||
|
|
|
|||
|
|
|
|||
|
|
def save_csv(csv_file, headers, entries):
|
|||
|
|
"""Сохраняет обновлённый CSV файл"""
|
|||
|
|
with open(csv_file, 'w', newline='', encoding='utf-8') as f:
|
|||
|
|
writer = csv.writer(f, delimiter=';')
|
|||
|
|
writer.writerow(headers)
|
|||
|
|
writer.writerows(entries)
|
|||
|
|
|
|||
|
|
|
|||
|
|
def print_statistics(symbols_count, substituted_count, symbols):
|
|||
|
|
"""Выводит статистику по заменам констант"""
|
|||
|
|
print(f"\n--- Статистика замены констант ---")
|
|||
|
|
print(f" Всего констант в AST: {symbols_count}")
|
|||
|
|
print(f" Заменено в командах: {substituted_count}")
|
|||
|
|
|
|||
|
|
if symbols:
|
|||
|
|
print(f"\n--- Найденные константы ---")
|
|||
|
|
for name, value in sorted(symbols.items()):
|
|||
|
|
print(f" {name} = {value}")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def main():
|
|||
|
|
if len(sys.argv) != 3:
|
|||
|
|
print("Использование: python kvs_pass3.py <аст.файл> <входной.csv>")
|
|||
|
|
print(" <аст.файл> - файл с AST (например, программа.аст)")
|
|||
|
|
print(" <входной.csv> - CSV файл для обновления")
|
|||
|
|
sys.exit(1)
|
|||
|
|
|
|||
|
|
ast_file = sys.argv[1]
|
|||
|
|
csv_file = sys.argv[2]
|
|||
|
|
|
|||
|
|
print(f"\n=== Третий проход КВС ===")
|
|||
|
|
print(f"Чтение AST: {ast_file}")
|
|||
|
|
|
|||
|
|
# Читаем константы из AST
|
|||
|
|
symbols = read_ast(ast_file)
|
|||
|
|
print(f"Найдено констант: {len(symbols)}")
|
|||
|
|
|
|||
|
|
print(f"\nЧтение CSV: {csv_file}")
|
|||
|
|
headers, entries = read_csv(csv_file)
|
|||
|
|
|
|||
|
|
print(f"\n--- Замена констант в командах ---")
|
|||
|
|
substituted_count = substitute_constants(entries, headers, symbols)
|
|||
|
|
|
|||
|
|
print_statistics(len(symbols), substituted_count, symbols)
|
|||
|
|
|
|||
|
|
# Сохраняем результат
|
|||
|
|
save_csv(csv_file, headers, entries)
|
|||
|
|
print(f"\nCSV сохранен: {csv_file}")
|
|||
|
|
print(f"Колонка 'команда_со_значениями' обновлена")
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
main()
|