"Write Yourself a Scheme in 48 Hours/Parsing" の後半を読む

Recursive Parsers: Adding lists, dotted lists, and quoted datums

ということで、"Parsing"の章の前半では、AtomやStringなどのパースをやったが、
後半ではリストなど繰り返しのある構文のパースをする。ここではsepByという関数がでてくる。
http://legacy.cs.uu.nl/daan/download/parsec/parsec.html#sepBy
型は、
sepBy :: GenParser tok st a -> GenParser tok st sep -> GenParser tok st [a]
で、(sepBy p sep)としたとき、p やp >> sep >> p や p >> sep >> p >> sep >> p のような形にマッチして、
各pのパース結果をリストにしたものが結果になるようなパーサが得られる。ソースはこんな感じでした。

sepBy1,sepBy :: GenParser tok st a -> GenParser tok st sep -> GenParser tok st [a]
sepBy p sep         = sepBy1 p sep <|> return []
sepBy1 p sep        = do{ x <- p
                        ; xs <- many (sep >> p)
                        ; return (x:xs)
                        }

ふんふん、勉強になります。
試してみると、

Main> parse (sepBy parser spaces1) "" "abc"
Right [Atom "abc"]
Main> parse (sepBy parser spaces1) "" " abc"
Right []
Main> parse (sepBy parser spaces1) "" "abc c"
Right [Atom "abc",Atom "c"]
Main> parse (sepBy parser spaces1) "" "abc "
Left (line 1, column 5):
unexpected end of input
expecting space, letter, digit or "\""
Main> parse (sepBy parser spaces1) "" "abc de fg"
Right [Atom "abc",Atom "de",Atom "fg"]

こんな感じ。