解析问题'\\';在Haskell赋值中为合成语言实现解析器时
我正在为EBNF提供的语言编写解析器。一切都进行得很顺利,我成功地解析了“if”“then”“else”、“Let”“in”和中缀,比如1+2。但是当我对“\”使用相同的方法时,会返回“Nothing”,我只是不知道为什么。EBNF对lambda的描述如下:解析问题'\\';在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
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)