Parsec --- 2.5 Sequences and separators (3)
sepBy1を使うことで「英語の文」を単語のリストに分解するパーサをsentenceを作ります.
word:: Parser String word = many1 (letter <|> digit) sentence:: Parser [String] sentence = do words <- sepBy1 word separator oneOf ".?!" return words separator:: Parser () separator = skipMany1 (space <|> oneOf ",:;'\"")
wordはアルファベットだけでなく数字も許容し,単語間の区切りはカンマ以外のものも,引用符やコロン,セミコロンも許容させています.
ただ,これでは英語の文はパースしきれません.I said "Hello! I'm Taro."みたいな文だと,最後の " がパースされないで残ってしまいます.
そこで,もうちょっと工夫してみます.
word:: Parser String word = many1 (letter <|> digit) sentence:: Parser [String] sentence = do many separator words <- sepBy1 word separator oneOf ".?!" >> many (oneOf "'\"") eof return words separator:: Parser () separator = skipMany1 (space <|> oneOf ",:;?!'\"")
単語区切りに,?!を追加して,さらに引用で文が終わるケースも含め,さらに全部の処理が終わってるかをチェックするようにしています.ついでに冒頭に区切りがあっても無視するようにしました.
けど,まだだめで,「引用文中に複数の文があるケース」は対処できてません.バックトラックが必要なのかもしれませんが,そもそも自然言語を相手にしてるのできりがないので,この辺であきらめます。。。
*Main> parseTest sentence "\"Hello, I am Hippo 2007!,\" he said suddenly." ["Hello","I","am","Hippo","2007","he","said","suddenly"]