Войти в систему

Home
    - Создать дневник
    - Написать в дневник
       - Подробный режим

LJ.Rossia.org
    - Новости сайта
    - Общие настройки
    - Sitemap
    - Оплата
    - ljr-fif

Редактировать...
    - Настройки
    - Список друзей
    - Дневник
    - Картинки
    - Пароль
    - Вид дневника

Сообщества

Настроить S2

Помощь
    - Забыли пароль?
    - FAQ
    - Тех. поддержка



Пишет superhuman ([info]superhuman)
@ 2018-02-02 10:53:00


Previous Entry  Add to memories!  Tell a Friend!  Next Entry
Налабал перевод выражений из инфиксной формы (строки) в префиксную схемовскую, с приоритетами. Заюзал родной схемовский/рэкет парсер read - он и скобки сразу парсит.

Взял только *, +, - чтобы проще было сравнивать эвал схемовский (уже после конвертации) с эвалом питона (исходной строки через шелл-колл). С делением схема сумеет рациональные числа, а питон перейдёт на флоаты.

Наиболее элегантно получается правыми фолдами: сворачивать по операторам справа налево. И сворачивать само выражение справа налево - для левой ассоциативности: это нежиданно, я с левого фолда начинал. Но и чистым фолдом не получится: нужен и фолд высшего порядка, и вложенные списки путаются под ногами, и рекурсия нужна, нетипичная для фолдов.

Короче, внутренняя не свёртка, а сворачивающе-рекурсивная процедура. Назвал pivot, потому что берёт оператор в середине списка, и как бы "свешивает" левый и правый список в дерево с оператором в корне, лифтит оператор, по сути.

Понятно стало, как и под правоассоциативные операторы обобщить. Те же числа, присваивающиеся в расхожих ЯП приоритетам, кажется, и не нужны вовсе: приоритеты - это упорядоченный список операций. Числа, наверное, чтобы чуть уменьшить количество проходов по выражению.

Ещё небольшие непонятки с арностью. Кажется, в обычных ЯП или унарные, или бинарные операторы только бывают. Инвалидный тернарный с++ оператор не стоит учитывать. Если оператор с 3+ операндами, то его непонятно, как записывать... кроме как функцию. Поэтому обобщать по арности такой парсер выражений и не нужно, по идее.

Но вот из нормальных может быть и вариадный, унарно-бинарный мутант. Конкретно "-" такой оказался. Вроде и легко его рассматривать как бинарный, а если внезапно пустые списки где-нибудь остаются, заменять их на 0. Так случай унарного - или + обрабатывается. Но кривовато как-то получается, вариадность не декларируется явно.