$`int:stop_line$, $`int:stop_bol$, $`int:stop_off$,
$`bool:ghost$) >>
+(* Convert 'expr option' to an expression that contains the option inside. *)
+let expr_of_option _loc = function
+ | None -> <:expr< None >>
+ | Some e -> <:expr< Some $e$ >>
+
(* "Lift" an expression, turning it from an expression into an OCaml
* abstract syntax tree in the output. This is pretty obscure.
* http://caml.inria.fr/pub/ml-archives/caml-list/2008/09/591f7c4a8df9295d675a5adcb6802748.en.html
let lift_expr = M.Expr.meta_expr
(* Handle a top level statement. *)
-let rec call_stmt name (_loc, stmt, sh) =
- let name = if name <> "" then name else unique_job_name () in
- let name = <:expr< $str:name$ >> in
+let rec call_stmt ?name ?pre ?post (_loc, stmt, sh) =
+ let name =
+ match name with
+ | None -> let name = unique_job_name () in <:expr< $str:name$ >>
+ | Some name -> name in
+ let pre = expr_of_option _loc pre in
+ let post = expr_of_option _loc post in
match stmt with
- | `When e -> when_stmt _loc name e sh
- | `Every p -> every_stmt _loc name p sh
+ | `When e -> when_stmt _loc name pre post e sh
+ | `Every p -> every_stmt _loc name pre post p sh
(* Handle a top level "when" statement.
* e -> when expression
* Returns a top level statement (str_item) which when executed just
* adds the statement to a global list.
*)
-and when_stmt _loc name e sh =
+and when_stmt _loc name pre post e sh =
let loc = expr_of_loc _loc _loc in
let e = lift_expr _loc e in
<:str_item<
open Camlp4.PreCast
- Whenfile.add_when_job $loc$ $name$ $e$ $sh$
+ Whenfile.add_when_job $loc$ $name$ $pre$ $post$ $e$ $sh$
>>
(* Handle a top level "every" statement. *)
-and every_stmt _loc name period sh =
+and every_stmt _loc name pre post period sh =
let loc = expr_of_loc _loc _loc in
<:str_item<
open Camlp4.PreCast
- Whenfile.add_every_job $loc$ $name$ $period$ $sh$
+ Whenfile.add_every_job $loc$ $name$ $pre$ $post$ $period$ $sh$
>>
let () =
)
| _ -> raise Stream.Failure
)
-
-(*
-(* This hand-written parser looks for "job <name>" before a statement. *)
-let optjob =
- Gram.Entry.of_parser "optjob"
- (fun stream ->
- let info, name =
- match Stream.npeek 2 stream with
- | [ LIDENT "job", info; STRING (_,name), _ ] ->
- Stream.junk stream;
- Stream.junk stream;
- info, name
- | (_, info) :: _ ->
- (* Job is unnamed so generate a unique internal name. *)
- info, unique_job_name ()
- | _ -> assert false in
- let _loc = Gram.token_location info in
- <:expr< $str:name$ >>
- )
-*)
;;
EXTEND Gram
| [ e = period_parser -> e ]
];
+ (* Pre and post functions. *)
+ pre: [[ "pre"; f = expr -> f ]];
+ post: [[ "post"; f = expr -> f ]];
+
(* Top level statements. *)
statement: [
[ "when"; e = expr; ":"; sh = expr ->
(* "str_item" is a top level statement in an OCaml program. *)
str_item: LEVEL "top" [
- [ s = statement -> call_stmt "" s ]
- | [ "job"; name = STRING; s = statement -> call_stmt name s ]
+ [ s = statement -> call_stmt s ]
+ | [ "job"; name = expr;
+ pre = OPT pre;
+ post = OPT post;
+ s = statement ->
+ call_stmt ~name ?pre ?post s ]
];
END