let of_string str : t =
let fail msg =
raise (Parse_error (sprintf "Request Syntax Error: %s" msg)) in
let atom_list l =
Ls.map l ~f:(function Sx.Atom s -> s
| _ -> fail "Expecting list of atoms") in
let rec parse_expr =
function
| Sx.Atom s -> fail (sprintf "Unexpected atom: %s" s)
| Sx.List ((Sx.Atom "and") :: args) ->
if args =@= [] then
fail "'and' expects arguments"
else
(`list_and (Ls.map parse_expr args))
| Sx.List ((Sx.Atom "or") :: args) ->
if args =@= [] then
fail "'or' expects arguments"
else
(`list_or (Ls.map parse_expr args))
| Sx.List ((Sx.Atom "not") :: args) ->
(`not (parse_expr (Sx.List args)))
| Sx.List [(Sx.Atom "matches"); (Sx.Atom field); (Sx.Atom rex)] ->
(`matches ((Biblio.field_name_of_string field), rex))
| Sx.List ((Sx.Atom "ids") :: args) ->
(`ids (atom_list args))
| Sx.List ((Sx.Atom "tags") :: args) ->
(`tags (atom_list args))
| Sx.List [(Sx.Atom "has"); (Sx.Atom field)] ->
(`has (Biblio.field_name_of_string field))
| Sx.List ((Sx.List l) :: []) ->
(parse_expr (Sx.List l))
| s -> fail (sprintf
"Can't parse expression %s"
(Sx.to_string s))
in
let sexp =
try Sx.of_string (sprintf "(%s)" str)
with Failure msg ->
raise (Parse_error (sprintf "Request Syntax Error (sexplib): %s" msg))
in
(parse_expr sexp)