如何解决Haskell lexer输入和返回令牌或错误列表
您好,我正在研究lexer接受输入字符串并返回令牌列表或错误的问题。如果有人知道如何解决问题,请提供帮助。谢谢:)
lexer :: String -> Either Error [Token]
我不使用任何一种都无法工作,但是无法使用Haskell的任何一种功能。我想让左边给出一个错误,而右边则想生成带有多个条件匹配的令牌列表。
这是无效的代码:
lexar (x:xs)
| isSpace x = Main.lexar xs
| isDigit x = Right (Literal (show x): Main.lexar xs)
| x == '+' = Right (Plus : Main.lexar xs)
| x == '-' = Right (Minus : Main.lexar xs)
| x == '*' = Right (Mult : Main.lexar xs)
| x == '/' = Right (Div : Main.lexar xs)
| x == '(' = Right (LeftP : Main.lexar xs)
| x == ')' = Right (RightP : Main.lexar xs)
| otherwise = Left (error "fail")
解决方法
首先,您不能使用返回值为:
的{{1}}运算符。
此版本的lexar
返回一个lexar
,它不是列表,因此不能作为运算符Either
的第二个参数。
每次您递归调用:
时,它都会返回一个lexar
,它可以是Either
或Left
。如果它是Right
,则包含错误,您只需将其向上传递。如果它是Left
,则它包含下游词法分析的结果,您可以在当前标记之前加上它,然后在返回之前再次将其包装在Right
中。让我们写下来:
Right
当然,如果您必须为每个单个标记编写一个完整的 | isDigit x =
case lexar xs of
Left err -> Left err
Right tokens -> Right (Literal (show x) : tokens)
表达式,这将变得非常繁琐。因此,您可以将其包装在辅助函数中:
case
如果您对更多抽象的概念很满意,还可以通过使用运算符lexar (x:xs)
...
| isDigit x = prependToken (Literal (show x))
| x == '+' = prependToken Plus
...
where
prependToken t =
case lexar xs of
Left err -> Left err
Right tokens -> Right (t : tokens)
来利用Functor
的{{1}}实例:
Either
用于<$>
的运算符lexar (x:xs)
...
| isDigit x = (Literal (show x) :) <$> lexar xs
| x == '+' = (Plus :) <$> lexar xs
...
的标准库实现将给定函数应用于<$>
值或返回Either
值不变。本质上,这正是我的辅助函数Right
正在做的事情。
最后,在返回Left
时,请勿调用prependToken
函数。该函数将在评估结果时使程序崩溃,这不是您想要的结果。只需将字符串包装在Left
中即可:
error
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。