Parsing Haskell:运算符解析器一直使用未定义的而不是输入

Parsing Haskell:运算符解析器一直使用未定义的而不是输入,parsing,haskell,Parsing,Haskell,我在练习写语法分析器。我用它作为参考。我试图通过解析任意长度的算法来增加它,我已经提出了以下AST data HVal = HInteger Integer -- No Support For Floats | HBool Bool | HNull | HString String | HChar Char | HList [HVal] | HObj [(String, HVal)] deriving (Show, Eq, Read) data Op -- Th

我在练习写语法分析器。我用它作为参考。我试图通过解析任意长度的算法来增加它,我已经提出了以下AST

data HVal
  = HInteger Integer -- No Support For Floats
  | HBool Bool
  | HNull
  | HString String
  | HChar Char
  | HList [HVal]
  | HObj [(String, HVal)]
  deriving (Show, Eq, Read)

data Op -- There's only one operator for the sake of brevity at the moment.
  = Add
  deriving (Show, Read)

newtype Parser a = Parser {
 runParser :: String -> Maybe (String, a)
}
以下函数是我实现运算符解析器的尝试

ops :: [Char]
ops = ['+']

isOp :: Char -> Bool
isOp c = elem c ops

spanP :: (Char -> Bool) -> Parser String
spanP f = Parser $ \input -> let (token, rest) = span f input
                              in Just (rest, token)

opLiteral :: Parser String
opLiteral = spanP isOp

sOp :: String -> Op
sOp "+"  = Add
sOp  _   = undefined

parseOp :: Parser Op
parseOp = sOp <$> (charP '"' *> opLiteral <* charP '"')
我不知道错误发生在哪里。我假设这与
sOp
有关,主要是因为其他函数与
parseOp
的其余部分一样,都是
parseString
函数的翻译:

stringLiteral :: Parser String
stringLiteral = spanP (/= '"')  

parseString :: Parser HVal
parseString = HString <$> (charP '"' *> stringLiteral <* charP '"') 

()
的实现是罪魁祸首。在下一次调用
q
时,您没有使用
input'
,而是使用了
input
。因此,您可以将字符串传递给下一个解析器,而无需“吃掉”字符。您可以通过以下方法解决此问题:

instance Applicative Parser where
  pure x = Parser $ \input -> Just (input, x)
  (Parser p) <*> (Parser q) = Parser $ \input -> do
                (input', f) <- p input
                (input'', a) <- q input'
                Just (input'', f a)

嗯,
+
符号没有被解析。你到底传递给解析器什么?我忘了把它加进去!我在编辑中添加了它,但我在GHCI中做了以下操作:
λ>runParser parseOp“\”+\”
您发布的所有代码对我来说都很好;请同时发布
charP
Applicative
实例。@leftaroundabout我添加了它们!
charP :: Char -> Parser Char
charP x = Parser $ f
  where f (y:ys)
          | y == x = Just (ys, x)
          | otherwise = Nothing
        f []  = Nothing

instance Applicative Parser where
  pure x = Parser $ \input -> Just (input, x)
  (Parser p) <*> (Parser q) = Parser $ \input -> do
                (input', f) <- p input
                (input', a) <- q input
                Just (input', f a)
instance Applicative Parser where
  pure x = Parser $ \input -> Just (input, x)
  (Parser p) <*> (Parser q) = Parser $ \input -> do
                (input', f) <- p input
                (input'', a) <- q input'
                Just (input'', f a)
*Main> runParser parseOp "\"+\""
Just ("",Add)