Haskell - 使用状态与替代

时间:2018-04-03 09:04:40

标签: parsing haskell applicative state-monad

我的数据类型如下所示:

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 个答案:

答案 0 :(得分:0)

根据评论的建议,我改造了我的解析器以利用我的语法是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