Closed s5bug closed 4 years ago
Hey!
Several parser combinator libraries define a function called sepBy
, which might be close what you're after. Perhaps it would help to have a look at what they do, e.g. https://www.stackage.org/haddock/lts-14.20/parser-combinators-1.1.0/src/Control.Applicative.Combinators.html#sepBy. Note that you have to use rule
in Earley to create recursive parsers.
Your approach might work as well. If you e.g. want to parse qualified names, you could first parse a list of allowed characters including '.'
using Earley, and then split it outside of Earley (e.g. using splitOn "." <$> ...
as in your example).
Hope this helps!
The sepBy
you linked isn't recursive, but copying it to Earley doesn't actually split and just outputs "abc.def.ghi"
instead of ["abc", "def", "ghi"]
.
sepBy :: Alternative m => m a -> m sep -> m [a]
sepBy p sep = sepBy1 p sep <|> pure []
sepBy1 :: Alternative m => m a -> m sep -> m [a]
sepBy1 p sep = liftA2 (:) p (many (sep *> p))
dparse :: (String -> Bool) -> Prod r String String [String]
dparse f = sepBy (satisfy f) (token ".")
Maybe you meant for your parser to work on Char
s as tokens instead of String
s? Otherwise you need to tokenise first.
Probably? Right now I'm trying to get it to parse
arti abc.def.ghi
pack jkl.mno
into
Prog
(Arti
(Domain ["abc", "def", "ghi"])
)
(Pack
(Domain ["jkl", "mno"])
)
So what you're saying is I shouldn't feed words
into the parser and make it work on Char
?
Yeah, I got it to work with Char
:
sepBy :: Alternative m => m a -> m sep -> m [a]
sepBy p sep = sepBy1 p sep <|> pure []
sepBy1 :: Alternative m => m a -> m sep -> m [a]
sepBy1 p sep = liftA2 (:) p (many (sep *> p))
someBy :: Eq a => a -> Prod r e a [[a]]
someBy s = sepBy (some $ satisfy $ (/=) s) (token s)
I just have to properly handle whitespace now. Thank you!
I'm a very novice Haskell programmer and I wanted to write something with parsers. My current solution for parsing
abc.def.ghi
uses thesplit
package like so:I feel like, from my Scala+cats knowledge, that this is a very poor way to do this. How should I properly implement it?