解析问题'\\';在Haskell赋值中为合成语言实现解析器时

解析问题'\\';在Haskell赋值中为合成语言实现解析器时,haskell,Haskell,我正在为EBNF提供的语言编写解析器。一切都进行得很顺利,我成功地解析了“if”“then”“else”、“Let”“in”和中缀,比如1+2。但是当我对“\”使用相同的方法时,会返回“Nothing”,我只是不知道为什么。EBNF对lambda的描述如下: block ::= cond | lambda | let | infix lambda ::= "\" var "->" block var is a letter followed by 0 or more letters. I

我正在为EBNF提供的语言编写解析器。一切都进行得很顺利,我成功地解析了“if”“then”“else”、“Let”“in”和中缀,比如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)))
测试设置如下:

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。下面的代码是与此问题相关的部分(所有代码编译时没有错误或警告)

我试过了

operator "\\"

他们中没有人工作过,每次我都一无所获。 FYI,我给出的解析器库与此问题相关:

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
预期结果:

(Just (Lambda "y" (Num 3)))
实际结果:

Nothing
我知道“\”有问题,因为我将正在工作的if-then-else解析器中的“if”切换到了“\”then-else,if-then-else解析器立即崩溃。 我还想至少尝试获取一条错误消息,所以我添加了

 lambda = (do ...... ) <|> return (Var "lambdaError")
lambda=(do…)返回(变量“lambdaError”)
mainParser中lambda块的末尾,我仍然没有得到任何结果,而不是Just(Var“lambdaError”)。
如何解析“\”?或者至少如何测试这里的问题是什么?

NVM我发现了问题

operator "\\"
实际上有效,但是

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

这最终奏效了:

    lambda = do
        operator "\\"
        va <- var
        char '-'
        operator ">"
        blk <- block
        return (Lambda va blk)
lambda=do
运算符“\\”

va尝试将
lambda
放在
block
的第一位,这样类似于
block=lambda cond…
。(我不确定它是否会起作用,但有时这类事情确实起作用。)不,它没有。但我想我可能会意识到问题所在。“->”的解析不正确。是否有人可以将此问题设置为已解决?当我这样做时,我得到以下信息:>您可以在2天内接受自己的答案为什么不使用
运算符“->”
operator "\\"
keyword "->"
    lambda = do
        operator "\\"
        va <- var
        char '-'
        operator ">"
        blk <- block
        return (Lambda va blk)