I'm trying to parse a list of asset types where each asset type potentially has a name. After the list is done I'd like to continue parsing a list of attributes for the asset types, one list for all asset types.
The string I'm trying to parse looks like:
converter named a023, signaltower, powerunit named 23 attributes power, temperature
The parser signature looks like
Parser<((Asset * AssetName option) list * Attribute liste),unit>
I got parsing the assets name, and the attributes separately, the problem arise when I combine the two and list is done, it then fails on the attributes string stating Expecting: 'named'
.
To me it seems that it is trying the opt assetname parser which fails on the attributes string, but I am not sure how to ignore that and move on when the list is "done" (after all the asset name part is optional)..
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"