Как использовать комбинаторы мегапарсек на StateT
Я строю компилятор для Java для университетского проекта, в моем проекте мои парсеры в основном StateT (Scope,SymbolTable) String m a
где Scope
это область, в которой мы находимся сейчас (метод, класс и т. д.) и SymbolTable
содержит символы, определенные до сих пор.
Я хотел использовать комбинаторы мегапарсек на этих парсерах, для parens
,braces
это не проблема, я просто использую mapStateT
но для sepBy
и другие разработали эту функцию:
mapsequence :: (Monoid s,Monad m) => (m (a,(b,s)) -> m [(a,(b,s))]) -> StateT (b,s) m a -> StateT (b,s) m [a]
mapsequence f stm = do
s <- get
ases <- lift $ f $ runStateT stm s
case ases of
(_:_) -> do
put ((fst . snd . last) ases,(mconcat . map (snd . snd)) ases)
return $ map fst ases
[] -> return []
Сейчас f
будет, например:
\p -> p `sepBy` semi
Во всяком случае, в последнее время я понял, что вышеприведенная функция неверна, функция будет запускать парсер (инкапсулированный в StateT
) кормить это состояние, которое мы имеем сейчас, который s
затем он запустит его снова, но вместо подачи в новое состояние, полученное в результате первого запуска, он подаст его s
снова и снова и...
Как использовать такие комбинаторы мегапарсек, как sepBy
,sepEndBy
и т. д., чтобы я много раз запускал парсер, но связывал результирующее состояние с первого на второе и третье и т. д.?
2 ответа
Я не знаю, почему я думал, что мне нужна специальная функция, чтобы сделать это, sepBy
и другие определены на Alternative
и потому что каждый StateT
имеет Alternative
функции экземпляра, такие как sepBy
,many
и т. д. можно вызвать напрямую.
Моя проблема, вероятно, заключалась в том, что я должен был использовать symbol
,char
и т.д., которые я думал ParsecT ...
но потом я понял, что эти функции определены с точки зрения MonadParsec
класс типов, который StateT
снова есть экземпляр, так что мне даже не нужно lift
или же mapStateT
,
Так что все, что я сделал, это изменил сигнатуры функций для работы с MonadParsec
и моя проблема была решена.
Мегапарсек имеет монадный трансформаторный интерфейс ParsecT
:
data ParsecT e s m a
ParsecT e s m a
парсер с пользовательским компонентом данных об ошибкахe
тип потокаs
лежащая в основе монадаm
и тип возвратаa
,
Вы должны быть в состоянии использовать это с чем-то вроде type Parser = ParsecT Dec Text (State (Scope, SymbolTable))
, который добавит функциональность синтаксического анализа в базовый State (Scope, SymbolTable)
монада.