秒差距 start-of-row 模式?

Parsec start-of-row pattern?

我正在尝试使用 Parsec 解析 mediawiki 文本。 mediawiki 标记中的某些结构只能出现在行的开头(例如 header 标记 ==header level 2==)。在正则表达式中,我会使用锚点(例如 ^)来查找一行的开头。

GHCi 的一次尝试是

Prelude Text.Parsec> parse (char '\n' *> string "==" *> many1 letter <* string "==") "" "\n==hej=="
Right "hej"

但这不太好,因为它会在文件的第一行失败。我觉得这应该是一个解决的问题...

Parsec 中最惯用的 "Start of line" 解析是什么?

也许您可以使用 many (char '\n') 而不仅仅是 char '\n'。在解析器组合器中,没有 行首 的意义,因为它们总是 运行 在输入的开头。您唯一可以做的就是手动检查您的输入可以从哪些符号开始。使用 many (char '\n') 确保在 header == my header ==.

之前只有零个或多个空行

您可以使用 getPosition and sourceColumn 来找出解析器当前正在查看的列号。如果当前位置在一行的开头(例如在输入的开头或在 \n\r 字符之后),列号将为 1

没有 built-in 组合器,但您可以轻松实现:

import Text.Parsec
import Control.Monad (guard)

startOfLine :: Monad m => ParsecT s u m ()
startOfLine = do
    pos <- getPosition
    guard (sourceColumn pos == 1)

现在您可以将 header 解析器编写为:

header = startOfLine *> string "==" *> many1 letter <* string "=="