-
Notifications
You must be signed in to change notification settings - Fork 86
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Greedy combinators #513
Comments
I wrote my own combinator sepEndBy' :: Parser a -> Parser sep -> Parser [a]
sepEndBy' p sep = do
x <- try p
xs <- many (try (sep >> p))
pure (x : xs) and it seems to work, but not sure if this is an optimal way |
Can you show |
That explanation makes sense, thanks for your response. How could I make it commit?
declaration :: ModuleName -> Parser (Declaration Frontend)
declaration = liftA2 (<|>) defDec letDec
defDec :: ModuleName -> Parser (Declaration Frontend)
defDec modName = do
symbol "def"
name <- NVarName <$> lexeme varName
symbol ":"
ty <- type'
let annotation = TypeAnnotation name ty
let declBody = ValueTypeDef (Just annotation)
pure (Declaration modName name declBody)
letDec :: ModuleName -> Parser (Declaration Frontend)
letDec modName = do
(name, patterns, e) <- L.nonIndented sc letRaw
let value = Value e patterns Nothing
pure (Declaration modName (NVarName name) value)
letRaw :: Parser (MaybeQualified VarName, [Frontend.Pattern], Frontend.Expr)
letRaw = do
((name, patterns), e) <- optionallyIndented letPreamble element
pure (name, patterns, e)
where
letPreamble = do
symbol "let"
name <- lexeme varName
patterns <- sepBy (lexeme pattern') sc
symbol "="
pure (name, patterns) To allow the syntax |
@knightzmc Check out the However, I do wonder whether another package is even necessary. Could |
@mitchellwrosen I had a look at that package, seems to solve my problem! But I agree that there should be an easier way of doing this which doesn't require external libraries (and a lot of boilerplate converting to and from |
From what I see in your code it should work as it is, but it is still incomplete, so I cannot be sure. @knightzmc Can you provide a repository with complete source code and an example input? I could then give it a try and it would perhaps be clearer what is going on there. |
I'm having a similar issue. I'd like to parse either a list of key-value pairs (separated by
Here is a very minimal, simplified grammar. It doesn't support white spaces and both keys and values can only be identifiers. But it's enough to show the issue. type KeyValue = (String, String)
data Val = KeyValList [KeyValue] | Val String deriving Show
ident :: Parser String
ident = some letterChar
keyVal :: Parser KeyValue
keyVal = do
k <- ident
":"
v <- ident
pure (k, v)
prog :: Parser Val
prog = try (KeyValList <$> keyVal `sepEndBy1` ",") <|> (Val <$> ident) This thing handles correctly the two examples I showed above, and reports the correct error for invalid inputs like However the error it reports for an input like
When the input is Is there any way to get Megaparsec to report the error I wish to see? |
@BlueNebulaDev with your definition of keyVal :: Parser KeyValue
keyVal = do
k <- try (ident <* ":")
v <- ident
pure (k, v) Try this and it should behave as you want in all four cases. Still waiting a complete example from @knightzmc which should be fixable without resorting to any third-party libraries, but I'm happy to be proven wrong. |
Thanks! After following your suggestion, the errors my parser is reporting are much better. I'm not sure I understand why |
|
Hey apologies for the delay. This code is pretty outdated now but if you're still happy to take a look I'd appreciate it! |
This may be an XY problem, but I'm having an issue with
sepEndBy
not being greedy enough, and is hiding errors.For context, I'm parsing a haskell-like language with the following syntax
The code to do this is pretty simple:
Using
module' <* eof
as the "entrypoint" parser.The problem is, if
declaration
fails for some reason, the error thrown doesn't propagate up. Instead,sepEndBy
just returns an empty list, and the parser succeeds. This results in some very opaque error messages. For example, if I omitted the body for thelet
declaration:let main =
I'd expect to see an error saying something akin to
Unexpected end of input, expecting expression
. Instead, themodule'
succeeds with an empty list of declarations, and theeof
causes an unintuitive and vague error message:(I'm not actually sure why it says this and not something like
Unexpected let ..., expecting eof
, but that's not the main problem here)I have
dbg
'd anddeclaration
throws the expected error, the problem is withsepEndBy
.My question is, is there an alternative to
sepEndBy
that will "greedily" parse the declarations? I still want to allow empty modules sosepEndBy1
won't do, but if alet
is seen it should keep parsing and fail if necessary, rather than backtracking and returning an empty list.Thanks for any help!
The text was updated successfully, but these errors were encountered: