Parsing Haskell中的元组解析器
我一直在尝试学习Haskell中的函数解析,作为练习,我想编写一个简单的元组解析器,使用Parsing Haskell中的元组解析器,parsing,haskell,tuples,Parsing,Haskell,Tuples,我一直在尝试学习Haskell中的函数解析,作为练习,我想编写一个简单的元组解析器,使用Text.parsercompbinators.ReadP中介于和sepBy1之间的函数。本质上,我需要tupleAsIntPair::ReadP(Int,Int),当使用ReadP\u to\u S进行解析时,它接受一个字符串,例如“(3,4)”,并返回一对整数(3,4),该整数被装箱在ReadS中。目前我有: import Text.ParserCombinators.ReadP isNumericOr
Text.parsercompbinators.ReadP
中介于和sepBy1
之间的函数。本质上,我需要tupleAsIntPair::ReadP(Int,Int)
,当使用ReadP\u to\u S
进行解析时,它接受一个字符串,例如“(3,4)”
,并返回一对整数(3,4)
,该整数被装箱在ReadS
中。目前我有:
import Text.ParserCombinators.ReadP
isNumericOrSep :: Char -> Bool
isNumericOrSep = flip elem $ "0123456789-, "
tuplify2 :: [Int] -> (Int, Int)
tuplify2 [x,y] = (x,y)
tupleAsIntPair :: ReadP (Int, Int)
tupleAsIntPair = fmap tuplify2 parsedList
where parsedList = fmap (map read) $ sepBy1 noparens sep
noparens = between open close $ many1 (satisfy isNumericOrSep)
open = char '('
close = char ')'
sep = char ','
但是,当我尝试运行(readP_to_S tupleAsIntPair)“(3,4)”
时,我得到一个无解析错误。另一方面,如果我全局定义noparens
并运行(readP_to_S noparens)”(3,4)”
,我会得到[((“3,4”),如果我运行(readP_to_$sepBy1(many1$said isNumericOrSep)sep)“3,4”
,我会得到一个[([(“3“,”,“,”,“,”,“,“,”,“,“,”,“,“,”,“,”,“,”,“,”,“,”,“,”,“,”,“,”,“,”,”,“,”,“,”,“,”,”,“,”,“,“,”,”,“,“,”,”,“,所以至少解析器sepBy1
正在做一些事情,尽管我只需要第三次解析
我认为我在
和
sepBy1
之间编写了两个解析器,这是错误的,或者可能是sepBy1
没有做我认为应该做的事情。我实际上如何实现这个元组解析器?我也希望得到任何风格上的建议(例如,tuplify2
让我有点烦)。第一个问题是你对isNumericOrSep
的定义。您正在定义的列表包含作为元素的,
。这意味着isNumericOrSep
将解析用作分隔符的,
,因此parsedList
将由于缺少sep
而失败
isNumericOrSep :: Char -> Bool
isNumericOrSep = flip elem $ "0123456789- "
那么,您不想定义isNumeric
?为什么在此定义中需要分隔符
第二个问题是组合子的顺序。您的描述在两个noparens
之间解析sep
,其中noparens
定义为一个左括号、多个(但至少一个)数值和一个右括号的组合。所以,我想你真正想要的是在开始括号和结束括号之间解析一个元组
tupleAsIntPair :: ReadP (Int,Int)
tupleAsIntPair = fmap tuplify2 parsedList
where
parsedList = fmap (map read) $ between open close $ sepBy1 noparens sep
noparens = many1 (satisfy isNumericOrSep)
open = char '('
close = char ')'
sep = char ','
这将产生以下结果:
*Main> (readP_to_S tupleAsIntPair) "(3,4)"
[((3,4),"")]
我可能误解了你的目标。但是在你的介绍中,我读到你想要解析一个元组,但也许你想要解析许多元组
编辑:
不首先解析括号。请看一下以下各项的定义:
between::ReadP open->ReadP close->ReadP a->ReadP a
--^@在打开-关闭p@之间解析@open@,后面跟着@p@最后
-- @close@. 只返回@p@的值。
开闭之间p=do u非常感谢您的帮助;这正是我想要的。检查一下,代码首先删除括号,然后解析逗号列表,对吗?那么我应该考虑从左到右组合解析器吗?对第二个问题是的,当你组合解析器时,从左到右组合更自然。对于第二个答案,我将编辑我的答案。
between :: ReadP open -> ReadP close -> ReadP a -> ReadP a
-- ^ @between open close p@ parses @open@, followed by @p@ and finally
-- @close@. Only the value of @p@ is returned.
between open close p = do _ <- open
x <- p
_ <- close
return x