"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"]
こんな感じ。