Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
String 如何使用parsec获取字符串中特定模式的子字符串_String_Parsing_Haskell - Fatal编程技术网

String 如何使用parsec获取字符串中特定模式的子字符串

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

我是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。代码如下:

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)