2 ms·
> I would have to encode the position by hand ... or manually pass position context through. You're having a /r/restofthefuckingowl moment, and I understand th
by mrkeen 3y ago
> I would have to encode the position by hand ... or manually pass position context through.
You're having a /r/restofthefuckingowl moment, and I understand the reaction, but calm down :D
There is a little wiggle-room for error, down at the 'unit' level. Here's a parser (based on the above Parser type) which consumes input as long as its predicate matches:
parseWhile :: (Char -> Bool) -> Parser String
parseWhile pred = P $ \s -> do
let some = takeWhile pred s
rest = dropWhile pred s
Just (some, rest)
It's verbose, and maybe there's a bug in it? (Side note: it also needs to step through s twice, so it's dumb). Here's a more compact version without the 2 * work:
parseWhile' :: (Char -> Bool) -> Parser String
parseWhile' pred = P $ Just . span pred
No type-systemy category-theoretical nonsense will stop me from getting a boolean the wrong way around. Maybe I accidentally implemented skipWhile or parseUntil without realising.
So what's the point?
* You build bigger parts out of smaller parts *
Here's the actual parser for my if-then-else expression in my language:
parseIfThenElse :: Parser ParseState (Expr Untyped ByteString)
parseIfThenElse = do
p <- token TIf *> parseExpr
t <- token TThen *> parseExpr
f <- token TElse *> parseExpr
pure $ IfThenElse Untyped p t f
No manual plumbing or passing in the above code. What about one step up? Here's code which calls the above:
parseNonApply :: Parser ParseState (Expr Untyped ByteString)
parseNonApply = parseLet
<|> parseIfThenElse
<|> parseLambda
<|> parseTerm
<|> parseNegated
<|> parseShown
<|> parseErr
<|> parseParen