在Haskell赋值中为实现语言实现解析器时,无法解析'\'

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了在Haskell赋值中为实现语言实现解析器时,无法解析'\'相关的知识,希望对你有一定的参考价值。

我正在为EBNF提供的语言编写解析器。一切顺利,我成功地解析了“if”“then”“else”,“let”“in”和infix就像1 + 2.但是当我使用相同的方法“\”时,“Nothing”被返回并且我只是不知道为什么。 EBNF描述了这样的lambda:

block ::= cond | lambda | let | infix
lambda ::= "\" var "->" block
var is a letter followed by 0 or more letters. I tested my var parser, it works

测试设置如下:

newtype Parser a = PsrOf (String -> Maybe (String, a))
runParser :: Parser a -> String -> Maybe a
runParser (PsrOf p) inp = case p inp of
                            Nothing -> Nothing
                            Just (_, a) -> Just a
parse = runParser mainParser
testHandout =
    "handout" ~: parse inp
    ~?= (Just (Lambda "y" (Num 3)))

这是提供的Expr数据类型:

data Expr
    = Num Integer
    | Var String
    | Prim2 Op2 Expr Expr       -- Prim2 op operand operand
    | Let [(String, Expr)] Expr -- Let [(name, rhs), ...] body
    | Lambda String Expr        -- Lambda var body
    | App Expr Expr             -- App func arg
    | Cond Expr Expr Expr       -- Cond test then-branch else-branch
    deriving (Eq, Show)

data Op2 = Eq | Lt | Plus | Minus | Mul | Div | Mod
    deriving (Eq, Show)

我的工作是编写mainParser。以下代码是与此问题相关的部分(所有代码编译时没有错误或警告)

mainParser :: Parser Expr
mainParser = whitespaces *> block <* eof
  where
    block = cond <|> lambda <|> letin <|> infixx <|> return (Var "Error")
    lambda = do
        char '\\' *> whitespaces
        va <- var
        keyword "->"
        blk <- block
        return (Lambda va blk)
...more code unrelated to question

为线

char '\\' *> whitespaces

我试过了

operator "\\"

keyword "\\"

string "\\" *> whitespaces

他们没有工作,我每次都没有结果。仅供参考,我给出的解析器库与此问题相关:

char :: Char -> Parser Char
char wanted = satisfy (\c -> c == wanted)

satisfy :: (Char -> Bool) -> Parser Char
satisfy pred = PsrOf p
  where
    p (c:cs) | pred c = Just (cs, c)
    p _ = Nothing

string :: String -> Parser String
string wanted = PsrOf p
  where
    p inp = case stripPrefix wanted inp of
              Nothing -> Nothing
              Just suffix -> Just (suffix, wanted)

keyword :: String -> Parser String
keyword wanted = do
    c <- satisfy isAlpha
    cs <- many (satisfy isAlphaNum)
    whitespaces
    if c:cs == wanted then return wanted else empty

-- | Read something that looks like an operator, then skip trailing spaces.
anyOperator = some (satisfy symChar) <* whitespaces
  where
    symChar c = c `elem` "=/<>&|+-*%\\"

-- | Read the wanted operator, then skip trailing spaces.
operator wanted = do
    sym <- anyOperator
    if sym == wanted then return wanted else empty

我的测试用例:

"\\y->3"

预期结果:

(Just (Lambda "y" (Num 3)))

实际结果:

Nothing

我知道这是“\”的问题,因为我在我的工作中切换了“if”,然后将其他解析器切换为“\”,然后if和then then解析器立即断开。此外,我想至少尝试收到错误消息,所以我添加了

 lambda = (do ...... ) <|> return (Var "lambdaError")

在mainParser中的lambda块的末尾,但是我仍然得到Nothing,而不是Just(Var“lambdaError”)。如何解析'\'?或者至少如何测试这里的问题是什么?

答案

NVM我发现了这个问题

operator "\\"

实际上工作但是

keyword "->"

不是因为关键字只解析字母,这就是为什么我在使用运算符“\”时得到Nothing。所以我将使用运算符“\”并为“ - >”编写一个解析器

这最终奏效了:

    lambda = do
        operator "\\"
        va <- var
        char '-'
        operator ">"
        blk <- block
        return (Lambda va blk)

以上是关于在Haskell赋值中为实现语言实现解析器时,无法解析'\'的主要内容,如果未能解决你的问题,请参考以下文章

了解Haskell中已实现的递归下降解析器

在 Haskell 中使用 Alex 制作解析骰子卷的词法分析器

Haskell 函数可以序列化吗?

当我调用位置管理器时无法解析方法“requestLocationUpdates”

C++模版编程实现Haskell的函数模式匹配特性

HaskellHaskell中的条件编译