Существует ли установленный способ писать парсеры, которые могут восстановить их точный ввод?

Скажем, я хочу проанализировать файл на языке X. Действительно, меня интересует только небольшая часть информации внутри. Достаточно легко написать парсер в одном из Haskell для многих eDSL для этой цели (например, Megaparsec).

data Foo = Foo Int  -- the information I'm after.

parseFoo :: Parsec Text Foo
parseFoo = ...

Это легко дает функцию getFoo :: Text -> Maybe Foo.

Но теперь я также хотел бы изменить источник информации Foo, т.е. в основном я хочу реализовать

changeFoo :: (Foo -> Foo) -> Text -> Text

со свойствами

changeFoo id ≡ id
getFoo . changeFoo f ≡ fmap f . getFoo

Это можно сделать, изменив результат анализатора на что-то вроде объектива

parseFoo :: Parsec Text (Foo, Foo -> Text)
parseFoo = ...

но это делает определение намного более громоздким - ndash; Я больше не могу просто замалчивать ненужную информацию, но вам нужно сохранить совпадение каждого подпакета string и вручную собрать его.

Это может быть несколько автоматизировано, сохраняя повторную сборку строк на уровне StateT вокруг монарды синтаксического анализатора, но я не мог просто использовать существующие примитивные синтаксические анализаторы.

Существует ли существующее решение для этой проблемы?

Ответ 1

Решение, реализованное в Haskell? Я не знаю ни одного; они могут существовать.

В общем, можно хранить достаточно информации, чтобы восстановить законную версию программы, которая похожа на оригинал в произвольной степени, путем хранения "форматирования" информации с помощью собранных жетонов. В пределе форматная информация является исходной строкой для токена; любое приближение этого будет давать менее точные ответы.

Если вы сохраняете пробелы как явные токены в дереве разбора, в пределе вы можете даже восстановить его. Может ли это быть полезным, вероятно, зависит от приложения. В общем, я думаю, что это слишком много.

Подробная информация о том, что/как взять и как восстановить, можно найти в моем ответе SO: Компиляция AST обратно в исходный код