All streams
Search
Write a publication
Pull to refresh
0
0

Пользователь

Send message

Я про это писал, но вы к сожалению не поняли. Моё решение было саркастическим, делать реальный проект на его основе нельзя.

Python не общается внешним миром через IO, там нет арифметических типов, do-натации и монад тоже нет. Python и Haskell это два разных мира и тащить абстракции из одного в другой не надо.

parser = SuperParser("+79623333333")

parser.opt(char('+'))
parser.char('7').alt(char('8'))
parser.opt(char('('))
parser.char('9')

code1 = parser.digit()
code2 = parser.digit()
parser.opt(char(')'))

d1 = parser.digit()
d2 = parser.digit()
d3 = parser.digit()

От парсера на Pythone-е ожидаешь что то вроде этого, а не ужаса на корутинах.

А что если Вам нужно получить не весь номер целиком, а цифры в номере третью, седьмую и десятую?

Ну это какой то уникальный случай. По этому я не вижу проблем в распаковке и обращению к строке по индексу. Но тем не менее можно сделать парсер типа такого:

(sity, oper, num1, num2, num3) = super_parser(
(alt, (char('7'), char('8')))
, (opt, char('('))
, number(3)
, (opt, char(')'))
, number(3)
, number(1)
, number(3)
)

Кстати, не подскажете почему Parsec, Megaparsec и другие библиотеки
парсер комбинаторов в Haskell применяют именно описанный мной проход, а
не тот, что Вы предлагаете?

Этот вопрос нужно задать авторам данных библиотек. Но что то мне подсказывает что их парсер может работать только внутри монады IO, это и сформировало такой подход.

Потом как-то по индексам из коллекции нужно извлекать разобранные значения, а такое решение будет очень сложно поддерживать

Как раз наоборот. В примере с телефонным номером результатом разбора стало создание девяти локальных переменных, я же предпочитаю иметь дело с чем то вроде: ("+7", "962", "3333333"). Поддерживать второй вариант гораздо проще. Попробуйте разобрать что то более сложное (например DSL) и тогда поймёте что я имею в виду.

программист сам решает какие структуры данных наиболее удобны для его проекта.

Задача парсера вытащить конкретные значения из переданных данных и всё. То какие структуры данных будут потом созданы от него не зависит.

Вы слишком серьёзно отнеслись к моему комментарию. Его основной посыл в том что даже скобочный синтаксис Lisp-а будет смотреться намного лучше чем попытка переделывания конструкций Haskell-а на Python. Теперь по порядку:

  1. Всё нормально. Результатом работы свертки должна быть функция которая принимает данные и разбирает их последовательно применяя парсеры. Фактически при помощи свёртки создаётся своеобразная композиция комбинаторов.
    Семантика функции and_then конечно будет отличаться от той что сейчас в проекте.

  2. Я не думаю что создание кучи переменных является хорошей идеей. Результатом разбора должна быть какая то коллекция. Но никто не мешает создать под капотом простространство имён куда парсеры
    смогут записывать какие то значения.

Ну ты что то намудрил... Да ещё и попытался переписать функции на ООП. Давай вернём их на место.

Для начала сделаем and_then отдельной функцией и вместо "do - натации" будем с её помощью сворачивать последовательность комбинаторов:

reduce(and_then, (char('7'), char('('), char('9'), ....))

А как же быть с попытками реализации квантеров (opt, many и alt)? Их тоже можно сделать функциями. Тогда парсер phone_number может быть записан в виде последовательности в которой квантероы представлены парами. Такая последовательность может быть рекурсивно редуцированна:

(and_then, (
(alt, (char('7'), char('8')))
, (opt, char('('))
, char('9')
, digit()
, digit()
, (opt, (char(')'))
....
)


Ой! Кажется у меня в место Haskell-а LISP получился... Но так же всё равно интересней. Ведь правда?

ИХМО самый безопасный язык это Haskell.

Information

Rating
Does not participate
Location
Пятигорск, Ставропольский край, Россия
Date of birth
Registered
Activity