5
bluestorm <bluestorm.dylc@gmail.com>
7
This program is free software: you can redistribute it and/or
8
modify it under the terms of the GNU Library General Public
9
License as published by the Free Software Foundation, either
10
version 2 of the License, or (at your option) any later version,
11
with the special exception on linking described in the file
14
This program is distributed in the hope that it will be useful,
15
but WITHOUT ANY WARRANTY; without even the implied warranty of
16
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17
GNU Library General Public License (file LICENSE) for more details.
20
Introduce a "where" keyword for backward declarations.
23
<something> where <declaration> ==> <declaration> (sep) <something>
24
Supported forms : where let, where val
26
expr where let a = b ==> let a = b in expr
27
expr where let rec a = b ==> let rec a = b in expr
28
str_item where val a = b ==> let a = b ;; str_item
30
Default case : as "where let" is the more common form,
31
the "let" is optional and you can use "where" alone :
32
expr where a = b ==> let a = b in expr
34
Associativity : a where b where c ==> (a where b) where c
35
Precedence : let a = b where c and d ==> let a = (b where c and d)
54
ocamlfind ocamlc -syntax camlp4o -package camlp4.extend,camlp4.quotations -c pa_where.ml
55
Ocamlfind installation :
56
ocamlfind install pa_where META pa_where.cmo pa_where.ml test.ml
58
ocamlfind ocamlc -syntax camlp4o -package pa_where.syntax ....
67
let description = "'where' backward declarations"
70
module Make (Syntax : Sig.Camlp4Syntax) = struct
73
let test_where_let = Gram.Entry.of_parser "test_where_let"
74
(* we don't ask for the 2-deep npeek directly because, in the
75
toplevel, it would hang and wait for two more tokens (wich is
76
problematic if the first token was ";;" and the user is waiting
77
for feedback). We only ask for the second token if the first is
80
match Stream.peek strm with
81
| Some (KEYWORD "where", _) ->
82
(match Stream.npeek 2 strm with
83
| [ (KEYWORD "where", _); (KEYWORD ("let" | "rec"), _) ] -> ()
84
| [ (KEYWORD "where", _); (KEYWORD _, _) ] -> raise Stream.Failure
85
| [ (KEYWORD "where", _); _ ] -> ()
86
| _ -> raise Stream.Failure)
87
| _ -> raise Stream.Failure)
91
GLOBAL: expr str_item;
93
str_item: BEFORE "top"
95
[ e = str_item; "where"; "val";
96
rf = opt_rec; lb = top_where_binding ->
97
<:str_item< value $rec:rf$ $lb$ ; $e$ >>
100
(* the test_where_let is necessary because of the dangling
103
let a = b where val b = 2 *)
106
[ e = expr; test_where_let; "where"; OPT "let";
107
rf = opt_rec; lb = where_binding ->
108
<:expr< let $rec:rf$ $lb$ in $e$ >>
113
[ b1 = SELF; "and"; b2 = SELF -> <:binding< $b1$ and $b2$ >>
114
| p = ipatt; e = fun_binding -> <:binding< $p$ = $e$ >> ] ];
118
[ b1 = SELF; "and"; b2 = SELF -> <:binding< $b1$ and $b2$ >>
119
| p = ipatt; e = fun_binding' -> <:binding< $p$ = $e$ >> ] ];
121
(* fun_binding' is needed for associativity issues :
122
(a where b where c) parses as ((a where b) where c)
123
with fun_binding' and (a where (b where c)) with fun_binding.
125
The first form was choosen as standard.
126
Rationale : it more natural to have an aligned indentation,
127
wich suggest the first choice :
134
[ p = labeled_ipatt; e = SELF ->
135
<:expr< fun $p$ -> $e$ >>
136
| "="; e = expr LEVEL "top" -> <:expr< $e$ >>
137
| ":"; t = ctyp; "="; e = expr LEVEL "top" -> <:expr< ($e$ : $t$) >>
138
| ":>"; t = ctyp; "="; e = expr LEVEL "top" -> <:expr< ($e$ :> $t$) >> ] ];
143
let module M = Register.OCamlSyntaxExtension(Id)(Make) in ()