在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 中使用 Alex 制作解析骰子卷的词法分析器