首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >简单Haskell Parser

简单Haskell Parser
EN

Code Review用户
提问于 2020-12-15 09:26:51
回答 1查看 1K关注 0票数 2

一般来说,我对haskell (我从不使用Monad、函子和其他东西)和FP非常陌生。我决定用一些扩展的可能性来编写最简单的解析器。(我对编程语言有普遍的兴趣,所以这就是我选择这样做的原因.)。

我有一个简单的解析器类型:

代码语言:javascript
复制
type Parser a = String -> (Maybe a, String)
-- (Nothing, ErrorMessage)
-- (Just a, Leftovers)

如果没有任何字符,我可以解析任何字符并返回错误:

代码语言:javascript
复制
eatParser :: Parser Char
eatParser []     = (Nothing, "Unexpected EOF")
eatParser (x:xs) = (Just x, xs)

我可以解析一个特定的字符:

代码语言:javascript
复制
charParser :: Char -> Parser Char
charParser c s = case eatParser s of
    (Nothing, e) -> (Nothing, e)
    (Just x, xs) | x == c -> (Just x, xs)
    (Just x, _) | x /= c ->
        (Nothing,
        "Expected " ++ [c] ++ ", but got " ++ [x] ++ " instead.")

另外,一个特定的字符串:

代码语言:javascript
复制
stringParser :: String -> Parser String
stringParser [] s = (Just "", s)
stringParser u s = case charParser (head u) s of
    (Nothing, e) -> (Nothing, e)
    (Just x, xs) -> case stringParser (tail u) xs of
        (Nothing, e) -> (Nothing, e)
        (Just x', xs') -> (Just $ x : x', xs')

任何一个词:

代码语言:javascript
复制
varParser :: Parser String
varParser s = case eatParser s of
    (Nothing, _) -> (Just [], [])
    (Just x, xs) | not $ isLetter x -> (Just [], xs)
    (Just x, xs) | isLetter x ->
        case varParser xs of
            (Nothing, e') -> (Nothing, e')
            (Just [], _) -> (Just [x], xs)
            (Just x', xs') ->
                (Just $ x : x', xs')

最后,表达式解析器

代码语言:javascript
复制
data Expr = Open Expr | Value String deriving (Show)
exprParser :: Parser Expr
exprParser s = case charParser '(' s of
    (Nothing, _) -> case varParser s of
        (Nothing, e) -> (Nothing, e)
        (Just x, xs) -> (Just $ Value x, xs)
    (Just _, xs) -> case exprParser xs of
        (Nothing, e)  -> (Nothing, e)
        (Just q, xs') -> case charParser ')' xs' of
            (Nothing, e)   -> (Nothing, e)
            (Just _, xs'') -> (Just $ Open q, xs'')

下面是代码的一些示例:

代码语言:javascript
复制
*Test2> eatParser "abc"
(Just 'a',"bc")
*Test2> charParser 'a' "abc"
(Just 'a',"bc")
*Test2> charParser 'b' "abc"
(Nothing,"Expected b, but got a instead.")
*Test2> stringParser "abc" "abce"
(Just "abc","e")
*Test2> stringParser "abc" "abc"
(Just "abc","")
*Test2> stringParser "abc" "axbc"
(Nothing,"Expected b, but got x instead.")
*Test2> varParser "abc"
(Just "abc","")
*Test2> varParser "abc2"
(Just "abc","2")
*Test2> varParser "abc abc2"
(Just "abc"," abc2")
*Test2> exprParser "((aa))bc"
(Just (Open (Open (Value "aa"))),"bc")
*Test2> exprParser "((aa)b)bc)"
(Nothing,"Expected ), but got b instead.")

我知道有一个方法可以简化所有的case ... s of (Nothing, e) -> (Nothing, e) (Just x, xs) -> ...

不使用parserSequence..。

你能告诉我能改进什么吗?预先感谢:D

EN

回答 1

Code Review用户

回答已采纳

发布于 2020-12-16 20:44:11

票数 2
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/253497

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档