Далее "моя" реализация. "Моя" - потому что я заиспользовал комбинаторы.
Парсер комбинаторы - круто. Смотрим и
Эта часть легко находится по подстроке "-- Carsten Schuermann: From: Monadic Parser Combinators [Hutton, Meijer]"
Тут пока некоторая магия, в которую за 5 минут не въехать. Далее должно быть понятнее.
AST - это или ссылка на ячейку, или число, или бинарный оператор из AST.
Вводим парсер для AST. Опишем стандартные арифметические операторы.
А теперь *барабанная дробь*
Собственно все, парсер (лексер + синтАнализатор) готов.
Запускаем и оно работает.
Где вы еще сможете в 3-4Кб уложится? Это вам не парсер-генератор, здесь все сделано вручную... Правда, исходя из этого - это LL. Бывает кое-что затруднительно выразить в LL, да еще и следить за левой рекурсией. LR вручную непросто реализовать, но мне местами такая грамматика больше нравится. Есть еще всякие PEG/Packrat, с не очень понятной теорией (трудно понять, выразима ли конкретная грамматика в них), и куча непрактичных но теоретических парсеров.
Далее опишем типы для "excel". Ячейка - есть строка, лист как коллекция пар из (ячейка, строковая формула) и так далее. В идеале надо бы абстрактный маппинг (словарь/функцию) из ячейки в формулу.
Простая вычислялка AST и вычислялка для строки.
Пара тривиальных вещей:
Несколько типов для вычислителя excel-я.
EvaluatedCellBuffer - это результат вычислений. Далее его как аккумулятор и будем вычислять.
Вся логика вычислений в следующем:
Далее очевидная вода:
Вычисление одной ячейки:
Тривиальный вычислитель
Пара утилитных функций
И вычисление всего листа
Примеры листов:
И примеры:
Еще можно добавить шапочку :)
В 8Кб имеет парсер, AST, вычислитель, и обход и расчет листа excel.
Несложно расширяемо на
- функции и несложную типизацию в встроенном языке
- отказаться от дву(3 ли 3.5 как в excel) мерности задачи и перейти к произвольной размерности.
У меня в текущем проекте есть нечто похожее, но это явно не 8Кб.
ЗЫ. Научиться бы здесь нормальное форматирование делать... В процессе.
Комментариев нет:
Отправить комментарий