快速解析允许转义字符的字符串?

丹尼尔·RS

我正在尝试解析一个可以包含转义字符的字符串,这是一个示例:

import qualified Data.Text as T

exampleParser :: Parser T.Text
exampleParser = T.pack <$> many (char '\\' *> escaped <|> anyChar)
  where escaped = satisfy (\c -> c `elem` ['\\', '"', '[', ']'])

上面的解析器创建一个String,然后将其打包到中Text有什么方法可以使用attoparsec提供的有效字符串处理功能来解析带有上述转义符的字符串?stringscanrunScannertakeWhile...

解析类似的东西"one \"two\" \[three\]"会产生one "two" [three]

更新

感谢@epsilonhalbe,我得以提出一个完全适合我需要的通用解决方案。请注意,以下功能不查找匹配转义字符一样[..]".."(..)等; 并且,如果找到无效的转义字符,则将其视为\文字字符。

takeEscapedWhile :: (Char -> Bool) -> (Char -> Bool) -> Parser Text
takeEscapedWhile isEscapable while = do
  x <- normal
  xs <- many escaped
  return $ T.concat (x:xs)
  where normal = Atto.takeWhile (\c -> c /= '\\' && while c)
        escaped = do
          x <- (char '\\' *> satisfy isEscapable) <|> char '\\'
          xs <- normal
          return $ T.cons x xs
epsilonhalbe

可以编写一些转义代码,attoparsec并且text-总体而言非常简单-看到您已经使用解析器

import Data.Attoparsec.Text as AT
import qualified Data.Text as T
import Data.Text (Text)

escaped, quoted, brackted :: Parser Text
normal =  AT.takeWhile (/= '\\')
escaped = do r <- normal
             rs <- many escaped'
             return $ T.concat $ r:rs
  where escaped' = do r1 <- normal
                      r2 <- quoted <|> brackted
                      return $ r1 <> r2

quoted = do string "\\\""
            res <- normal
            string "\\\""
            return $ "\""<>res <>"\""

brackted = do string "\\["
              res <- normal
              string "\\]"
              return $ "["<>res<>"]"

然后您可以使用它来解析以下测试用例

Prelude >: MyModule
Prelude MyModule> import Data.Attoparsec.Text as AT
Prelude MyModule AT> import Data.Text.IO as TIO
Prelude MyModule AT TIO>:set -XOverloadedStrings
Prelude MyModule AT TIO> TIO.putStrLn $ parseOnly escaped "test"
test
Prelude MyModule AT TIO> TIO.putStrLn $ parseOnly escaped "\\\"test\\\""
"test"
Prelude MyModule AT TIO> TIO.putStrLn $ parseOnly escaped "\\[test\\]"
[test]
Prelude MyModule AT TIO> TIO.putStrLn $ parseOnly escaped "test \\\"test\\\" \\[test\\]"
test "test" [test]

请注意,您必须逃脱-这就是为什么您看到\\\"而不是\"

另外,如果您只是解析,它将打印Text转义值,例如

Right "test \"text\" [test]"

对于最后一个例子。

如果解析文件,则在文件中写入简单的转义文本。

test.txt

I \[like\] \"Haskell\"

那么你就可以

Prelude MyModule AT TIO> file <- TIO.readFile "test.txt" 
Prelude MyModule AT TIO> TIO.putStrLn $ parseOnly escaped file
I [like] "Haskell"

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章