使用 Parsec 解析数据并省略注释

标签 parsing haskell parsec

我正在尝试编写一个 Haksell Parsec Parser,它将文件中的输入数据解析为 LogLine 数据类型,如下所示:

--Final parser that holds the indvidual parsers.
final :: Parser [LogLine]
final = do{ logLines <- sepBy1 logLine eol
        ; return logLines
        }


--The logline token declaration
logLine :: Parser LogLine
logLine = do
name <-  plainValue -- parse the name (identifier)
many1 space -- parse and throw away a space
args1 <- bracketedValue -- parse the first arguments
many1 space -- throw away the second sapce
args2 <- bracketedValue -- parse the second list of arguments
many1 space -- 
constant <- plainValue -- parse the constant identifier
space
weighting <- plainValue --parse the weighting double
space
return $ LogLine name args1 args2 constant weighting

它可以很好地解析所有内容,但是现在我需要向文件添加注释,并且必须修改解析器以使其忽略它们。
它应该支持仅以“--”开头并以“\n”结尾的单行注释
我试过如下定义评论标记:
comments :: Parser String
comments = do 
    string "--"
    comment <- (manyTill anyChar newline)
    return ""

然后将其插入final像这样的解析器:
final :: Parser [LogLine]
final = do 
        optional comments
        logLines <- sepBy1 logLine (comments<|>newline)
        optional comments
        return logLines

它编译得很好,但它不解析。我已经尝试了几个小的修改,但最好的结果是解析所有内容直到第一个评论,所以我开始认为这不是这样做的方法。
PS:
我见过这个 Similar Question ,但这与我试图实现的目标略有不同。

最佳答案

如果我正确理解您在评论中对格式的描述,您的格式示例将是

name arg1 arg2 c1 weight
-- comment goes here

可选地后跟进一步的日志行和/或评论。

那么你的问题是日志行和注释行之间有一个换行符,这意味着 comments部分分隔符解析器失败 - comments必须以 "--" 开头- 不消耗输入,所以 newline尝试并成功。然后下一行以 "--" 开头这使得 plainValue在不消耗输入的情况下失败,从而结束 sepBy1 .

解决的办法是让分隔符先消耗一个换行符,然后尽可能多的注释行如下:
final = do
    skipMany comments
    sepEndBy1 logLine (newline >> skipMany comments)

通过允许序列以分隔符( sepEndBy1 而不是 sepBy1 )结束,最后的 LogLine 之后的任何注释行会自动跳过。

关于使用 Parsec 解析数据并省略注释,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12990847/

相关文章:

php - PHP解析/语法错误;以及如何解决它们

haskell - Aeson 棱镜,引用号为 "free"

haskell - 新型 HashMap 键的 FromJSON 实例

parsing - Haskell 解析 - Parsec 与 Alex

python - 使用 Python 的 parsec.py 库进行递归解析

c++ - 检查字符串是否包含子字符串,不管大小写

python - 在Python中解析和截断长字符串

python - 从特定值开始读取 3,000 个文件并将其连接到 pandas 数据帧中,python

haskell - 数组生成中的奇怪 <<loop>> 异常

parsing - Parsec 解析不同类型语句的列表