- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
考虑这个正则表达式:
^foo/[^=]+/baz=(.*),[^,]*$
如果我在 foo/bar/baz=one,two
上运行它,它会匹配并且子组捕获 one
。如果我在 foo/bar/baz/bar/baz=三,四,五
上运行它,它会匹配并且子组捕获三,四
。
我知道如何将其转换为 regex-applicative
解析器或 ReadP
解析器:
import Text.Regex.Applicative
match (string "foo/" *> some (psym (/= '=')) *> string "/baz=" *> many anySym <* sym ',' <* many (psym (/= ','))) <$> ["foo/bar/baz=one,two", "foo/bar/baz/bar/baz=three,four,five"]
-- [Just "one",Just "three,four"]
import Text.ParserCombinators.ReadP
readP_to_S (string "foo/" *> many1 (satisfy (/= '=')) *> string "/baz=" *> many get <* char ',' <* many (satisfy (/= ',')) <* eof) <$> ["foo/bar/baz=one,two", "foo/bar/baz/bar/baz=three,four,five"]
-- [[("one","")],[("three,four","")]]
这两者都按照我想要的方式工作。但是当我尝试将其直接音译为 Megaparsec 时,情况很糟糕:
import Text.Megaparsec
parse (chunk "foo/" *> some (anySingleBut '=') *> chunk "/baz=" *> many anySingle <* single ',' <* many (anySingleBut ',') <* eof) "" <$> ["foo/bar/baz=one,two", "foo/bar/baz/bar/baz=three,four,five"]
-- [Left (ParseErrorBundle {bundleErrors = TrivialError 11 (Just (Tokens ('=' :| "one,"))) (fromList [Tokens ('/' :| "baz=")]) :| [], bundlePosState = PosState {pstateInput = "foo/bar/baz=one,two", pstateOffset = 0, pstateSourcePos = SourcePos {sourceName = "", sourceLine = Pos 1, sourceColumn = Pos 1}, pstateTabWidth = Pos 8, pstateLinePrefix = ""}}),Left (ParseErrorBundle {bundleErrors = TrivialError 19 (Just (Tokens ('=' :| "thre"))) (fromList [Tokens ('/' :| "baz=")]) :| [], bundlePosState = PosState {pstateInput = "foo/bar/baz/bar/baz=three,four,five", pstateOffset = 0, pstateSourcePos = SourcePos {sourceName = "", sourceLine = Pos 1, sourceColumn = Pos 1}, pstateTabWidth = Pos 8, pstateLinePrefix = ""}})]
我知道这源于兆秒差距默认情况下不回溯。我试图通过在许多不同的地方粘贴 try
来解决这个问题,但我无法让它工作。最终,我用 notFollowedBy
让这个怪物开始工作:
import Text.Megaparsec
parse (chunk "foo/" *> some (noneOf "=/" <|> try (single '/' <* notFollowedBy (chunk "baz="))) *> chunk "/baz=" *> many (try (anySingle <* notFollowedBy (many (anySingleBut ',') <* eof))) <* single ',' <* many (anySingleBut ',') <* eof) "" <$> ["foo/bar/baz=one,two", "foo/bar/baz/bar/baz=three,four,five"]
-- [Right "one",Right "three,four"]
但这看起来一团糟!特别是,我不喜欢我实际上必须两次指定大部分模式。从技术上讲,这不是相当于正则表达式 ^foo/(?:[^=/]|/(?!baz=))+/baz=((?:.(?![^, ]*$))*),[^,]*$
,而不是我最初的正则表达式?必须有更好的方法来编写该解析器。我该怎么做?
编辑:我也尝试过这种方式,也有效(不,它错误地接受foo//baz=,
):
import Text.Megaparsec
parse (chunk "foo/" *> (some . try $ many (noneOf "=/") *> single '/') *> chunk "baz=" *> ((++) <$> many (anySingleBut ',') <*> (concat <$> manyTill ((:) <$> single ',' <*> many (anySingleBut ',')) (try $ single ',' *> many (anySingleBut ',') *> eof)))) "" <$> ["foo/bar/baz=one,two", "foo/bar/baz/bar/baz=three,four,five"]
-- [Right "one",Right "three,four"]
不过,它看起来同样困惑,并且 manyTill
意味着它不再真正映射到任何正则表达式。
最佳答案
如果不仔细阅读,我猜给您带来麻烦的是这部分:
(.*),[^,]*
如果是这样,请考虑使用
sepBy (many (noneOf ",")) (string ",")
它将解析逗号分隔的列表。然后在纯代码中在该列表中除最后一个元素之外的所有元素之间重新插入逗号(例如,使用放置良好的 fmap
)。
从评论来看,您似乎在这部分也遇到了一些问题:
/[^=]+/baz=
你可以考虑这样的翻译:
slashPath = string "/" <++> path
path = string "baz=" <|> (many (noneOf "=/") <++> slashPath)
(<++>) = liftA2 (++)
关于regex - 如何将这个正则表达式转换为 Megaparsec 解析器而不造成困惑?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59654051/
我正在使用 Megaparsec 开发一个小型解析器并尝试解析算术。 -- Arithmetic expressions data Aexp = N Num | V Var
我正在尝试使用 lamdba 表达式解析一种简单的语言。但是runParser expr "lamdbda(x) (return x)返回Right (Var "lamdba")而不是Right (L
我在使用 Megaparsec 6 的 makeExprParser 时遇到问题 helper 。我似乎无法弄清楚如何绑定(bind)两个二进制 ^和一元 -在我期望的优先级。 使用这个makeExp
我想使用 Megaparsec 解析一种基本的缩进语言。最初我使用的是 Parsec,我设法通过缩进正常工作,但现在我遇到了一些麻烦。 我一直在关注一个教程here这是我必须解析一种忽略缩进的语言的代
我遇到了以下解析问题: 解析一些可能包含来自有限字符集的零个或多个元素的文本字符串,最多但不包括一组终止字符中的一个。应通过Maybe 指示内容/无内容。终止字符可能以转义形式出现在字符串中。任何不允
考虑这个正则表达式: ^foo/[^=]+/baz=(.*),[^,]*$ 如果我在 foo/bar/baz=one,two 上运行它,它会匹配并且子组捕获 one。如果我在 foo/bar/baz/
我有一个解析器定义为以下稍微复杂的版本: data X = X { getX :: State ([Int], [X]) Bool } type Parser = ParsecT Void Strin
我正在尝试为正在解析的某些源文件生成源映射,并且我想获取每个节点的范围。 getSourcePos只给出 start position一个节点(src:line:column)。如何获得它的结束位置?
我想使用 Megaparsec 在 Haskell 中解析与此类似的文本。 # START SKIP def foo(a,b): c = 2*a # Foo return a + b
使用 Megaparsec 5。 关注 this guide ,我可以通过结合 StateT 来实现回溯用户状态和 ParsecT (未定义的类型应该是明显的/不相关的): type MyParser
我在关注 Megaparsec documentation解析多维数组。 opSubscript = Postfix $ foldr1 (.) some singleIndex singleInde
所以我正在尝试做标准的“为类似方案的语言编写一个解析器”练习来找出 MegaParsec 和 monad 转换器。根据许多教程和博客文章的建议,我使用 ReaderT 和 local 来实现词法作用域
如果我有一个像这样的解析器: notZeroOrOne :: Parser Char notZeroOrOne = noneOf ['0' , '1'] 有没有一种方法可以组合另一个解析器(例如dig
我已经完成了this Megaparsec tutorial现在我正在尝试基于此编写我自己的解析器。我想为编写的汇编语言编写一个简单的解析器: Label: lda $0ffe sta
我是一名优秀的程序员,十分优秀!