Пакет indents для Haskell Parsec обеспечивает способ анализа языков в стиле отступа (например, Haskell и Python). Он переопределяет тип Parser, поэтому как вы используете функции парсера токенов, экспортируемые модулем Parsec Text.Parsec.Token, которые имеют обычный тип Parser?
Фон
- Parsec - это библиотека комбинаторного анализатора, что бы это ни значило.
- IndentParser 0.2.1 - это старый пакет, предоставляющий два модуля
Text.ParserCombinators.Parsec.IndentParserиText.ParserCombinators.Parsec.IndentParser.Token - indents 0.3.3 - это новый пакет, предоставляющий единый модуль
Text.Parsec.Indent
Parsec поставляется с загрузкой модулей. большинство из них экспортируют кучу полезных парсеров (например, newline из Text.Parsec.Char, который анализирует новую строку) или комбинаторы парсеров (например, count n p из Text.Parsec.Combinator, который запускает парсер p, n раз)
Однако модуль Text.Parsec.Token хотел бы экспортировать функции, которые параметризованы пользователем с функциями анализируемого языка, так что, например, Функция braces p запустит парсер p после разбора '{' и до синтаксического анализа '}', игнорируя такие вещи, как комментарии, синтаксис которых зависит от вашего языка.
Способ, которым Text.Parsec.Token достигает этого, заключается в том, что он экспортирует одну функцию makeTokenParser, который вы вызываете, предоставляя ему параметры вашего конкретного языка (например, как выглядит комментарий) и возвращает запись, содержащую все функции в Text.Parsec.Token, адаптированные на ваш язык, как указано.
Конечно, в языке с отступом они должны быть адаптированы (возможно, здесь, где я не уверен - я объясню в одно мгновение), поэтому я отмечаю, что (предположительно устаревший) пакет IndentParser предоставляет модуль Text.ParserCombinators.Parsec.IndentParser.Token, который выглядит как замена для Text.Parsec.Token.
В какой-то момент я должен упомянуть, что все парсеры Parsec являются монадическими функциями, поэтому они делают магические вещи с состоянием, чтобы сообщения об ошибках могли сказать, в какой строке и столбце в исходном файле появилась ошибка.
Моя проблема
По нескольким небольшим причинам мне кажется, что пакет indents больше или меньше текущей версии IndentParser, однако он не предоставляет модуль который выглядит как Text.ParserCombinators.Parsec.IndentParser.Token, он предоставляет только Text.Parsec.Indent, поэтому Мне интересно, как сделать все парсера-маркера из Text.Parsec.Token (например, reserved "something", который анализирует зарезервированное ключевое слово "что-то" или как braces, о котором я упоминал ранее).
Мне кажется, что (новый) Text.Parsec.Indent работает с помощью какой-то монадической магии штата, чтобы разобраться в каких битах столбца исходного кода, так что ему не нужно модифицировать парсеров-маркеров, таких как whiteSpace от Text.Parsec.Token, что, вероятно, поэтому не дает заменяющего модуля. Но у меня проблема с типами.
Вы видите, что без Text.Parsec.Indent все мои парсеры имеют тип Parser Something, где Something - тип возвращаемого значения, а Parser - это псевдоним типа, определенный в Text.Parsec.String как
type Parser = Parsec String ()
но с Text.Parsec.Indent вместо импорта Text.Parsec.String я использую собственное определение
type Parser a = IndentParser String () a
который делает все мои парсеры типа IndentParser String () Something, где IndentParser определен в Text.Parsec.Indent. но анализаторы токенов, которые я получаю от makeTokenParser в Text.Parsec.Token, имеют неправильный тип.
Если это пока не имеет большого смысла, это потому, что я немного потерян. Проблема с типом обсуждается здесь.
Ошибка, которую я получаю, заключается в том, что я попытался заменить одно определение Parser выше на другое, но тогда, когда я пытаюсь использовать один из парсеров токенов из Text.Parsec.Token, я получаю ошибку компиляции.
Couldn't match expected type `Control.Monad.Trans.State.Lazy.State
Text.Parsec.Pos.SourcePos'
with actual type `Data.Functor.Identity.Identity'
Expected type: P.GenTokenParser
String
()
(Control.Monad.Trans.State.Lazy.State Text.Parsec.Pos.SourcePos)
Actual type: P.TokenParser ()
Ссылки
- Parsec
- IndentParser (старый пакет)
- indents, предоставляя Text.Parsec.Indent(новый пакет)
- некоторое обсуждение типов Parser с примером кода
- еще один пример использования Text.Parsec.Indent
К сожалению, ни один из приведенных выше примеров не использует парсера парсера, как те, что находятся в Text.Parsec.Token.