【发布时间】:2021-05-18 06:09:24
【问题描述】:
我正在编写一个特定文件格式的解析器,使用 FParsec 作为学习 fsharp 的第一步。部分文件格式如下
{ 123 456 789 333 }
括号中的数字是成对的值,可以有任意数量的空格来分隔它们。所以这些也是要解析的有效内容:
{ 22 456 7 333 }
当然,括号的内容可能是空的,即{}
此外,我希望解析器能够处理内容格式不正确的情况,例如。 { some descriptive text } 或者更可能是 { 12 3 4}(无效,因为 4 不会与任何东西配对)。在这种情况下,我只想将保存的内容单独处理。
到目前为止我有这个:
type DimNummer = int
type ObjektNummer = int
type DimObjektPair = DimNummer * ObjektNummer
type ObjektListResult = Result<DimObjektPair list, string>
let sieObjektLista =
let pnum = numberLiteral NumberLiteralOptions.None "dimOrObj"
let ws = spaces
let pobj = pnum .>> ws |>> fun x ->
let on: ObjektNummer = int x.String
on
let pdim = pnum |>> fun x ->
let dim: DimNummer = int x.String
dim
let pdimObj = (pdim .>> spaces1) .>>. pobj |>> DimObjektPair
let toObjektLista(objList:list<DimObjektPair>) =
let res: ObjektListResult = Result.Ok objList
res
let pdimObjs = sepBy pdimObj spaces1
let validList = pdimObjs |>> toObjektLista
let toInvalid(str:string) =
let res: ObjektListResult =
match str.Trim(' ') with
| "" -> Result.Ok []
| _ -> Result.Error str
res
let invalidList = manyChars anyChar |>> toInvalid
let pres = between (pchar '{') (pchar '}') (ws >>. (validList <|> invalidList) .>> ws)
pres
let parseSieObjektLista = run sieObjektLista
但是在一个有效的样本上运行这个我得到一个错误:
{ 53735 7785 86231 36732 }
^
Expecting: whitespace or '}'
【问题讨论】:
-
只是一个提示:至少对于调试(但一般来说,我的口味)我会从 sieObjektLista 中取出所有嵌套函数,这样您就可以轻松地单独测试每个(子)解析器函数。您在 f# 交互式中调试它。一般来说,嵌套函数可以避免污染命名空间,但会使代码维护变得更加困难(不能再单独运行它们),所以通常最好避免使用它们,除非有充分的理由。
-
感谢您的建议。我想保持模块界面相当干净,但我认为你是对的。如果所有解析器函数都可以访问,即使它们只是在内部使用,调试等也会变得更容易。