Refactor S-expression parsing
This commit is contained in:
parent
af82f587e4
commit
c6b2169037
|
@ -273,7 +273,6 @@ let create_for_opam ?root ~switch ~name () =
|
||||||
>>= fun s ->
|
>>= fun s ->
|
||||||
let vars =
|
let vars =
|
||||||
Sexp_lexer.single (Lexing.from_string s)
|
Sexp_lexer.single (Lexing.from_string s)
|
||||||
|> fst
|
|
||||||
|> Sexp.Of_sexp.(string_map string)
|
|> Sexp.Of_sexp.(string_map string)
|
||||||
in
|
in
|
||||||
let path =
|
let path =
|
||||||
|
|
|
@ -735,7 +735,7 @@ module Gen(P : Params) = struct
|
||||||
Build.arr (fun () ->
|
Build.arr (fun () ->
|
||||||
let files_contents =
|
let files_contents =
|
||||||
List.map2 files paths ~f:(fun fn path ->
|
List.map2 files paths ~f:(fun fn path ->
|
||||||
(fn, Sexp_load.single (Path.to_string path) (fun x -> x)))
|
(fn, Sexp_load.single (Path.to_string path)))
|
||||||
|> String_map.of_alist_exn
|
|> String_map.of_alist_exn
|
||||||
in
|
in
|
||||||
let set = Ordered_set_lang.Unexpanded.expand set ~files_contents in
|
let set = Ordered_set_lang.Unexpanded.expand set ~files_contents in
|
||||||
|
@ -1360,7 +1360,7 @@ module Gen(P : Params) = struct
|
||||||
Sexp.To_sexp.list Dep_conf_interpret.sexp_of_t alias_conf.deps in
|
Sexp.To_sexp.list Dep_conf_interpret.sexp_of_t alias_conf.deps in
|
||||||
let action =
|
let action =
|
||||||
match alias_conf.action with
|
match alias_conf.action with
|
||||||
| None -> Atom "none"
|
| None -> Sexp.Atom "none"
|
||||||
| Some a -> List [Atom "some" ; User_action.Unexpanded.sexp_of_t a] in
|
| Some a -> List [Atom "some" ; User_action.Unexpanded.sexp_of_t a] in
|
||||||
Sexp.List [deps ; action]
|
Sexp.List [deps ; action]
|
||||||
|> Sexp.to_string
|
|> Sexp.to_string
|
||||||
|
|
|
@ -15,7 +15,7 @@ module Section : sig
|
||||||
| Man
|
| Man
|
||||||
| Misc
|
| Misc
|
||||||
|
|
||||||
val t : Sexp.t -> t
|
val t : t Sexp.Of_sexp.t
|
||||||
end
|
end
|
||||||
|
|
||||||
module Entry : sig
|
module Entry : sig
|
||||||
|
|
|
@ -9,25 +9,24 @@ type conf =
|
||||||
}
|
}
|
||||||
|
|
||||||
let load ~dir ~visible_packages ~version =
|
let load ~dir ~visible_packages ~version =
|
||||||
let version, stanzas =
|
let sexps = Sexp_load.many (Path.relative dir "jbuild" |> Path.to_string) in
|
||||||
Sexp_load.many (Path.relative dir "jbuild" |> Path.to_string)
|
let versions, sexps =
|
||||||
(fun sexps ->
|
List.partition_map sexps ~f:(function
|
||||||
let versions, sexps =
|
| List (loc, [Atom (_, ("jbuilder_version" | "Jbuilder_version")); ver]) ->
|
||||||
List.partition_map sexps ~f:(function
|
Inl (Jbuilder_version.t ver, loc)
|
||||||
| List [Atom ("jbuilder_version" | "Jbuilder_version"); ver] as sexp ->
|
| sexp -> Inr sexp)
|
||||||
Inl (Jbuilder_version.t ver, sexp)
|
in
|
||||||
| sexp -> Inr sexp)
|
let version =
|
||||||
in
|
match versions with
|
||||||
let version =
|
| [] -> version
|
||||||
match versions with
|
| [(v, _)] -> v
|
||||||
| [] -> version
|
| _ :: (_, loc) :: _ ->
|
||||||
| [(v, _)] -> v
|
Loc.fail loc "jbuilder_version specified too many times"
|
||||||
| _ :: (_, sexp) :: _ ->
|
in
|
||||||
of_sexp_error sexp "jbuilder_version specified too many times"
|
let stanzas =
|
||||||
in
|
List.filter_map sexps ~f:(Stanza.select version)
|
||||||
(version, List.filter_map sexps ~f:(Stanza.select version)))
|
|> Stanza.resolve_packages ~dir ~visible_packages
|
||||||
in
|
in
|
||||||
let stanzas = Stanza.resolve_packages stanzas ~dir ~visible_packages in
|
|
||||||
(version, stanzas)
|
(version, stanzas)
|
||||||
|
|
||||||
let load () =
|
let load () =
|
||||||
|
|
|
@ -8,10 +8,6 @@ open Sexp.Of_sexp
|
||||||
[jane_street] version. When they are all the same, sexp parsers are just named [t].
|
[jane_street] version. When they are all the same, sexp parsers are just named [t].
|
||||||
*)
|
*)
|
||||||
|
|
||||||
type sexp = Sexp.t = Atom of string | List of sexp list
|
|
||||||
let of_sexp_error = Sexp.of_sexp_error
|
|
||||||
let of_sexp_errorf = Sexp.of_sexp_errorf
|
|
||||||
|
|
||||||
module Jbuilder_version = struct
|
module Jbuilder_version = struct
|
||||||
type t =
|
type t =
|
||||||
| V1
|
| V1
|
||||||
|
@ -73,7 +69,7 @@ module Raw_string () : sig
|
||||||
type t = private string
|
type t = private string
|
||||||
val to_string : t -> string
|
val to_string : t -> string
|
||||||
val of_string : string -> t
|
val of_string : string -> t
|
||||||
val t : Sexp.t -> t
|
val t : t Sexp.Of_sexp.t
|
||||||
end = struct
|
end = struct
|
||||||
type t = string
|
type t = string
|
||||||
let to_string t = t
|
let to_string t = t
|
||||||
|
@ -130,20 +126,13 @@ module User_action = struct
|
||||||
| With_stdout_to of 'a * 'a t
|
| With_stdout_to of 'a * 'a t
|
||||||
|
|
||||||
let rec t a sexp =
|
let rec t a sexp =
|
||||||
match sexp with
|
sum
|
||||||
| List (Atom "run" :: prog :: args) -> Run (a prog, List.map args ~f:a)
|
[ cstr_rest "run" [a] a (fun prog args -> Run (prog, args))
|
||||||
| List [ Atom "chdir"; dir; arg ] -> Chdir (a dir, t a arg)
|
; cstr "chdir" [a; t a] (fun dn t -> Chdir (dn, t))
|
||||||
| List [ Atom "setenv"; var; value; arg ] -> Setenv (a var, a value, t a arg)
|
; cstr "setenv" [a; a; t a] (fun k v t -> Setenv (k, v, t))
|
||||||
| List [ Atom "with-stdout-to"; file; arg ] -> With_stdout_to (a file, t a arg)
|
; cstr "with-stdout-to" [a; t a] (fun fn t -> With_stdout_to (fn, t))
|
||||||
| _ ->
|
]
|
||||||
of_sexp_error sexp "\
|
sexp
|
||||||
invalid action, expected one of:
|
|
||||||
|
|
||||||
(run <prog> <args>)
|
|
||||||
(chdir <dir> <action>)
|
|
||||||
(setenv <var> <value> <action>)
|
|
||||||
(with-stdout-to <file> <action>)
|
|
||||||
"
|
|
||||||
|
|
||||||
let rec map t ~f =
|
let rec map t ~f =
|
||||||
match t with
|
match t with
|
||||||
|
@ -184,7 +173,7 @@ invalid action, expected one of:
|
||||||
in
|
in
|
||||||
loop String_map.empty dir [] t
|
loop String_map.empty dir [] t
|
||||||
|
|
||||||
let rec sexp_of_t f = function
|
let rec sexp_of_t f : _ -> Sexp.t = function
|
||||||
| Run (a, xs) -> List (Atom "run" :: f a :: List.map xs ~f)
|
| Run (a, xs) -> List (Atom "run" :: f a :: List.map xs ~f)
|
||||||
| Chdir (a, r) -> List [Atom "chdir" ; f a ; sexp_of_t f r]
|
| Chdir (a, r) -> List [Atom "chdir" ; f a ; sexp_of_t f r]
|
||||||
| Setenv (k, v, r) -> List [Atom "setenv" ; f k ; f v ; sexp_of_t f r]
|
| Setenv (k, v, r) -> List [Atom "setenv" ; f k ; f v ; sexp_of_t f r]
|
||||||
|
@ -211,7 +200,7 @@ invalid action, expected one of:
|
||||||
| Bash x -> f init x
|
| Bash x -> f init x
|
||||||
| Shexp x -> Mini_shexp.fold x ~init ~f
|
| Shexp x -> Mini_shexp.fold x ~init ~f
|
||||||
|
|
||||||
let sexp_of_t f = function
|
let sexp_of_t f : _ -> Sexp.t = function
|
||||||
| Bash a -> List [Atom "bash" ; f a]
|
| Bash a -> List [Atom "bash" ; f a]
|
||||||
| Shexp a -> List [Atom "shexp" ; Mini_shexp.sexp_of_t f a]
|
| Shexp a -> List [Atom "shexp" ; Mini_shexp.sexp_of_t f a]
|
||||||
end
|
end
|
||||||
|
@ -296,11 +285,12 @@ module Preprocess_map = struct
|
||||||
| For_all pp -> pp
|
| For_all pp -> pp
|
||||||
| Per_file map -> String_map.find_default module_name map ~default:No_preprocessing
|
| Per_file map -> String_map.find_default module_name map ~default:No_preprocessing
|
||||||
|
|
||||||
let default = For_all (Pps { pps = Pp_set.singleton (Pp.of_string "ppx_jane"); flags = [] })
|
let default_v1 = For_all No_preprocessing
|
||||||
|
let default_vjs = For_all (Pps { pps = Pp_set.singleton (Pp.of_string "ppx_jane"); flags = [] })
|
||||||
|
|
||||||
let t sexp =
|
let t sexp =
|
||||||
match sexp with
|
match sexp with
|
||||||
| List (Atom "per_file" :: rest) -> begin
|
| List (_, Atom (_, "per_file") :: rest) -> begin
|
||||||
List.concat_map rest ~f:(fun sexp ->
|
List.concat_map rest ~f:(fun sexp ->
|
||||||
let pp, names = pair Preprocess.t module_names sexp in
|
let pp, names = pair Preprocess.t module_names sexp in
|
||||||
List.map (String_set.elements names) ~f:(fun name -> (name, pp)))
|
List.map (String_set.elements names) ~f:(fun name -> (name, pp)))
|
||||||
|
@ -352,15 +342,15 @@ module Lib_dep = struct
|
||||||
| Select of { result_fn : string; choices : choice list }
|
| Select of { result_fn : string; choices : choice list }
|
||||||
|
|
||||||
let choice = function
|
let choice = function
|
||||||
| List l as sexp ->
|
| List (_, l) as sexp ->
|
||||||
let rec loop acc = function
|
let rec loop acc = function
|
||||||
| [Atom "->"; sexp] ->
|
| [Atom (_, "->"); sexp] ->
|
||||||
{ lits = List.rev acc
|
{ lits = List.rev acc
|
||||||
; file = file sexp
|
; file = file sexp
|
||||||
}
|
}
|
||||||
| Atom "->" :: _ | List _ :: _ | [] ->
|
| Atom (_, "->") :: _ | List _ :: _ | [] ->
|
||||||
of_sexp_error sexp "(<[!]libraries>... -> <file>) expected"
|
of_sexp_error sexp "(<[!]libraries>... -> <file>) expected"
|
||||||
| Atom s :: l ->
|
| Atom (_, s) :: l ->
|
||||||
let len = String.length s in
|
let len = String.length s in
|
||||||
if len > 0 && s.[0] = '!' then
|
if len > 0 && s.[0] = '!' then
|
||||||
let s = String.sub s ~pos:1 ~len:(len - 1) in
|
let s = String.sub s ~pos:1 ~len:(len - 1) in
|
||||||
|
@ -371,16 +361,17 @@ module Lib_dep = struct
|
||||||
loop [] l
|
loop [] l
|
||||||
| sexp -> of_sexp_error sexp "(<library-name> <code>) expected"
|
| sexp -> of_sexp_error sexp "(<library-name> <code>) expected"
|
||||||
|
|
||||||
let sexp_of_choice { lits; file } =
|
let sexp_of_choice { lits; file } : Sexp.t =
|
||||||
List (List.fold_right lits ~init:[Atom "->"; Atom file] ~f:(fun lit acc ->
|
List (List.fold_right lits ~init:[Atom "->"; Atom file]
|
||||||
match lit with
|
~f:(fun lit acc : Sexp.t list ->
|
||||||
| Pos s -> Atom s :: acc
|
match lit with
|
||||||
| Neg s -> Atom ("!" ^ s) :: acc))
|
| Pos s -> Atom s :: acc
|
||||||
|
| Neg s -> Atom ("!" ^ s) :: acc))
|
||||||
|
|
||||||
let t = function
|
let t = function
|
||||||
| Atom s ->
|
| Atom (_, s) ->
|
||||||
Direct s
|
Direct s
|
||||||
| List (Atom "select" :: m :: Atom "from" :: libs) ->
|
| List (_, Atom (_, "select") :: m :: Atom (_, "from") :: libs) ->
|
||||||
Select { result_fn = file m
|
Select { result_fn = file m
|
||||||
; choices = List.map libs ~f:choice
|
; choices = List.map libs ~f:choice
|
||||||
}
|
}
|
||||||
|
@ -409,8 +400,8 @@ module Buildable = struct
|
||||||
; ocamlopt_flags : Ordered_set_lang.t
|
; ocamlopt_flags : Ordered_set_lang.t
|
||||||
}
|
}
|
||||||
|
|
||||||
let common =
|
let common ~pp_default =
|
||||||
field "preprocess" Preprocess_map.t ~default:Preprocess_map.default
|
field "preprocess" Preprocess_map.t ~default:pp_default
|
||||||
>>= fun preprocess ->
|
>>= fun preprocess ->
|
||||||
field "preprocessor_deps" (list Dep_conf.t) ~default:[]
|
field "preprocessor_deps" (list Dep_conf.t) ~default:[]
|
||||||
>>= fun preprocessor_deps ->
|
>>= fun preprocessor_deps ->
|
||||||
|
@ -432,10 +423,10 @@ module Buildable = struct
|
||||||
; ocamlopt_flags
|
; ocamlopt_flags
|
||||||
}
|
}
|
||||||
|
|
||||||
let v1 = common
|
let v1 = common ~pp_default:Preprocess_map.default_v1
|
||||||
|
|
||||||
let vjs =
|
let vjs =
|
||||||
common >>= fun t ->
|
common ~pp_default:Preprocess_map.default_vjs >>= fun t ->
|
||||||
field "extra_disabled_warnings" (list int) ~default:[]
|
field "extra_disabled_warnings" (list int) ~default:[]
|
||||||
>>= fun extra_disabled_warnings ->
|
>>= fun extra_disabled_warnings ->
|
||||||
let t =
|
let t =
|
||||||
|
@ -443,11 +434,13 @@ module Buildable = struct
|
||||||
let flags =
|
let flags =
|
||||||
Ordered_set_lang.append t.flags
|
Ordered_set_lang.append t.flags
|
||||||
(Ordered_set_lang.t
|
(Ordered_set_lang.t
|
||||||
(List [ Atom "-w"
|
(List (Loc.none,
|
||||||
; Atom
|
[ Atom (Loc.none, "-w")
|
||||||
(String.concat ~sep:""
|
; Atom
|
||||||
(List.map extra_disabled_warnings ~f:(sprintf "-%d")))
|
(Loc.none,
|
||||||
]))
|
String.concat ~sep:""
|
||||||
|
(List.map extra_disabled_warnings ~f:(sprintf "-%d")))
|
||||||
|
])))
|
||||||
in
|
in
|
||||||
{ t with flags }
|
{ t with flags }
|
||||||
else
|
else
|
||||||
|
@ -578,7 +571,9 @@ module Library = struct
|
||||||
; c_library_flags =
|
; c_library_flags =
|
||||||
Ordered_set_lang.Unexpanded.append
|
Ordered_set_lang.Unexpanded.append
|
||||||
(Ordered_set_lang.Unexpanded.t
|
(Ordered_set_lang.Unexpanded.t
|
||||||
(Sexp.To_sexp.(list string (List.map c_libraries ~f:((^) "-l")))))
|
(List (Loc.none,
|
||||||
|
List.map c_libraries ~f:(fun lib ->
|
||||||
|
Atom (Loc.none, "-l" ^ lib)))))
|
||||||
c_library_flags
|
c_library_flags
|
||||||
; self_build_stubs_archive
|
; self_build_stubs_archive
|
||||||
; js_of_ocaml
|
; js_of_ocaml
|
||||||
|
@ -691,14 +686,14 @@ module Provides = struct
|
||||||
|
|
||||||
let v1 sexp =
|
let v1 sexp =
|
||||||
match sexp with
|
match sexp with
|
||||||
| Atom s ->
|
| Atom (_, s) ->
|
||||||
{ name = s
|
{ name = s
|
||||||
; file =
|
; file =
|
||||||
match String.lsplit2 s ~on:':' with
|
match String.lsplit2 s ~on:':' with
|
||||||
| None -> s
|
| None -> s
|
||||||
| Some (_, s) -> s
|
| Some (_, s) -> s
|
||||||
}
|
}
|
||||||
| List [Atom s; List [Atom "file"; Atom file]] ->
|
| List (_, [Atom (_, s); List (_, [Atom (_, "file"); Atom (_, file)])]) ->
|
||||||
{ name = s
|
{ name = s
|
||||||
; file
|
; file
|
||||||
}
|
}
|
||||||
|
@ -714,10 +709,11 @@ module Install_conf = struct
|
||||||
; dst : string option
|
; dst : string option
|
||||||
}
|
}
|
||||||
|
|
||||||
let file (sexp : Sexp.t) =
|
let file sexp =
|
||||||
match sexp with
|
match sexp with
|
||||||
| Atom src -> { src; dst = None }
|
| Atom (_, src) -> { src; dst = None }
|
||||||
| List [Atom src; Atom "as"; Atom dst] -> { src; dst = Some dst }
|
| List (_, [Atom (_, src); Atom (_, "as"); Atom (_, dst)]) ->
|
||||||
|
{ src; dst = Some dst }
|
||||||
| _ ->
|
| _ ->
|
||||||
of_sexp_error sexp
|
of_sexp_error sexp
|
||||||
"invalid format, <name> or (<name> as <install-as>) expected"
|
"invalid format, <name> or (<name> as <install-as>) expected"
|
||||||
|
@ -814,7 +810,7 @@ module Stanza = struct
|
||||||
; cstr "jbuilder_version" [Jbuilder_version.t] (fun _ -> None)
|
; cstr "jbuilder_version" [Jbuilder_version.t] (fun _ -> None)
|
||||||
]
|
]
|
||||||
|
|
||||||
let select : Jbuilder_version.t -> Sexp.t -> t option = function
|
let select : Jbuilder_version.t -> t option Sexp.Of_sexp.t = function
|
||||||
| V1 -> v1
|
| V1 -> v1
|
||||||
| Vjs -> vjs
|
| Vjs -> vjs
|
||||||
|
|
||||||
|
|
|
@ -30,3 +30,4 @@ let in_file fn =
|
||||||
; stop = pos
|
; stop = pos
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let none = in_file "<none>"
|
||||||
|
|
|
@ -11,3 +11,5 @@ val fail : t -> ('a, unit, string, _) format4 -> 'a
|
||||||
val fail_lex : Lexing.lexbuf -> ('a, unit, string, _) format4 -> 'a
|
val fail_lex : Lexing.lexbuf -> ('a, unit, string, _) format4 -> 'a
|
||||||
|
|
||||||
val in_file : string -> t
|
val in_file : string -> t
|
||||||
|
|
||||||
|
val none : t
|
||||||
|
|
|
@ -2,7 +2,7 @@ open! Import
|
||||||
|
|
||||||
type t = Byte | Native
|
type t = Byte | Native
|
||||||
|
|
||||||
val t : Sexp.t -> t
|
val t : t Sexp.Of_sexp.t
|
||||||
|
|
||||||
val all : t list
|
val all : t list
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,30 @@
|
||||||
open! Import
|
open! Import
|
||||||
|
|
||||||
type t = Sexp.t
|
type t = Sexp.Ast.t
|
||||||
|
|
||||||
let t t = t
|
let t t = t
|
||||||
|
|
||||||
let eval t ~special_values =
|
let eval t ~special_values =
|
||||||
let rec of_sexp : Sexp.t -> _ = function
|
let rec of_sexp : Sexp.Ast.t -> _ = function
|
||||||
| Atom "\\" -> failwith "unexpected \\"
|
| Atom (loc, "\\") -> Loc.fail loc "unexpected \\"
|
||||||
| Atom s ->
|
| Atom (loc, s) ->
|
||||||
let len = String.length s in
|
let len = String.length s in
|
||||||
if len > 0 && s.[0] = ':' then
|
if len > 0 && s.[0] = ':' then
|
||||||
let name = String.sub s ~pos:1 ~len:(len - 1) in
|
let name = String.sub s ~pos:1 ~len:(len - 1) in
|
||||||
match List.assoc name special_values with
|
match List.assoc name special_values with
|
||||||
| l -> l
|
| l -> l
|
||||||
| exception Not_found -> Printf.ksprintf failwith "undefined symbol %s" s;
|
| exception Not_found -> Loc.fail loc "undefined symbol %s" s;
|
||||||
else
|
else
|
||||||
[s]
|
[s]
|
||||||
| List sexps -> of_sexps [] sexps
|
| List (_, sexps) -> of_sexps [] sexps
|
||||||
and of_sexps acc = function
|
and of_sexps acc = function
|
||||||
| Atom "\\" :: sexps -> of_sexps_negative acc sexps
|
| Atom (_, "\\") :: sexps -> of_sexps_negative acc sexps
|
||||||
| elt :: sexps ->
|
| elt :: sexps ->
|
||||||
let elts = of_sexp elt in
|
let elts = of_sexp elt in
|
||||||
of_sexps (List.rev_append elts acc) sexps
|
of_sexps (List.rev_append elts acc) sexps
|
||||||
| [] -> List.rev acc
|
| [] -> List.rev acc
|
||||||
and of_sexps_negative acc = function
|
and of_sexps_negative acc = function
|
||||||
| Atom "\\" :: sexps -> of_sexps_negative acc sexps
|
| Atom (_, "\\") :: sexps -> of_sexps_negative acc sexps
|
||||||
| elt :: sexps ->
|
| elt :: sexps ->
|
||||||
let elts = of_sexp elt in
|
let elts = of_sexp elt in
|
||||||
let acc = List.filter acc ~f:(fun acc_elt -> not (List.mem acc_elt ~set:elts)) in
|
let acc = List.filter acc ~f:(fun acc_elt -> not (List.mem acc_elt ~set:elts)) in
|
||||||
|
@ -34,7 +34,7 @@ let eval t ~special_values =
|
||||||
of_sexp t
|
of_sexp t
|
||||||
|
|
||||||
let is_standard : t -> bool = function
|
let is_standard : t -> bool = function
|
||||||
| Atom ":standard" -> true
|
| Atom (_, ":standard") -> true
|
||||||
| _ -> false
|
| _ -> false
|
||||||
|
|
||||||
let eval_with_standard t ~standard =
|
let eval_with_standard t ~standard =
|
||||||
|
@ -45,17 +45,17 @@ let eval_with_standard t ~standard =
|
||||||
|
|
||||||
let rec map (t : t) ~f =
|
let rec map (t : t) ~f =
|
||||||
match t with
|
match t with
|
||||||
| Atom s ->
|
| Atom (loc, s) ->
|
||||||
let len = String.length s in
|
let len = String.length s in
|
||||||
if len > 0 && s.[0] = ':' then
|
if len > 0 && s.[0] = ':' then
|
||||||
t
|
t
|
||||||
else
|
else
|
||||||
Atom (f s)
|
Atom (loc, f s)
|
||||||
| List l -> List (List.map l ~f:(map ~f))
|
| List (loc, l) -> List (loc, List.map l ~f:(map ~f))
|
||||||
|
|
||||||
let standard : t = Atom ":standard"
|
let standard : t = Atom (Loc.none, ":standard")
|
||||||
|
|
||||||
let append a b = Sexp.List [a; b]
|
let append a b : t = List (Loc.none, [a; b])
|
||||||
|
|
||||||
module Unexpanded = struct
|
module Unexpanded = struct
|
||||||
type nonrec t = t
|
type nonrec t = t
|
||||||
|
@ -67,16 +67,16 @@ module Unexpanded = struct
|
||||||
let files t =
|
let files t =
|
||||||
let rec loop acc : t -> _ = function
|
let rec loop acc : t -> _ = function
|
||||||
| Atom _ -> acc
|
| Atom _ -> acc
|
||||||
| List [Atom ":include"; Atom fn] -> String_set.add fn acc
|
| List (_, [Atom (_, ":include"); Atom (_, fn)]) -> String_set.add fn acc
|
||||||
| List l -> List.fold_left l ~init:acc ~f:loop
|
| List (_, l) -> List.fold_left l ~init:acc ~f:loop
|
||||||
in
|
in
|
||||||
loop String_set.empty t
|
loop String_set.empty t
|
||||||
|
|
||||||
let rec expand (t : t) ~files_contents =
|
let rec expand (t : t) ~files_contents =
|
||||||
match t with
|
match t with
|
||||||
| Atom _ -> t
|
| Atom _ -> t
|
||||||
| List [Atom ":include"; Atom fn] ->
|
| List (_, [Atom (_, ":include"); Atom (_, fn)]) ->
|
||||||
String_map.find_exn fn files_contents ~string_of_key:(sprintf "%S")
|
String_map.find_exn fn files_contents ~string_of_key:(sprintf "%S")
|
||||||
~desc:(fun _ -> "<filename to s-expression>")
|
~desc:(fun _ -> "<filename to s-expression>")
|
||||||
| List l -> List (List.map l ~f:(expand ~files_contents))
|
| List (loc, l) -> List (loc, List.map l ~f:(expand ~files_contents))
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
open Import
|
open Import
|
||||||
|
|
||||||
type t
|
type t
|
||||||
val t : Sexp.t -> t
|
val t : t Sexp.Of_sexp.t
|
||||||
|
|
||||||
val eval_with_standard : t -> standard:string list -> string list
|
val eval_with_standard : t -> standard:string list -> string list
|
||||||
val standard : t
|
val standard : t
|
||||||
|
@ -17,7 +17,7 @@ val map : t -> f:(string -> string) -> t
|
||||||
module Unexpanded : sig
|
module Unexpanded : sig
|
||||||
type expanded = t
|
type expanded = t
|
||||||
type t
|
type t
|
||||||
val t : Sexp.t -> t
|
val t : t Sexp.Of_sexp.t
|
||||||
val standard : t
|
val standard : t
|
||||||
|
|
||||||
val append : t -> t -> t
|
val append : t -> t -> t
|
||||||
|
@ -28,5 +28,5 @@ module Unexpanded : sig
|
||||||
(** Expand [t] using with the given file contents. [file_contents] is a map from
|
(** Expand [t] using with the given file contents. [file_contents] is a map from
|
||||||
filenames to their parsed contents. Every [(:include fn)] in [t] is replaced by
|
filenames to their parsed contents. Every [(:include fn)] in [t] is replaced by
|
||||||
[Map.find files_contents fn]. *)
|
[Map.find files_contents fn]. *)
|
||||||
val expand : t -> files_contents:Sexp.t String_map.t -> expanded
|
val expand : t -> files_contents:Sexp.Ast.t String_map.t -> expanded
|
||||||
end with type expanded := t
|
end with type expanded := t
|
||||||
|
|
147
src/sexp.ml
147
src/sexp.ml
|
@ -4,46 +4,16 @@ type t =
|
||||||
| Atom of string
|
| Atom of string
|
||||||
| List of t list
|
| List of t list
|
||||||
|
|
||||||
type sexp = t
|
module Ast = struct
|
||||||
|
|
||||||
module Locs = struct
|
|
||||||
type t =
|
type t =
|
||||||
| Atom of Loc.t
|
| Atom of Loc.t * string
|
||||||
| List of Loc.t * t list
|
| List of Loc.t * t list
|
||||||
|
|
||||||
let loc = function
|
let loc = function
|
||||||
| Atom loc -> loc
|
| Atom (loc, _) -> loc
|
||||||
| List (loc, _) -> loc
|
| List (loc, _) -> loc
|
||||||
end
|
end
|
||||||
|
|
||||||
let locate_in_list ts ~sub ~locs =
|
|
||||||
let rec loop ts locs =
|
|
||||||
match ts, locs with
|
|
||||||
| [], _ -> None
|
|
||||||
| _, [] -> assert false
|
|
||||||
| t::ts, loc::locs ->
|
|
||||||
if t == sub then
|
|
||||||
Some (Locs.loc loc)
|
|
||||||
else
|
|
||||||
match t, loc with
|
|
||||||
| Atom _, _ -> loop ts locs
|
|
||||||
| List inner_ts, List (_, inner_locs) -> begin
|
|
||||||
match loop inner_ts inner_locs with
|
|
||||||
| None -> loop ts locs
|
|
||||||
| Some _ as res -> res
|
|
||||||
end
|
|
||||||
| _ -> assert false
|
|
||||||
in
|
|
||||||
loop ts locs
|
|
||||||
|
|
||||||
let locate t ~sub ~locs =
|
|
||||||
locate_in_list [t] ~sub ~locs:[locs]
|
|
||||||
|
|
||||||
exception Of_sexp_error of t * string
|
|
||||||
|
|
||||||
let of_sexp_error t msg = raise (Of_sexp_error (t, msg))
|
|
||||||
let of_sexp_errorf t fmt = Printf.ksprintf (of_sexp_error t) fmt
|
|
||||||
|
|
||||||
let must_escape str =
|
let must_escape str =
|
||||||
let len = String.length str in
|
let len = String.length str in
|
||||||
len = 0 ||
|
len = 0 ||
|
||||||
|
@ -97,14 +67,21 @@ module To_sexp = struct
|
||||||
end
|
end
|
||||||
|
|
||||||
module Of_sexp = struct
|
module Of_sexp = struct
|
||||||
type nonrec 'a t = t -> 'a
|
type ast = Ast.t =
|
||||||
|
| Atom of Loc.t * string
|
||||||
|
| List of Loc.t * ast list
|
||||||
|
|
||||||
|
type 'a t = ast -> 'a
|
||||||
|
|
||||||
|
let of_sexp_error sexp str = raise (Loc.Error (Ast.loc sexp, str))
|
||||||
|
let of_sexp_errorf sexp fmt = ksprintf (of_sexp_error sexp) fmt
|
||||||
|
|
||||||
let unit = function
|
let unit = function
|
||||||
| List [] -> ()
|
| List (_, []) -> ()
|
||||||
| sexp -> of_sexp_error sexp "() expected"
|
| sexp -> of_sexp_error sexp "() expected"
|
||||||
|
|
||||||
let string = function
|
let string = function
|
||||||
| Atom s -> s
|
| Atom (_, s) -> s
|
||||||
| List _ as sexp -> of_sexp_error sexp "Atom expected"
|
| List _ as sexp -> of_sexp_error sexp "Atom expected"
|
||||||
|
|
||||||
let int sexp =
|
let int sexp =
|
||||||
|
@ -121,16 +98,16 @@ module Of_sexp = struct
|
||||||
| _ -> of_sexp_error sexp "'true' or 'false' expected"
|
| _ -> of_sexp_error sexp "'true' or 'false' expected"
|
||||||
|
|
||||||
let pair fa fb = function
|
let pair fa fb = function
|
||||||
| List [a; b] -> (fa a, fb b)
|
| List (_, [a; b]) -> (fa a, fb b)
|
||||||
| sexp -> of_sexp_error sexp "S-expression of the form (_ _) expected"
|
| sexp -> of_sexp_error sexp "S-expression of the form (_ _) expected"
|
||||||
|
|
||||||
let list f = function
|
let list f = function
|
||||||
| Atom _ as sexp -> of_sexp_error sexp "List expected"
|
| Atom _ as sexp -> of_sexp_error sexp "List expected"
|
||||||
| List l -> List.map l ~f
|
| List (_, l) -> List.map l ~f
|
||||||
|
|
||||||
let option f = function
|
let option f = function
|
||||||
| List [] -> None
|
| List (_, []) -> None
|
||||||
| List [x] -> Some (f x)
|
| List (_, [x]) -> Some (f x)
|
||||||
| sexp -> of_sexp_error sexp "S-expression of the form () or (_) expected"
|
| sexp -> of_sexp_error sexp "S-expression of the form () or (_) expected"
|
||||||
|
|
||||||
let string_set sexp = String_set.of_list (list string sexp)
|
let string_set sexp = String_set.of_list (list string sexp)
|
||||||
|
@ -141,8 +118,8 @@ module Of_sexp = struct
|
||||||
of_sexp_error sexp (sprintf "key %S present multiple times" key)
|
of_sexp_error sexp (sprintf "key %S present multiple times" key)
|
||||||
|
|
||||||
type unparsed_field =
|
type unparsed_field =
|
||||||
{ value : sexp option
|
{ value : Ast.t option
|
||||||
; entry : sexp
|
; entry : Ast.t
|
||||||
}
|
}
|
||||||
|
|
||||||
module Name_map = Map.Make(struct
|
module Name_map = Map.Make(struct
|
||||||
|
@ -158,7 +135,7 @@ module Of_sexp = struct
|
||||||
end)
|
end)
|
||||||
|
|
||||||
type record_parser_state =
|
type record_parser_state =
|
||||||
{ record : sexp
|
{ loc : Loc.t
|
||||||
; unparsed : unparsed_field Name_map.t
|
; unparsed : unparsed_field Name_map.t
|
||||||
; known : string list
|
; known : string list
|
||||||
}
|
}
|
||||||
|
@ -195,19 +172,19 @@ module Of_sexp = struct
|
||||||
| Some { value = Some value; _ } ->
|
| Some { value = Some value; _ } ->
|
||||||
(value_of_sexp value, consume name state)
|
(value_of_sexp value, consume name state)
|
||||||
| Some { value = None; _ } ->
|
| Some { value = None; _ } ->
|
||||||
of_sexp_error state.record (Printf.sprintf "field %s needs a value" name)
|
Loc.fail state.loc "field %s needs a value" name
|
||||||
| None ->
|
| None ->
|
||||||
match default with
|
match default with
|
||||||
| Some v -> (v, add_known name state)
|
| Some v -> (v, add_known name state)
|
||||||
| None ->
|
| None ->
|
||||||
of_sexp_error state.record (Printf.sprintf "field %s missing" name)
|
Loc.fail state.loc "field %s missing" name
|
||||||
|
|
||||||
let field_o name value_of_sexp state =
|
let field_o name value_of_sexp state =
|
||||||
match Name_map.find name state.unparsed with
|
match Name_map.find name state.unparsed with
|
||||||
| Some { value = Some value; _ } ->
|
| Some { value = Some value; _ } ->
|
||||||
(Some (value_of_sexp value), consume name state)
|
(Some (value_of_sexp value), consume name state)
|
||||||
| Some { value = None; _ } ->
|
| Some { value = None; _ } ->
|
||||||
of_sexp_error state.record (Printf.sprintf "field %s needs a value" name)
|
Loc.fail state.loc "field %s needs a value" name
|
||||||
| None -> (None, add_known name state)
|
| None -> (None, add_known name state)
|
||||||
|
|
||||||
let field_b name state =
|
let field_b name state =
|
||||||
|
@ -222,15 +199,15 @@ module Of_sexp = struct
|
||||||
let make_record_parser_state sexp =
|
let make_record_parser_state sexp =
|
||||||
match sexp with
|
match sexp with
|
||||||
| Atom _ -> of_sexp_error sexp "List expected"
|
| Atom _ -> of_sexp_error sexp "List expected"
|
||||||
| List sexps ->
|
| List (loc, sexps) ->
|
||||||
let unparsed =
|
let unparsed =
|
||||||
List.fold_left sexps ~init:Name_map.empty ~f:(fun acc sexp ->
|
List.fold_left sexps ~init:Name_map.empty ~f:(fun acc sexp ->
|
||||||
match sexp with
|
match sexp with
|
||||||
| List [Atom name] ->
|
| List (_, [Atom (_, name)]) ->
|
||||||
Name_map.add acc ~key:name ~data:{ value = None; entry = sexp }
|
Name_map.add acc ~key:name ~data:{ value = None; entry = sexp }
|
||||||
| List [name_sexp; value] -> begin
|
| List (_, [name_sexp; value]) -> begin
|
||||||
match name_sexp with
|
match name_sexp with
|
||||||
| Atom name ->
|
| Atom (_, name) ->
|
||||||
Name_map.add acc ~key:name ~data:{ value = Some value; entry = sexp }
|
Name_map.add acc ~key:name ~data:{ value = Some value; entry = sexp }
|
||||||
| List _ ->
|
| List _ ->
|
||||||
of_sexp_error name_sexp "Atom expected"
|
of_sexp_error name_sexp "Atom expected"
|
||||||
|
@ -238,7 +215,7 @@ module Of_sexp = struct
|
||||||
| _ ->
|
| _ ->
|
||||||
of_sexp_error sexp "S-expression of the form (_ _) expected")
|
of_sexp_error sexp "S-expression of the form (_ _) expected")
|
||||||
in
|
in
|
||||||
{ record = sexp
|
{ loc = loc
|
||||||
; known = []
|
; known = []
|
||||||
; unparsed
|
; unparsed
|
||||||
}
|
}
|
||||||
|
@ -252,38 +229,48 @@ module Of_sexp = struct
|
||||||
let name, { entry; _ } = Name_map.choose state.unparsed in
|
let name, { entry; _ } = Name_map.choose state.unparsed in
|
||||||
let name_sexp =
|
let name_sexp =
|
||||||
match entry with
|
match entry with
|
||||||
| List (s :: _) -> s
|
| List (_, s :: _) -> s
|
||||||
| _ -> assert false
|
| _ -> assert false
|
||||||
in
|
in
|
||||||
of_sexp_errorf name_sexp
|
of_sexp_errorf name_sexp
|
||||||
"Unknown field %s%s" name (hint name state.known)
|
"Unknown field %s%s" name (hint name state.known)
|
||||||
|
|
||||||
|
type ('a, 'b) rest =
|
||||||
|
| No_rest : ('a, 'a) rest
|
||||||
|
| Many : 'a t -> ('a list -> 'b, 'b) rest
|
||||||
|
|
||||||
module Constructor_args_spec = struct
|
module Constructor_args_spec = struct
|
||||||
type 'a conv = 'a t
|
type 'a conv = 'a t
|
||||||
type ('a, 'b) t =
|
type ('a, 'b) t =
|
||||||
| [] : ('a, 'a) t
|
| [] : ('a, 'a) t
|
||||||
| ( :: ) : 'a conv * ('b, 'c) t -> ('a -> 'b, 'c) t
|
| ( :: ) : 'a conv * ('b, 'c) t -> ('a -> 'b, 'c) t
|
||||||
|
|
||||||
let rec convert : type a b. (a, b) t -> sexp -> sexp list -> a -> b
|
let rec convert : type a b c. (a, b) t -> (b, c) rest -> Ast.t -> Ast.t list -> a -> c
|
||||||
= fun t sexp sexps f ->
|
= fun t rest sexp sexps f ->
|
||||||
match t, sexps with
|
match t, rest, sexps with
|
||||||
| [], [] -> f
|
| [], No_rest, [] -> f
|
||||||
| _ :: _, [] -> of_sexp_error sexp "not enough arguments"
|
| [], Many _ , [] -> f []
|
||||||
| [], _ :: _ -> of_sexp_error sexp "too many arguments"
|
| _ :: _, _, [] -> of_sexp_error sexp "not enough arguments"
|
||||||
| conv :: t, s :: sexps ->
|
| [], No_rest, _ :: _ -> of_sexp_error sexp "too many arguments"
|
||||||
convert t sexp sexps (f (conv s))
|
| [], Many conv, l -> f (List.map l ~f:conv)
|
||||||
|
| conv :: t, _, s :: sexps ->
|
||||||
|
convert t rest sexp sexps (f (conv s))
|
||||||
end
|
end
|
||||||
|
|
||||||
module Constructor_spec = struct
|
module Constructor_spec = struct
|
||||||
type 'a t =
|
type 'a t =
|
||||||
T : { name : string
|
T : { name : string
|
||||||
; args : ('a, 'b) Constructor_args_spec.t
|
; args : ('a, 'b) Constructor_args_spec.t
|
||||||
|
; rest : ('b, 'c) rest
|
||||||
; make : 'a
|
; make : 'a
|
||||||
} -> 'b t
|
} -> 'c t
|
||||||
end
|
end
|
||||||
|
|
||||||
|
let cstr_rest name args rest make =
|
||||||
|
Constructor_spec.T { name; args; make; rest = Many rest }
|
||||||
|
|
||||||
let cstr name args make =
|
let cstr name args make =
|
||||||
Constructor_spec.T { name; args; make }
|
Constructor_spec.T { name; args; make; rest = No_rest }
|
||||||
|
|
||||||
let equal_cstr_name a b =
|
let equal_cstr_name a b =
|
||||||
let alen = String.length a and blen = String.length b in
|
let alen = String.length a and blen = String.length b in
|
||||||
|
@ -321,22 +308,22 @@ module Of_sexp = struct
|
||||||
|
|
||||||
let sum cstrs sexp =
|
let sum cstrs sexp =
|
||||||
match sexp with
|
match sexp with
|
||||||
| Atom s -> begin
|
| Atom (_, s) -> begin
|
||||||
let (Constructor_spec.T c) = find_cstr cstrs sexp s in
|
let (Constructor_spec.T c) = find_cstr cstrs sexp s in
|
||||||
Constructor_args_spec.convert c.args sexp [] c.make
|
Constructor_args_spec.convert c.args c.rest sexp [] c.make
|
||||||
end
|
end
|
||||||
| List [] -> of_sexp_error sexp "non-empty list expected"
|
| List (_, []) -> of_sexp_error sexp "non-empty list expected"
|
||||||
| List (name_sexp :: args) ->
|
| List (_, name_sexp :: args) ->
|
||||||
match name_sexp with
|
match name_sexp with
|
||||||
| List _ -> of_sexp_error name_sexp "Atom expected"
|
| List _ -> of_sexp_error name_sexp "Atom expected"
|
||||||
| Atom s ->
|
| Atom (_, s) ->
|
||||||
let (Constructor_spec.T c) = find_cstr cstrs sexp s in
|
let (Constructor_spec.T c) = find_cstr cstrs sexp s in
|
||||||
Constructor_args_spec.convert c.args sexp args c.make
|
Constructor_args_spec.convert c.args c.rest sexp args c.make
|
||||||
|
|
||||||
let enum cstrs sexp =
|
let enum cstrs sexp =
|
||||||
match sexp with
|
match sexp with
|
||||||
| List _ -> of_sexp_error sexp "Atom expected"
|
| List _ -> of_sexp_error sexp "Atom expected"
|
||||||
| Atom s ->
|
| Atom (_, s) ->
|
||||||
match
|
match
|
||||||
List.find cstrs ~f:(fun (name, _) ->
|
List.find cstrs ~f:(fun (name, _) ->
|
||||||
equal_cstr_name name s)
|
equal_cstr_name name s)
|
||||||
|
@ -350,25 +337,3 @@ module Of_sexp = struct
|
||||||
(List.map cstrs ~f:(fun (name, _) ->
|
(List.map cstrs ~f:(fun (name, _) ->
|
||||||
String.uncapitalize_ascii name)))
|
String.uncapitalize_ascii name)))
|
||||||
end
|
end
|
||||||
(*
|
|
||||||
module Both = struct
|
|
||||||
type sexp = t
|
|
||||||
type 'a t =
|
|
||||||
{ of_sexp : sexp -> 'a
|
|
||||||
; to_sexp : 'a -> sexp
|
|
||||||
}
|
|
||||||
|
|
||||||
module A = Of_sexp
|
|
||||||
module B = To_Sexp
|
|
||||||
|
|
||||||
let string = { of_sexp = A.string; to_sexp = B.string }
|
|
||||||
let int = { of_sexp = A.int; to_sexp = B.int }
|
|
||||||
let pair a b = { of_sexp = A.pair a.of_sexp b.of_sexp
|
|
||||||
; to_sexp =
|
|
||||||
let list f l = List (List.map l ~f)
|
|
||||||
let string_set set = list string (String_set.elements set)
|
|
||||||
let string_map f map = list (pair string f) (String_map.bindings map)
|
|
||||||
end
|
|
||||||
functor (C : Sexp.Combinators) -> struct
|
|
||||||
open C
|
|
||||||
let t = string int int *)
|
|
||||||
|
|
29
src/sexp.mli
29
src/sexp.mli
|
@ -4,23 +4,15 @@ type t =
|
||||||
| Atom of string
|
| Atom of string
|
||||||
| List of t list
|
| List of t list
|
||||||
|
|
||||||
exception Of_sexp_error of t * string
|
module Ast : sig
|
||||||
|
|
||||||
val of_sexp_error : t -> string -> _
|
|
||||||
val of_sexp_errorf : t -> ('a, unit, string, 'b) format4 -> 'a
|
|
||||||
|
|
||||||
val code_error : string -> (string * t) list -> _
|
|
||||||
|
|
||||||
module Locs : sig
|
|
||||||
type t =
|
type t =
|
||||||
| Atom of Loc.t
|
| Atom of Loc.t * string
|
||||||
| List of Loc.t * t list
|
| List of Loc.t * t list
|
||||||
|
|
||||||
val loc : t -> Loc.t
|
val loc : t -> Loc.t
|
||||||
end
|
end
|
||||||
|
|
||||||
val locate : t -> sub:t -> locs:Locs.t -> Loc.t option
|
val code_error : string -> (string * t) list -> _
|
||||||
val locate_in_list : t list -> sub:t -> locs:Locs.t list -> Loc.t option
|
|
||||||
|
|
||||||
val to_string : t -> string
|
val to_string : t -> string
|
||||||
|
|
||||||
|
@ -40,7 +32,14 @@ end
|
||||||
module To_sexp : Combinators with type 'a t = 'a -> t
|
module To_sexp : Combinators with type 'a t = 'a -> t
|
||||||
|
|
||||||
module Of_sexp : sig
|
module Of_sexp : sig
|
||||||
include Combinators with type 'a t = t -> 'a
|
type ast = Ast.t =
|
||||||
|
| Atom of Loc.t * string
|
||||||
|
| List of Loc.t * ast list
|
||||||
|
|
||||||
|
include Combinators with type 'a t = Ast.t -> 'a
|
||||||
|
|
||||||
|
val of_sexp_error : Ast.t -> string -> _
|
||||||
|
val of_sexp_errorf : Ast.t -> ('a, unit, string, 'b) format4 -> 'a
|
||||||
|
|
||||||
(* Record parsing monad *)
|
(* Record parsing monad *)
|
||||||
type 'a record_parser
|
type 'a record_parser
|
||||||
|
@ -67,6 +66,12 @@ module Of_sexp : sig
|
||||||
end with type 'a conv := 'a t
|
end with type 'a conv := 'a t
|
||||||
|
|
||||||
val cstr : string -> ('a, 'b) Constructor_args_spec.t -> 'a -> 'b Constructor_spec.t
|
val cstr : string -> ('a, 'b) Constructor_args_spec.t -> 'a -> 'b Constructor_spec.t
|
||||||
|
val cstr_rest
|
||||||
|
: string
|
||||||
|
-> ('a, 'b list -> 'c) Constructor_args_spec.t
|
||||||
|
-> 'b t
|
||||||
|
-> 'a
|
||||||
|
-> 'c Constructor_spec.t
|
||||||
|
|
||||||
val sum
|
val sum
|
||||||
: 'a Constructor_spec.t list
|
: 'a Constructor_spec.t list
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
val single : Lexing.lexbuf -> Sexp.t * Sexp.Locs.t
|
val single : Lexing.lexbuf -> Sexp.Ast.t
|
||||||
val many : Lexing.lexbuf -> (Sexp.t * Sexp.Locs.t) list
|
val many : Lexing.lexbuf -> Sexp.Ast.t list
|
||||||
|
|
|
@ -2,32 +2,30 @@
|
||||||
type stack =
|
type stack =
|
||||||
| Empty
|
| Empty
|
||||||
| Open of Lexing.position * stack
|
| Open of Lexing.position * stack
|
||||||
| Sexp of Sexp.t * Sexp.Locs.t * stack
|
| Sexp of Sexp.Ast.t * stack
|
||||||
|
|
||||||
let error = Loc.fail_lex
|
let error = Loc.fail_lex
|
||||||
|
|
||||||
let make_list =
|
let make_list =
|
||||||
let rec loop lexbuf acc acc_locs = function
|
let rec loop lexbuf acc = function
|
||||||
| Empty ->
|
| Empty ->
|
||||||
error lexbuf "right parenthesis without matching left parenthesis"
|
error lexbuf "right parenthesis without matching left parenthesis"
|
||||||
| Open (start, stack) ->
|
| Open (start, stack) ->
|
||||||
Sexp (List acc,
|
Sexp (List ({ start; stop = Lexing.lexeme_end_p lexbuf }, acc),
|
||||||
List ({ start; stop = Lexing.lexeme_end_p lexbuf }, acc_locs),
|
|
||||||
stack)
|
stack)
|
||||||
| Sexp (sexp, locs, stack) -> loop lexbuf (sexp :: acc) (locs :: acc_locs) stack
|
| Sexp (sexp, stack) -> loop lexbuf (sexp :: acc) stack
|
||||||
in
|
in
|
||||||
fun lexbuf stack -> loop lexbuf [] [] stack
|
fun lexbuf stack -> loop lexbuf [] stack
|
||||||
|
|
||||||
let new_sexp loop stack lexbuf =
|
let new_sexp loop stack lexbuf =
|
||||||
match stack with
|
match stack with
|
||||||
| Sexp (sexp, locs, Empty) -> Some (sexp, locs)
|
| Sexp (sexp, Empty) -> Some sexp
|
||||||
| _ -> loop stack lexbuf
|
| _ -> loop stack lexbuf
|
||||||
|
|
||||||
let atom_loc lexbuf : Sexp.Locs.t =
|
let atom_loc lexbuf : Loc.t =
|
||||||
Atom
|
{ start = Lexing.lexeme_start_p lexbuf
|
||||||
{ start = Lexing.lexeme_start_p lexbuf
|
; stop = Lexing.lexeme_end_p lexbuf
|
||||||
; stop = Lexing.lexeme_end_p lexbuf
|
}
|
||||||
}
|
|
||||||
|
|
||||||
let char_for_backslash = function
|
let char_for_backslash = function
|
||||||
| 'n' -> '\010'
|
| 'n' -> '\010'
|
||||||
|
@ -81,7 +79,7 @@ rule main stack = parse
|
||||||
| "#|"
|
| "#|"
|
||||||
{ block_comment 0 stack lexbuf }
|
{ block_comment 0 stack lexbuf }
|
||||||
| unquoted* as s
|
| unquoted* as s
|
||||||
{ new_sexp main (Sexp (Atom s, atom_loc lexbuf, stack)) lexbuf }
|
{ new_sexp main (Sexp (Atom (atom_loc lexbuf, s), stack)) lexbuf }
|
||||||
| eof
|
| eof
|
||||||
{ match stack with
|
{ match stack with
|
||||||
| Empty -> None
|
| Empty -> None
|
||||||
|
@ -105,8 +103,8 @@ and block_comment depth stack = parse
|
||||||
and scan_string buf start stack = parse
|
and scan_string buf start stack = parse
|
||||||
| '"'
|
| '"'
|
||||||
{ new_sexp main
|
{ new_sexp main
|
||||||
(Sexp (Atom (Buffer.contents buf),
|
(Sexp (Atom ({ start; stop = Lexing.lexeme_end_p lexbuf },
|
||||||
Atom { start; stop = Lexing.lexeme_end_p lexbuf },
|
Buffer.contents buf),
|
||||||
stack))
|
stack))
|
||||||
lexbuf
|
lexbuf
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,30 +1,7 @@
|
||||||
open Import
|
open Import
|
||||||
|
|
||||||
let single fn f =
|
let single fn =
|
||||||
let sexp, locs =
|
with_lexbuf_from_file fn ~f:Sexp_lexer.single
|
||||||
with_lexbuf_from_file fn ~f:Sexp_lexer.single
|
|
||||||
in
|
|
||||||
try
|
|
||||||
f sexp
|
|
||||||
with Sexp.Of_sexp_error (sub, msg) ->
|
|
||||||
let loc =
|
|
||||||
match Sexp.locate sexp ~sub ~locs with
|
|
||||||
| None -> Loc.in_file fn
|
|
||||||
| Some loc -> loc
|
|
||||||
in
|
|
||||||
Loc.fail loc "%s" msg
|
|
||||||
|
|
||||||
let many fn f =
|
let many fn =
|
||||||
let sexps, locs =
|
with_lexbuf_from_file fn ~f:Sexp_lexer.many
|
||||||
with_lexbuf_from_file fn ~f:Sexp_lexer.many
|
|
||||||
|> List.split
|
|
||||||
in
|
|
||||||
try
|
|
||||||
f sexps
|
|
||||||
with Sexp.Of_sexp_error (sub, msg) ->
|
|
||||||
let loc =
|
|
||||||
match Sexp.locate_in_list sexps ~sub ~locs with
|
|
||||||
| None -> Loc.in_file fn
|
|
||||||
| Some loc -> loc
|
|
||||||
in
|
|
||||||
Loc.fail loc "%s" msg
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
open! Import
|
open! Import
|
||||||
|
|
||||||
val single : string -> (Sexp.t -> 'a) -> 'a
|
val single : string -> Sexp.Ast.t
|
||||||
val many : string -> (Sexp.t list -> 'a) -> 'a
|
val many : string -> Sexp.Ast.t list
|
||||||
|
|
|
@ -91,7 +91,7 @@ let expand t ~f =
|
||||||
|
|
||||||
module type Container = sig
|
module type Container = sig
|
||||||
type 'a t
|
type 'a t
|
||||||
val t : (Sexp.t -> 'a) -> Sexp.t -> 'a t
|
val t : 'a Sexp.Of_sexp.t -> 'a t Sexp.Of_sexp.t
|
||||||
val sexp_of_t : ('a -> Sexp.t) -> 'a t -> Sexp.t
|
val sexp_of_t : ('a -> Sexp.t) -> 'a t -> Sexp.t
|
||||||
|
|
||||||
val map : 'a t -> f:('a -> 'b) -> 'b t
|
val map : 'a t -> f:('a -> 'b) -> 'b t
|
||||||
|
|
|
@ -6,7 +6,7 @@
|
||||||
open Import
|
open Import
|
||||||
|
|
||||||
type t
|
type t
|
||||||
val t : Sexp.t -> t
|
val t : t Sexp.Of_sexp.t
|
||||||
val sexp_of_t : t -> Sexp.t
|
val sexp_of_t : t -> Sexp.t
|
||||||
|
|
||||||
val of_string : string -> t
|
val of_string : string -> t
|
||||||
|
@ -19,7 +19,7 @@ val expand : t -> f:(string -> string option) -> string
|
||||||
|
|
||||||
module type Container = sig
|
module type Container = sig
|
||||||
type 'a t
|
type 'a t
|
||||||
val t : (Sexp.t -> 'a) -> Sexp.t -> 'a t
|
val t : 'a Sexp.Of_sexp.t -> 'a t Sexp.Of_sexp.t
|
||||||
val sexp_of_t : ('a -> Sexp.t) -> 'a t -> Sexp.t
|
val sexp_of_t : ('a -> Sexp.t) -> 'a t -> Sexp.t
|
||||||
|
|
||||||
val map : 'a t -> f:('a -> 'b) -> 'b t
|
val map : 'a t -> f:('a -> 'b) -> 'b t
|
||||||
|
@ -28,7 +28,7 @@ end
|
||||||
|
|
||||||
module Lift(M : Container) : sig
|
module Lift(M : Container) : sig
|
||||||
type nonrec t = t M.t
|
type nonrec t = t M.t
|
||||||
val t : Sexp.t -> t
|
val t : t Sexp.Of_sexp.t
|
||||||
|
|
||||||
val sexp_of_t : t -> Sexp.t
|
val sexp_of_t : t -> Sexp.t
|
||||||
|
|
||||||
|
|
|
@ -45,7 +45,7 @@ let eq (type a) (type b)
|
||||||
module Make_full
|
module Make_full
|
||||||
(T : sig type t end)
|
(T : sig type t end)
|
||||||
(To_sexp : sig val t : T.t -> Sexp.t end)
|
(To_sexp : sig val t : T.t -> Sexp.t end)
|
||||||
(Of_sexp : sig val t : Sexp.t -> T.t end)
|
(Of_sexp : sig val t : Sexp.Ast.t -> T.t end)
|
||||||
: S with type t = T.t =
|
: S with type t = T.t =
|
||||||
struct
|
struct
|
||||||
type t = T.t
|
type t = T.t
|
||||||
|
@ -59,10 +59,7 @@ struct
|
||||||
close_out oc
|
close_out oc
|
||||||
|
|
||||||
let load ~filename =
|
let load ~filename =
|
||||||
let sexp, _locs =
|
Of_sexp.t (Sexp_load.single filename)
|
||||||
with_lexbuf_from_file filename ~f:Sexp_lexer.single
|
|
||||||
in
|
|
||||||
Of_sexp.t sexp
|
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -27,5 +27,5 @@ module Make
|
||||||
module Make_full
|
module Make_full
|
||||||
(T : sig type t end)
|
(T : sig type t end)
|
||||||
(To_sexp : sig val t : T.t -> Sexp.t end)
|
(To_sexp : sig val t : T.t -> Sexp.t end)
|
||||||
(Of_sexp : sig val t : Sexp.t -> T.t end)
|
(Of_sexp : sig val t : Sexp.Ast.t -> T.t end)
|
||||||
: S with type t = T.t
|
: S with type t = T.t
|
||||||
|
|
|
@ -1,10 +1,6 @@
|
||||||
open Import
|
open Import
|
||||||
open Sexp.Of_sexp
|
open Sexp.Of_sexp
|
||||||
|
|
||||||
type sexp = Sexp.t = Atom of string | List of sexp list
|
|
||||||
let of_sexp_error = Sexp.of_sexp_error
|
|
||||||
let of_sexp_errorf = Sexp.of_sexp_errorf
|
|
||||||
|
|
||||||
module Context = struct
|
module Context = struct
|
||||||
module Opam = struct
|
module Opam = struct
|
||||||
type t =
|
type t =
|
||||||
|
@ -27,7 +23,7 @@ module Context = struct
|
||||||
type t = Default | Opam of Opam.t
|
type t = Default | Opam of Opam.t
|
||||||
|
|
||||||
let t = function
|
let t = function
|
||||||
| Atom "default" -> Default
|
| Atom (_, "default") -> Default
|
||||||
| sexp -> Opam (Opam.t sexp)
|
| sexp -> Opam (Opam.t sexp)
|
||||||
|
|
||||||
let name = function
|
let name = function
|
||||||
|
@ -55,4 +51,4 @@ let t sexps =
|
||||||
ctx :: acc)
|
ctx :: acc)
|
||||||
|> List.rev
|
|> List.rev
|
||||||
|
|
||||||
let load fn = Sexp_load.many fn t
|
let load fn = t (Sexp_load.many fn)
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
(** Workspaces definitions *)
|
||||||
|
|
||||||
|
open! Import
|
||||||
|
|
||||||
|
module Context : sig
|
||||||
|
module Opam : sig
|
||||||
|
type t =
|
||||||
|
{ name : string
|
||||||
|
; switch : string
|
||||||
|
; root : string option
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
type t = Default | Opam of Opam.t
|
||||||
|
end
|
||||||
|
|
||||||
|
type t = Context.t list
|
||||||
|
|
||||||
|
val load : string -> t
|
Loading…
Reference in New Issue