0

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 ?

Cactus
  • 27,075
  • 9
  • 69
  • 149
niceman
  • 2,653
  • 29
  • 57
  • 1
    This looks wrong. `runState` should get you `((b, s), a)`, not `[a]`, so that you could `put` that state. – Bartek Banachewicz May 29 '17 at 15:43
  • @BartekBanachewicz the state is `(b,s)` so `runState` would return `(a,(b,s))`, I run the function `f` on the result to get `[((b,s),a)]` – niceman May 29 '17 at 15:49
  • 1
    So there's your problem. You're left with multiple states. Which one should you pick now? – Bartek Banachewicz May 29 '17 at 15:53
  • @BartekBanachewicz exactly, that's my problem, I have to parse statements which include variable declaration statements, when `int x=3;` occurs `x` should be added to the symboltable but those statements are seperated by a semi colon, that's why I'm asking – niceman May 29 '17 at 15:56

2 Answers2

0

Megaparsec has a monad transformer interface ParsecT:

data ParsecT e s m a

ParsecT e s m a is a parser with custom data component of error e, stream type s, underlying monad m and return type a.

You should be able to use this with something like type Parser = ParsecT Dec Text (State (Scope, SymbolTable)), which will add parsing functionality to the underlying State (Scope, SymbolTable) monad.

Community
  • 1
  • 1
Cactus
  • 27,075
  • 9
  • 69
  • 149
  • all my parsers are `StateT (Scope,SymbolTable) String (ParsecT ...) a` here, I've got a lot of them I can't change them easily , anyway I found the solution and I'm going to post it – niceman May 30 '17 at 09:07
0

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.

niceman
  • 2,653
  • 29
  • 57