Haskell - 将 State 与 Alternative 结合使用
Haskell - Using State with Alternative
我的数据类型如下所示:
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
的递归调用然后处理以下令牌。但是,这样做意味着替代案例不会从与第一个案例相同的标记开始。
有没有标准的方法来处理这个问题?
根据评论的建议,我改造了我的解析器以利用我的语法是 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
我的数据类型如下所示:
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
的递归调用然后处理以下令牌。但是,这样做意味着替代案例不会从与第一个案例相同的标记开始。
有没有标准的方法来处理这个问题?
根据评论的建议,我改造了我的解析器以利用我的语法是 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