Пакет 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.