Вы всё ещё не слушаете http://bananasandlenses.net/ ? Вот лалки. // Серьёзно, отличный подкаст, рекомендую.
Пишу опердень на attoparsec. Т.к. парсер у нас одновременно и лексер, и собственно парсер, логику приходится перемежать обработкой пробельных символов:
pVarDecl :: Parser VariableDeclaration
pVarDecl = do
string "var"
skipWhitespace1 -- пропускаем 1 или больше пробельных символов
name <- pVarName
skipWhitespace -- пропускаем 0 или больше пробельных символов
value <- optional $ do
string "="
skipWhitespace
pExpression
skipWhitespace
string ";"
return $ VariableDeclaration name value
Это утомляет. Появляется закономерное желание «переопределить точку с запятой» и явно указывать только места, где пробельные символы обязательны:
pVarDecl :: Parser VariableDeclaration
pVarDecl = do
string "var"
requiredWhitespace
name <- pVarName
value <- optional $ do
string "="
pExpression
string ";"
return $ VariableDeclaration name value
(и потом ещё для полного счастья keyword k = string k >> requiredWhitespace
, да).
Удивительно, но сам attoparsec, похоже, ничего для этого не предлагает. Итак, какие у меня варианты?
Можно определить свою монаду. Это, конечно, круто, но придётся лифтить часть Data.Attoparsec. В принципе, это всё же лучше, чем ещё двести раз набрать «skipWhitespace», но все равно грязновато.
Есть ощущение, что можно обернуть парсер в трансформер, для которого определить инстанс Monad, и будет мне счастье. Но я трансформерами никогда не пользовался даже, не говоря уж о написании собственных; возможно, это бред, а не идея.
Есть у вас какие-то соображения на этот счёт?