namespace Sanchime.Json module Parser = let (|Match|_|) pattern input = let result = System.Text.RegularExpressions.Regex.Match(input, pattern) if result.Success then Some result.Value else None // 将字符串转为Ststem.Boolean类型 let bool (value: string) = System.Boolean.Parse(value) // 去除引号 let unquote (str: string) = str.Substring(1, str.Length - 2) // 获取Token let token = function | Match @"^\s+" str -> str, Whitespace | Match @"^""[^""\\]*(?:\\.[^""\\]*)*""" str -> str, str |> unquote |> StringLiteral | Match @"^\{|^\}|^\[|^\]|^:|^," str -> str, str[0] |> Symbol | Match @"^\d+(\.\d+)?|\.\d+" str -> str, str |> float |> NumberLiteral | Match @"^true|false" str -> str, str |> bool |> BooleanLiteral | _ -> failwith "无效的符号" // 将字符串拆分为Token列表 let tokenize str = let rec loop index (str: string) = if index = str.Length then [] else let next = str.Substring index let text, token = next |> token token :: loop (index + text.Length) str loop 0 str |> List.choose (function Whitespace -> None | value -> Some value) let rec (|Value|_|) = function // 数字常量字面量由数字组成 | NumberLiteral number :: tokens -> Some (Number number, tokens) // 逻辑常量字面了由真假值组成 | BooleanLiteral bool :: tokens -> Some (Boolean bool, tokens) // 字符串常量字面量由字符串组成 | StringLiteral string :: tokens -> Some (String string, tokens) // 数组由标识符 + 左中括号 + 值列表 + 右中括号组成 | Symbol '[' :: Values(jsons, Symbol ']' :: tokens) -> Some (Array jsons, tokens) // 对象由标识符 + 左大括号 + 对象列表 + 右大括号组成 | Symbol '{' :: Brackets (ps, Symbol '}' :: tokens) -> Some (Object ps, tokens) | [] -> Some (Null, []) | _ -> None // 值列表由逗号分割 and (|Values|_|) = function | Value(p, token) -> let rec aux p' = function | Symbol ',' :: Value (p, token) -> aux (p :: p') token | token -> p' |> List.rev, token Some (aux [p] token) | _ -> None // 对象由文本常量字面量 + 冒号 + 值组成 and (|Bracket|_|) = function | StringLiteral key :: Symbol ':' :: Value (value, token) -> Some ((key, value), token) | _ -> None // 对象数组由对象 + 逗号组成的列表 and (|Brackets|_|) = function | Bracket (p, tokens) -> let rec aux p' = function | Symbol ',' :: Bracket(p, tokens) -> aux (p :: p') tokens | tokens -> p' |> List.rev, tokens Some (aux [p] tokens) | _ -> None let parse str = str |> tokenize |> function | Value (value, []) -> value | _ -> failwith "解析Json失败"