Ответ 1
Как все уже сказали haskell-src-meta
предоставляет
parsePat :: String -> Either String Pat
parseExp :: String -> Either String Exp
parseType :: String -> Either String Type
parseDecs :: String -> Either String [Dec]
где Pat
, Exp
, Type
и Dec
такие же, как от Language.Haskell.TH.Syntax
.
Почему GHC не выставляет собственный парсер?
Это так. Fire GHCi с ghci -package ghc
(ghc
- скрытый пакет по умолчанию), и вы можете импортировать Parser
. Он имеет функции для синтаксического анализа String
в предварительные АСТ (декларации данных которых находятся в HsSyn
) для шаблонов, выражений, типов и деклараций.
ОК, тогда почему не существует библиотеки, которая использует этот синтаксический анализатор, и преобразует свой вывод в AST из
template-haskell
(тот, который находится вLanguage.Haskell.TH.Syntax
)?
Заглядывая в HsSyn
, очевидно, что AST не совсем то же самое, что в Language.Haskell.TH.Syntax
. Откройте оба HsExpr
и Exp
и бок о бок вы увидите, что последний заполнен такими типами, как PostTc id <some-other-type>
и PostRn id <some-other-type>
. Поскольку AST передается от анализатора к переименованному устройству проверки типов, эти биты и кусочки медленно заполняются. Например, мы даже не знаем ограничений операторов до тех пор, пока не получим проверку типов!
Чтобы выполнить нужные функции, нам нужно будет запускать гораздо больше, чем просто синтаксический анализатор (по крайней мере, переименовать и проверить тип, возможно, больше). Представьте себе, что: каждый раз, когда вы хотите разобрать даже небольшое выражение, например "1 + 2"
, вам все равно придется набирать контрольный кучу импорта. Даже тогда преобразование обратно в Language.Haskell.TH.Syntax
не было бы прогулкой в парке: GHC имеет множество особенностей, таких как собственные специальные глобальный способ хранения имен и идентификаторов.
Хммм... но что делает GHC с квазициклами?
Это крутая часть! В отличие от Exp
, HsExpr
имеет HsSplice
для представления сращений. Посмотрите типы для первых двух конструкторов:
HsTypedSplice :: id -> LHsExpr id -> HsSplice id. -- things like [|| 1 + 2 ||]
HsUntypedSplice :: id -> LHsExpr id -> HsSplice id -- things like [| 1 + 2 |]
Обратите внимание, что они не сохраняют String
, они уже хранят AST! Сочетания обрабатываются одновременно с остальной частью АСТ. И точно так же, как и остальные АСТ, сращивания будут передаваться вместе с переименователем, контролером типа и т.д., Где пропущенная информация будет заполнена.
Так что в принципе невозможно использовать парсер GHC
Наверное, нет. Но вывести его из остальной части GHC может быть довольно сложно. Если использовать парсер GHC, мы должны также запустить средство проверки типов и переименовать, может быть более элегантным и простым просто использовать автономный синтаксический анализатор, такой как haskell-src-exts
(от которого зависит haskell-src-meta
), который может сделать все за один проход (например, исправления - это одна из вещей, которые вы должны заранее дать этому парсеру).