Search code examples
haskellstatemonad-transformersmegaparsec

how to use megaparsec's combinators on StateT


I'm building a compiler for java for university project, in my project my parsers are mostly StateT (Scope,SymbolTable) String m a where Scope is the scope we're at now(method,class,etc) and SymbolTable holds the symbols defined till now.

I wanted to use megaparsec's combinators on those parsers, for parens,braces it's not problem, I just use mapStateT but for sepBy and others I developed this function :

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 []

Now f would be for example :

\p -> p `sepBy` semi

Anyway I realized lately that the function above is wrong, the function will run the parser(encapsulated in StateT) feeding it the state we have right now which is s then it will run it again but instead of feeding it the new state resulting from the first run it will feed it s again and again and ... .

How do I use megaparsec's combinators like sepBy,sepEndBy and etc so that I run the parser many times but chaining the resulting state from the first to the second to the third etc ?


Solution

  • I don't know why I thought that I needed a special function to do this, sepBy and others are defined on Alternative and because every StateT has an Alternative instance functions like sepBy,many, etc can be called directly.

    My problem probably was because I had to use symbol,char,etc which I thought are ParsecT ... but then I realized those functions are defined in terms of MonadParsec typeclass which StateT again has instance for so I didn't even need lift or mapStateT.

    So all I did is to change functions signatures to work with MonadParsec and my problem was solved.