我希望使用F#將字符串解析爲遞歸數據結構。在這個問題中,我將介紹一個簡化的例子,切入我想要做的核心。解析爲遞歸數據結構
我想分析嵌套的方括號中的字符串中的記錄類型:
type Bracket = | Bracket of Bracket option
所以:
- 「[]」 - >
Bracket None
- 「[[]] 「 - >
Bracket (Some (Bracket None))
- 」[[[]]]「 - >
Bracket (Some (Bracket (Some (Bracket None))))
我想使用FParsec庫中的解析器組合器來執行此操作。以下是我迄今爲止:
let tryP parser =
parser |>> Some
<|>
preturn None
/// Parses up to nesting level of 3
let parseBrakets : Parser<_> =
let mostInnerLevelBracket =
pchar '['
.>> pchar ']'
|>> fun _ -> Bracket None
let secondLevelBracket =
pchar '['
>>. tryP mostInnerLevelBracket
.>> pchar ']'
|>> Bracket
let firstLevelBracket =
pchar '['
>>. tryP secondLevelBracket
.>> pchar ']'
|>> Bracket
firstLevelBracket
我甚至有一些Expecto測試:
open Expecto
[<Tests>]
let parserTests =
[ "[]", Bracket None
"[[]]", Bracket (Some (Bracket None))
"[[[]]]", Bracket (Some (Bracket (Some (Bracket None)))) ]
|> List.map(fun (str, expected) ->
str
|> sprintf "Trying to parse %s"
|> testCase
<| fun _ ->
match run parseBrakets str with
| Success (x, _,_) -> Expect.equal x expected "These should have been equal"
| Failure (m, _,_) -> failwithf "Expected a match: %s" m
)
|> testList "Bracket tests"
let tests =
[ parserTests ]
|> testList "Tests"
runTests defaultConfig tests
問題當然是如何處理和築巢的任意水平的 - 只有上面的代碼是用來檢測向上到3個級別。我會像向編寫的代碼是:
let rec pNestedBracket =
pchar '['
>>. tryP pNestedBracket
.>> pchar ']'
|>> Bracket
但F#不允許這樣做。
我是怎麼解決這個問題的(我知道有更簡單的方法來解決這個特定的問題),我完全吠叫了錯誤的樹嗎?
謝謝托馬斯 - 一旦我有機會通過它,標誌着答案。 – Lawrence