我试图解析一个资产类型列表,其中每个资产类型都可能有一个名称。列表完成后,我想继续解析资产类型的属性列表,即所有资产类型的一个列表。
我试图解析的字符串如下所示:converter named a023, signaltower, powerunit named 23 attributes power, temperature
解析器签名看起来像Parser<((Asset * AssetName option) list * Attribute liste),unit>
我分别解析了资产名称和属性,当我将两者合并并列出时,问题就出现了,然后在声明Expecting: 'named'
的属性字符串上失败了。
对我来说,它似乎在尝试opt-assetname解析器,但它在属性字符串上失败了,但我不知道如何忽略它,并在列表"完成"时继续前进(毕竟资产名称部分是可选的(。。
type AssetName = AssetName of string
let named = str "named" >>. spaces1 >>. word
let assetName = spaces1 >>. (named |>> AssetName)
type Asset = | Converter | Signaltower | Powerunit
let assetType = ["converter"; "signaltower"; "powerunit";] |> Seq.map pstring |> choice
let findAsset = function
| "converter" -> Converter
| "signaltower" -> Signaltower
| "powerunit" -> Powerunit
| _ -> raise <| Exception "Invalid asset type"
let asset = (assetType |>> findAsset) .>>. opt assetName
type Attribute = Attribute of string
let attribute = word |>> Attribute
let attributes = spaces1 >>. str "attributes" >>. spaces1 >>. sepBy attribute commaMaybeSpace
let p = sepBy asset (pchar ',' >>. spaces) .>>. attributes
let r input = run p3 input
r "converter named a023, signaltower, powerunit named 23 attributes power, temperature"
编辑正如类似答案中所讨论的,以及文档中所暗示的,如果p
在更改其状态后失败,则可选的解析器opt p
将失败。相反,应该使用回溯(恢复状态(,可以与attempt
解析器一起使用,也可以与其中一个回溯运算符一起使用。
请记住,opt (attempt (p >>. q))
等同于opt (p >>? q)
,请尝试
let assetName = spaces1 >>? (named |>> AssetName)
不确定它是否与问题有关,但示例中的解析器类型与您描述的语法不匹配。我想你想要:
资产类型:|转换器|信号电源|动力装置
命名资产:|资产类型|已命名ident的资产类型
资产列表:命名资产命名资产
属性资产列表:资产列表属性标识列表
下面的行不重复命名资产的解析器。
let p = asset .>>. attributes
// val p : Parser<((Asset * AssetName option) * Attribute list),unit>
你可以用代替它
let p = sepBy asset (pchar ',' >>. spaces) .>>. attributes
// val p : Parser<((Asset * AssetName option) list * Attribute list),unit>
"converter named a023, signaltower, powerunit named 23 attributes power, temperature"
|> run p |> printfn "%A"
// Success: ([(Converter, Some (AssetName "a023")); (Signaltower, null);
// (Powerunit, Some (AssetName "23"))],
// [Attribute "power"; Attribute "temperature"])