我正在为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)))
这是提供的 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 else解析器的“ if”切换为“ \” then else,而if then else解析器立即中断。 另外,我至少希望收到一条错误消息,所以我添加了
lambda = (do ...... ) <|> return (Var "lambdaError")
在 mainParser 中的lambda块的末尾,但是我仍然没有得到Just(Var“ lambdaError”)。 如何解析“ \”?或者至少如何测试这里的问题?
答案 0 :(得分:3)
我找到问题的NVM
operator "\\"
实际上可以,但是
keyword "->"
不是因为关键字仅解析字母,所以这就是为什么我在使用运算符“ \”时得到什么都没有的原因。因此,我将使用运算符“ \”并为“->”编写一个解析器
最终成功了:
lambda = do
operator "\\"
va <- var
char '-'
operator ">"
blk <- block
return (Lambda va blk)