Вам нужно реструктурировать свой парсер. Вы используете комбинаторы в очень странных местах, и они все портят.
A var
- это varName
между "[[" и "]]". Итак, напишите, что:
var = between (string "[[") (string "]]") varName
A varName
должен иметь какой-то формат (я не думаю, что вы хотите принять "% A¤% &", не так ли?), Поэтому вы должны сделать для этого парсер; но в случае, если это действительно может быть что угодно, просто сделайте это:
varName = many $ noneOf "]"
Тогда текст, содержащий переменные, представляет собой нечто с переменными, разделенными не переменными.
varText = someText *> var `sepEndBy` someText
... где someText
- это что угодно, кроме '[':
someText = many $ noneOf "["
Вещи усложняются, если вы хотите, чтобы это было разбираемо:
bla bla [ bla bla [[somevar]blabla]]
Тогда вам нужен лучший парсер для varName
и someText
:
varName = concat <$> many (try incompleteTerminator <|> many1 (noneOf "]"))
-- Parses e.g. "]a"
incompleteTerminator = (\ a b -> [a, b]) <$> char ']' <*> noneOf "]"
someText = concat <$> many (try incompleteInitiator <|> many1 (noneOf "["))
-- Parses e.g. "[b"
incompleteInitiator = (\ a b -> [a, b]) <$> char '[' <*> noneOf "["
PS . (<*>)
, (*>)
и (<$>)
от Control.Applicative
.