String 如何使用parsec获取字符串中特定模式的子字符串
我是Haskell的新手,现在我正在学习使用parsec。我陷入了一个问题,那就是,我想得到满足字符串中特定模式的所有子字符串。例如,从以下字符串 “我想从F1(a)、F2a、F5-a、F34-5等中选择F12或F12, 但是不应该只选择F,也就是说,选择那些以F开头的 后跟一个数字(数字之前可能有零个或多个空格),然后是['a'…'z']中的任何字符++ ['A'..'Z']++['0'..'9']+++['(',')',“-”] 结果应为[F12、F12、F1(a)、F2a、F5-a、F34-5],其中F和数字之间的空格应删除 使用parsec,我成功地获得了一个子字符串,如F12、F2a。代码如下:String 如何使用parsec获取字符串中特定模式的子字符串,string,parsing,haskell,String,Parsing,Haskell,我是Haskell的新手,现在我正在学习使用parsec。我陷入了一个问题,那就是,我想得到满足字符串中特定模式的所有子字符串。例如,从以下字符串 “我想从F1(a)、F2a、F5-a、F34-5等中选择F12或F12, 但是不应该只选择F,也就是说,选择那些以F开头的 后跟一个数字(数字之前可能有零个或多个空格),然后是['a'…'z']中的任何字符++ ['A'..'Z']++['0'..'9']+++['(',')',“-”] 结果应为[F12、F12、F1(a)、F2a、F5-a、F34
hao :: Parser Char
hao = oneOf "abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ()-"
tuhao :: Parser String
tuhao = do { c <- char 'F'
; many space
; c1 <- digit
; cs <- many hao
; return (c:c1:cs)
}
parse tuhao "" str -- can parse the str and get one sub-string.
hao::解析器字符
hao=其中一个“ABCDEFGHIjklmnopqrstuvxyz1234567890ABCDEFGHIjklmnopqrstuvxyz()-”
tuhao::解析器字符串
tuhao=do{c
F12
,F12
,F1(a)
,F2a
,F5-a
,F34-5
这是一个不完整的描述,所以我会做一些猜测
我将首先定义一个类型,该类型可以包含这些表达式的逻辑部分
newtype F = F (Int, Maybe String) deriving Show
也就是说,“F”后面跟一个数字,可选的部分是字母、括号中的字母或破折号后面跟字母/数字。由于“F”后面的数字可以有多个数字,我假设可选的字母/数字也可以是多个
由于示例有限,我假设以下内容无效:F1a(b)
,F1(a)b
,F1a-5
,F1(a)-a
,F1a(a)-5
,F1a1
,F1-(a)
,等等。以下内容有效:F1a
,F1abc
,F1(abc)
,F1 abc
,F1-a1b2
。这可能不是真的。[1]
然后,我将继续为这些子部分中的每一个子部分编写解析器,并编写它们:
module Main where
import Text.Parsec
import Data.Maybe (catMaybes)
symbol :: String -> Parser String
symbol s = string s <* spaces
parens :: Parser a -> Parser a
parens = between (string "(") (string ")")
digits :: Parser Int
digits = read <$> many1 digit
parseF :: Parser F
parseF = curry F <$> firstPart <*> secondPart
where
firstPart :: Parser Int
firstPart = symbol "F" >> digits
secondPart :: Parser (Maybe String)
secondPart = optionMaybe $ choice
[ many1 letter
, parens (many1 letter)
, string "-" >> many1 alphaNum
]
外卖:
- 您可以使用令牌解析(
symbol
)解析可选空白
- 您可以使用语法解析可选部分
- 您可以使用
abc
或choice[a,b,c]
在组合符之间切换
- 当在两个选项之间交替时,确保它们的第一组不重叠。否则,您需要重叠;这很糟糕,但有时是不可避免的。(在这种情况下,三个选项的第一组是
字母,字符串”(“
和字符串”-”
,即不重叠。)
[1] :为了限制,我保留了上述假设,但我觉得我也可以假设F1a-B
,F1(a)-5
和F1(a)-5A
是有效的,在这种情况下,我可能会将模型更改为:
newtype F = F (Int, Maybe String, Maybe String)
我们可以使用
来自
请注意,这个tuhao
解析器实际上并没有返回任何内容。findAll
组合器只是检查解析器是否成功找到与模式匹配的子字符串
import Replace.Megaparsec
导入文本.Megaparsec
导入Text.Megaparsec.Char
导入数据,也许吧
导入数据。或者
let tuhao::Parsec空字符串()
土豪
无效$single'F'
void$space
无效$digitChar
void$many$one of“abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ()-”
input=“我想从F1(a)、F2a、F5-a、F34-5等中选择F12或F12,但不应仅选择F,也就是说,选择以F开头,后跟数字(数字之前可能有零个或多个空格),然后是['a'..'z']++['a'..'z']+['0'..'9']+['(','),\“-\”]中的任何字符。”
权限$fromJust$parseMaybe(findAll tuhao)输入
[“F12”、“F12”、“F1(a)”、“F2a”、“F5-a”、“F34-5”]
您的输入字符串是什么?我想看看这个,但尽管您给出了预期的输出([“F12”、“F12”、“F1(a)”、“F2a”、“F5-a”、“F34-5”]
),但没有给出input@AdamSmith显然,问题陈述本身就是输入:“我想从F1(a)中选择F12或F12…”@AdamSmith正如Zeta所说,问题描述是输入。使用[m|m这并没有解决如何从输入中提取所有这些内容的主要问题。您可以使用类似于的catMaybes many(try)(只是parseF)来实现这一点(没什么@JonPurdy:谢谢;这确实让解析器变得更有用了。@SimonShine和JonPurdy谢谢你们两位!这些建议对我很有帮助,特别是many
和try
,这是使用
Right [F (12,Nothing),F (12,Nothing),F (1,Just "a"),F (2,Just "a"),F (5,Just "A"),F (34,Just "5")]
newtype F = F (Int, Maybe String, Maybe String)