|
| |||
|
|
Налабал перевод выражений из инфиксной формы (строки) в префиксную схемовскую, с приоритетами. Заюзал родной схемовский/рэкет парсер read - он и скобки сразу парсит. Взял только *, +, - чтобы проще было сравнивать эвал схемовский (уже после конвертации) с эвалом питона (исходной строки через шелл-колл). С делением схема сумеет рациональные числа, а питон перейдёт на флоаты. Наиболее элегантно получается правыми фолдами: сворачивать по операторам справа налево. И сворачивать само выражение справа налево - для левой ассоциативности: это нежиданно, я с левого фолда начинал. Но и чистым фолдом не получится: нужен и фолд высшего порядка, и вложенные списки путаются под ногами, и рекурсия нужна, нетипичная для фолдов. Короче, внутренняя не свёртка, а сворачивающе-рекурсивная процедура. Назвал pivot, потому что берёт оператор в середине списка, и как бы "свешивает" левый и правый список в дерево с оператором в корне, лифтит оператор, по сути. Понятно стало, как и под правоассоциативные операторы обобщить. Те же числа, присваивающиеся в расхожих ЯП приоритетам, кажется, и не нужны вовсе: приоритеты - это упорядоченный список операций. Числа, наверное, чтобы чуть уменьшить количество проходов по выражению. Ещё небольшие непонятки с арностью. Кажется, в обычных ЯП или унарные, или бинарные операторы только бывают. Инвалидный тернарный с++ оператор не стоит учитывать. Если оператор с 3+ операндами, то его непонятно, как записывать... кроме как функцию. Поэтому обобщать по арности такой парсер выражений и не нужно, по идее. Но вот из нормальных может быть и вариадный, унарно-бинарный мутант. Конкретно "-" такой оказался. Вроде и легко его рассматривать как бинарный, а если внезапно пустые списки где-нибудь остаются, заменять их на 0. Так случай унарного - или + обрабатывается. Но кривовато как-то получается, вариадность не декларируется явно. |
|||||||||||||