Haskell - Использование State с Альтернативой

У меня есть тип данных, который выглядит следующим образом:

type Parser a = ExceptT ParseError (State [Token]) a

А также функции манипулирования состоянием:

consumeToken :: Parser Token
consumeToken = do
    toks <- lift get
    if null toks 
        then throwE OutOfTokensError
        else 
            do
                lift $ put (tail toks)
                return $ head toks

peekToken :: Parser Token
peekToken = do
    toks <- lift get
    if null toks 
        then throwE OutOfTokensError
        else 
            do
                return $ head toks

Я пытаюсь использовать эти функции, чтобы помочь проверить правила производства в грамматике:

charList :: Parser CharList
charList =
    (return CharListCharacter <*> isToken (Character "<char>") <*> charList)
    <|> (return CharListSpace <*> isToken (Space " ") <*> charList)
    <|> (return EmptyCharList)

Кажется, что isToken необходимо использовать текущий токен (используя consumeToken) так что рекурсивные вызовы charList тогда разберитесь со следующим токеном. Однако это означает, что альтернативные варианты не будут начинаться с того же токена, что и первый вариант.

Есть ли стандартный способ решения этой проблемы?

1 ответ

Решение

Следуя совету из комментариев, я переделал свой синтаксический анализатор, чтобы использовать тот факт, что моя грамматика - LL(1). Это означало, что мне не нужно Alternative,

Это финальная версия charList функция (с isToken с помощью consumeToken):

charList :: Parser CharList
charList = do
    tok <- peekToken
    case tok of Character _ -> return CharListCharacter <*> isToken (Character "<char>") <*> charList
                Space _     -> return CharListSpace <*> isToken (Space " ") <*> charList
                _           -> return EmptyCharList
Другие вопросы по тегам