Ваша грамматика является леворекурсивной, что не очень хорошо с try
, поскольку Parsec будет постоянно возвращаться назад Есть несколько способов обойти это. Возможно, самое простое - просто сделать *
необязательным в другом правиле:
lit :: Parser (Char, Maybe Char)
lit = do
c <- noneOf "*"
s <- optionMaybe $ char '*'
return (c, s)
Конечно, в любом случае вы, вероятно, в конечном итоге обернете вещи в тип данных, и есть много способов сделать это. Вот один из моих голов:
import Control.Applicative ((<$>))
data Term = Literal Char
| Sequence [Term]
| Star Term
expr :: Parser Term
expr = Sequence <$> many term
term :: Parser Term
term = do
c <- lit
s <- optionMaybe $ char '*' -- Easily extended for +, ?, etc.
return $ if isNothing s
then Literal c
else Star $ Literal c
Возможно, более опытный Хаскеллер найдет лучшее решение.