Это взлом, но я думаю, что он делает то, что вы хотите:
list = (:[])
text = many (try em <|> (anyChar >>= return . list))
>>= return . ("<p>"++) . (++"</p>") . concat
(каждый неотмеченный символ возвращается в виде своей собственной строки.)
Вот как это работает:
На каждом символе сначала попробуйте разобрать em
. Это начинается с двух тире. Поскольку em
может потерпеть неудачу после использования одного тире, как в «a-b», вам необходимо поставить перед ним префикс try
. Если в остальной части ввода не разрешены тире, попытка не требуется, но, вероятно, это не так. В противном случае, потреблять anyChar. Но это тип Char
, а не String
, поэтому его необходимо заключить в список.
Возвращает список односимвольных строк с чередованием выделенных разделов. Но вы хотите, чтобы одна строка была окружена тегами p
, поэтому сначала вы должны concat
, а затем добавить начало / конец тега в начало / конец. Затем вы возвращаете это значение.
Вероятно, есть способ переписать весь этот синтаксический анализатор, чтобы вместо anyChar вы использовали ввод, пока не увидите две черты. Но я не уверен, как написать это на моей голове, так что вместо этого вы получите этот хак, который, вероятно, гораздо менее эффективен.