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 ?
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.