我正在使用 Parsec 解析器来处理有点复杂的数据文件格式(我无法控制这种格式)。
我已经取得了很大的进步,但目前我坚持以下几点。
我需要能够像这样解析一行:
4 0.123 1.452 0.667 * 3.460 149 - -
语义上,4
是一个nodeNum,Floats
和*
是负对数概率(因此,*
表示概率为零的负对数)。和149
减号真的很垃圾,我可以丢弃,但我至少需要确保它们不会破坏解析器。
这是我到目前为止所拥有的:
这处理了我提到的“垃圾”。它可能更简单,但它本身就可以工作。
emAnnotationSet = (,,) <$> p_int <*>
(reqSpaces *> char '-') <*>
(reqSpaces *> char '-')
该nodeNum
行的开头由另一个有效的解析器处理,我不需要进入。
问题在于尝试p_logProb
从行中挑选出所有 s ,而不消耗 . 开头的数字emAnnotationSet
。
解析器p_logProb
看起来像这样:
p_logProb = liftA mkScore (lp <?> "logProb")
where lp = try dub <|> string "*"
dub = (++) <$> ((++) <$> many1 digit <*> string ".") <*> many1 digit
最后,我尝试将logProb
条目与尾随emAnnotationSet
(以整数开头)分开,如下所示:
hmmMatchEmissions = optSpaces *> (V.fromList <$> sepBy p_logProb reqSpaces)
<* optSpaces <* emAnnotationSet <* eol
<?> "matchEmissions"
因此,p_logProb
只会在以数字开头、包含小数点、然后有更多数字的浮点数上成功(文件格式遵守此限制)。
我希望定义try
中的 thep_logProb
可以避免使用前导数字,如果它不解析小数和其余部分,但这似乎不起作用;Parsec 仍然抱怨它在以下整数的数字之后看到了一个意外的空格emAnnotationSet
:
Left "hmmNode" (line 1, column 196):
unexpected " "
expecting logProb
第 196 列对应于减号之前的整数之后的空格,所以我很清楚问题在于p_logProb
解析器正在使用整数。我该如何解决这个问题,以便p_logProb
解析器正确使用前瞻,从而将输入留给emAnnotationSet
解析器?