Search code examples
parsinghaskellghcghcihaskell-src-exts

Haskell Src Exts Parsing Multiple Statements


I would like to parse a list of Haskell statements. For instance, suppose I have the following code:

let a = b
    c = e
out <- return 3

I'd like a function, for instance parseStmts, which can return this in some parsed format.

I've looked into haskell-src-exts and saw parseStmt. This works for a single statement. It has type parseStmt :: String -> ParseResult Stmt, and if you try parseStmt "let a = 3", the result is a successful ParseOk. However, if you provide multiple statements, this function complains because there is more than one statement in the string.

How do I parse multiple statements, without wrapping them in a do block? Alternatively, how can I find the places in a string which are separations of Haskell statements, so I can separate them and then use parseStmt from haskell-src-exts?

Thanks!


Solution

  • You're looking for parseExp, although the output is a bit large:

    > :m + Language.Haskell.Exts.Parser
    > parseExp "do\n  let a = b\n      c = e\n  out <- return 3\n  return $ a + c + out"
    ParseOk (Do [LetStmt (BDecls [PatBind (SrcLoc {srcFilename = "<unknown>.hs", srcLine = 2, srcColumn = 7}) (PVar (Ident "a")) Nothing (UnGuardedRhs (Var (UnQual (Ident "b")))) (BDecls []),PatBind (SrcLoc {srcFilename = "<unknown>.hs", srcLine = 3, srcColumn = 7}) (PVar (Ident "c")) Nothing (UnGuardedRhs (Var (UnQual (Ident "e")))) (BDecls [])]),Generator (SrcLoc {srcFilename = "<unknown>.hs", srcLine = 4, srcColumn = 3}) (PVar (Ident "out")) (App (Var (UnQual (Ident "return"))) (Lit (Int 3))),Qualifier (InfixApp (Var (UnQual (Ident "return"))) (QVarOp (UnQual (Symbol "$"))) (InfixApp (InfixApp (Var (UnQual (Ident "a"))) (QVarOp (UnQual (Symbol "+"))) (Var (UnQual (Ident "c")))) (QVarOp (UnQual (Symbol "+"))) (Var (UnQual (Ident "out")))))])
    

    I had to add the return $ a + c + out to the end or else it throws an error, since it wouldn't be considered a valid do block otherwise.