2019-05-12 19:31:22 +02:00
|
|
|
%{
|
|
|
|
(* START HEADER *)
|
|
|
|
|
2019-09-27 13:33:25 +00:00
|
|
|
[@@@warning "-42"]
|
2019-05-12 19:31:22 +02:00
|
|
|
|
2019-09-27 13:33:25 +00:00
|
|
|
open Region
|
|
|
|
open AST
|
2019-05-22 19:38:09 +02:00
|
|
|
|
2019-05-12 19:31:22 +02:00
|
|
|
(* END HEADER *)
|
|
|
|
%}
|
|
|
|
|
2019-09-27 13:33:25 +00:00
|
|
|
(* See [ParToken.mly] for the definition of tokens. *)
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
(* Entry points *)
|
|
|
|
|
2019-09-27 13:33:25 +00:00
|
|
|
%start contract interactive_expr
|
|
|
|
%type <AST.t> contract
|
2019-06-03 17:43:25 +02:00
|
|
|
%type <AST.expr> interactive_expr
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
%%
|
|
|
|
|
|
|
|
(* RULES *)
|
|
|
|
|
|
|
|
(* The rule [sep_or_term(item,sep)] ("separated or terminated list")
|
|
|
|
parses a non-empty list of items separated by [sep], and optionally
|
|
|
|
terminated by [sep]. *)
|
|
|
|
|
|
|
|
sep_or_term_list(item,sep):
|
|
|
|
nsepseq(item,sep) {
|
|
|
|
$1, None
|
|
|
|
}
|
|
|
|
| nseq(item sep {$1,$2}) {
|
|
|
|
let (first,sep), tail = $1 in
|
|
|
|
let rec trans (seq, prev_sep as acc) = function
|
|
|
|
[] -> acc
|
|
|
|
| (item,next_sep)::others ->
|
|
|
|
trans ((prev_sep,item)::seq, next_sep) others in
|
|
|
|
let list, term = trans ([],sep) tail
|
|
|
|
in (first, List.rev list), Some term }
|
|
|
|
|
|
|
|
(* Compound constructs *)
|
|
|
|
|
2019-09-27 13:33:25 +00:00
|
|
|
par(X):
|
|
|
|
LPAR X RPAR {
|
|
|
|
let region = cover $1 $3
|
|
|
|
and value = {
|
|
|
|
lpar = $1;
|
|
|
|
inside = $2;
|
|
|
|
rpar = $3}
|
|
|
|
in {region; value}
|
|
|
|
}
|
|
|
|
|
|
|
|
brackets(X):
|
|
|
|
LBRACKET X RBRACKET {
|
|
|
|
let region = cover $1 $3
|
|
|
|
and value = {
|
|
|
|
lbracket = $1;
|
|
|
|
inside = $2;
|
|
|
|
rbracket = $3}
|
|
|
|
in {region; value}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
(* Sequences
|
|
|
|
|
|
|
|
Series of instances of the same syntactical category have often to
|
|
|
|
be parsed, like lists of expressions, patterns etc. The simplest of
|
|
|
|
all is the possibly empty sequence (series), parsed below by
|
|
|
|
[seq]. The non-empty sequence is parsed by [nseq]. Note that the
|
|
|
|
latter returns a pair made of the first parsed item (the parameter
|
|
|
|
[X]) and the rest of the sequence (possibly empty). This way, the
|
|
|
|
OCaml typechecker can keep track of this information along the
|
|
|
|
static control-flow graph. The rule [sepseq] parses possibly empty
|
|
|
|
sequences of items separated by some token (e.g., a comma), and
|
|
|
|
rule [nsepseq] is for non-empty such sequences. See module [Utils]
|
|
|
|
for the types corresponding to the semantic actions of those
|
|
|
|
rules.
|
|
|
|
*)
|
|
|
|
|
|
|
|
(* Possibly empty sequence of items *)
|
|
|
|
|
|
|
|
seq(item):
|
|
|
|
(**) { [] }
|
|
|
|
| item seq(item) { $1::$2 }
|
|
|
|
|
|
|
|
(* Non-empty sequence of items *)
|
|
|
|
|
|
|
|
nseq(item):
|
|
|
|
item seq(item) { $1,$2 }
|
|
|
|
|
|
|
|
(* Non-empty separated sequence of items *)
|
|
|
|
|
|
|
|
nsepseq(item,sep):
|
|
|
|
item { $1, [] }
|
|
|
|
| item sep nsepseq(item,sep) { let h,t = $3 in $1, ($2,h)::t }
|
|
|
|
|
|
|
|
(* Possibly empy separated sequence of items *)
|
|
|
|
|
|
|
|
sepseq(item,sep):
|
|
|
|
(**) { None }
|
|
|
|
| nsepseq(item,sep) { Some $1 }
|
|
|
|
|
|
|
|
(* Helpers *)
|
|
|
|
|
2019-09-27 13:33:25 +00:00
|
|
|
%inline type_name : Ident { $1 }
|
|
|
|
%inline field_name : Ident { $1 }
|
|
|
|
%inline module_name : Constr { $1 }
|
|
|
|
%inline struct_name : Ident { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
(* Non-empty comma-separated values (at least two values) *)
|
|
|
|
|
|
|
|
tuple(item):
|
2019-09-27 13:33:25 +00:00
|
|
|
item COMMA nsepseq(item,COMMA) {
|
|
|
|
let h,t = $3 in $1,($2,h)::t
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
(* Possibly empty semicolon-separated values between brackets *)
|
|
|
|
|
2019-07-24 14:34:26 +02:00
|
|
|
list(item):
|
2019-09-27 13:33:25 +00:00
|
|
|
LBRACKET sep_or_term_list(item,SEMI) RBRACKET {
|
|
|
|
let elements, terminator = $2 in
|
|
|
|
{ value =
|
|
|
|
{
|
|
|
|
opening = LBracket $1;
|
|
|
|
elements = Some elements;
|
|
|
|
terminator;
|
|
|
|
closing = RBracket $3
|
|
|
|
};
|
|
|
|
region = cover $1 $3
|
|
|
|
}
|
|
|
|
}
|
|
|
|
| LBRACKET RBRACKET {
|
|
|
|
{ value =
|
|
|
|
{
|
|
|
|
opening = LBracket $1;
|
|
|
|
elements = None;
|
|
|
|
terminator = None;
|
|
|
|
closing = RBracket $2
|
|
|
|
};
|
|
|
|
region = cover $1 $2
|
|
|
|
}
|
2019-06-10 15:19:42 +02:00
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
(* Main *)
|
|
|
|
|
2019-09-27 13:33:25 +00:00
|
|
|
contract:
|
|
|
|
declarations EOF { {decl = Utils.nseq_rev $1; eof=$2} }
|
2019-05-22 19:38:09 +02:00
|
|
|
|
|
|
|
declarations:
|
|
|
|
declaration { $1 }
|
2019-05-24 19:31:39 +02:00
|
|
|
| declaration declarations { Utils.(nseq_foldl (swap nseq_cons) $2 $1)}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
declaration:
|
2019-09-27 13:33:25 +00:00
|
|
|
LetEntry entry_binding {
|
|
|
|
let start = $1 in
|
|
|
|
let stop = expr_to_region $2.let_rhs in
|
|
|
|
let region = cover start stop in
|
|
|
|
LetEntry { value = ($1, $2); region}, []
|
|
|
|
}
|
|
|
|
| type_decl { TypeDecl $1, [] }
|
|
|
|
| let_declaration { Let $1, [] }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
(* Type declarations *)
|
|
|
|
|
|
|
|
type_decl:
|
2019-09-27 13:33:25 +00:00
|
|
|
Type type_name EQ type_expr {
|
|
|
|
let region = cover $1 (type_expr_to_region $4) in
|
|
|
|
let value = {
|
|
|
|
kwd_type = $1;
|
|
|
|
name = $2;
|
|
|
|
eq = $3;
|
|
|
|
type_expr = $4;
|
|
|
|
}
|
|
|
|
in {region; value}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
type_expr:
|
|
|
|
cartesian { TProd $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| sum_type { TSum $1 }
|
|
|
|
| record_type { TRecord $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
cartesian:
|
2019-09-27 13:33:25 +00:00
|
|
|
nsepseq(fun_type, TIMES) {
|
|
|
|
let region = nsepseq_to_region type_expr_to_region $1
|
|
|
|
in {region; value=$1}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
fun_type:
|
2019-09-27 13:33:25 +00:00
|
|
|
core_type {
|
|
|
|
$1
|
|
|
|
}
|
|
|
|
| core_type ARROW fun_type {
|
|
|
|
let region = cover (type_expr_to_region $1)
|
|
|
|
(type_expr_to_region $3)
|
|
|
|
in
|
|
|
|
TFun {region; value = ($1, $2, $3)}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
core_type:
|
2019-09-27 13:33:25 +00:00
|
|
|
type_name {
|
2019-05-13 17:35:31 +02:00
|
|
|
TAlias $1
|
2019-05-12 19:31:22 +02:00
|
|
|
}
|
2019-09-27 13:33:25 +00:00
|
|
|
| module_name DOT type_name {
|
|
|
|
let module_name = $1.value in
|
|
|
|
let type_name = $3.value in
|
|
|
|
let value = module_name ^ "." ^ type_name in
|
|
|
|
let region = cover $1.region $3.region
|
|
|
|
in
|
|
|
|
TAlias {region; value}
|
|
|
|
}
|
|
|
|
| core_type type_constr {
|
|
|
|
let arg_val = $1 in
|
|
|
|
let constr = $2 in
|
|
|
|
let start = type_expr_to_region $1 in
|
|
|
|
let stop = $2.region in
|
|
|
|
let region = cover start stop in
|
2019-05-24 19:31:39 +02:00
|
|
|
let lpar, rpar = ghost, ghost in
|
2019-05-22 19:38:09 +02:00
|
|
|
let value = {lpar; inside=arg_val,[]; rpar} in
|
2019-09-27 13:33:25 +00:00
|
|
|
let arg = {value; region = start} in
|
|
|
|
TApp Region.{value = constr, arg; region}
|
2019-05-12 19:31:22 +02:00
|
|
|
}
|
2019-09-27 13:33:25 +00:00
|
|
|
| type_tuple type_constr {
|
|
|
|
let total = cover $1.region $2.region in
|
|
|
|
TApp {region=total; value = $2, $1 }
|
|
|
|
}
|
|
|
|
| par(cartesian) {
|
|
|
|
let Region.{value={inside=prod; _}; _} = $1 in
|
|
|
|
TPar {$1 with value={$1.value with inside = TProd prod}} }
|
2019-05-13 17:35:31 +02:00
|
|
|
|
2019-05-12 19:31:22 +02:00
|
|
|
type_constr:
|
2019-05-13 17:35:31 +02:00
|
|
|
type_name { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
type_tuple:
|
|
|
|
par(tuple(type_expr)) { $1 }
|
|
|
|
|
|
|
|
sum_type:
|
2019-09-27 13:33:25 +00:00
|
|
|
ioption(VBAR) nsepseq(variant,VBAR) {
|
|
|
|
let region = nsepseq_to_region (fun x -> x.region) $2
|
|
|
|
in {region; value = $2}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
variant:
|
2019-09-27 13:33:25 +00:00
|
|
|
Constr Of cartesian {
|
|
|
|
let region = cover $1.region $3.region
|
|
|
|
and value = {constr = $1; args = Some ($2, $3)}
|
|
|
|
in {region; value}
|
|
|
|
}
|
|
|
|
| Constr {
|
|
|
|
{region=$1.region; value= {constr=$1; args=None}} }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
record_type:
|
2019-09-27 13:33:25 +00:00
|
|
|
LBRACE sep_or_term_list(field_decl,SEMI) RBRACE {
|
|
|
|
let elements, terminator = $2 in
|
|
|
|
let region = cover $1 $3
|
|
|
|
and value = {
|
|
|
|
opening = LBrace $1;
|
|
|
|
elements = Some elements;
|
|
|
|
terminator;
|
|
|
|
closing = RBrace $3}
|
|
|
|
in {region; value}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
field_decl:
|
2019-09-27 13:33:25 +00:00
|
|
|
field_name COLON type_expr {
|
|
|
|
let stop = type_expr_to_region $3 in
|
|
|
|
let region = cover $1.region stop
|
|
|
|
and value = {field_name = $1; colon = $2; field_type = $3}
|
|
|
|
in {region; value}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
2019-05-22 19:38:09 +02:00
|
|
|
(* Entry points *)
|
|
|
|
|
|
|
|
entry_binding:
|
2019-09-27 13:33:25 +00:00
|
|
|
Ident nseq(sub_irrefutable) type_annotation? EQ expr {
|
2019-06-01 08:37:43 +00:00
|
|
|
let let_rhs = $5 in
|
2019-06-01 11:29:31 +00:00
|
|
|
let pattern = PVar $1 in
|
|
|
|
let (hd , tl) = $2 in
|
|
|
|
{bindings = pattern :: hd :: tl; lhs_type=$3; eq=$4; let_rhs}
|
2019-05-22 19:38:09 +02:00
|
|
|
}
|
2019-09-27 13:33:25 +00:00
|
|
|
| Ident type_annotation? EQ fun_expr(expr) {
|
2019-06-03 17:43:25 +02:00
|
|
|
let pattern = PVar $1 in
|
2019-06-01 11:29:31 +00:00
|
|
|
{bindings = [pattern]; lhs_type=$2; eq=$3; let_rhs=$4} }
|
2019-05-22 19:38:09 +02:00
|
|
|
|
|
|
|
(* Top-level non-recursive definitions *)
|
|
|
|
|
|
|
|
let_declaration:
|
2019-09-27 13:33:25 +00:00
|
|
|
Let let_binding {
|
|
|
|
let kwd_let = $1 in
|
|
|
|
let binding, region = $2 in
|
|
|
|
{value = kwd_let, binding; region}
|
2019-05-22 19:38:09 +02:00
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
let_binding:
|
2019-09-27 13:33:25 +00:00
|
|
|
Ident nseq(sub_irrefutable) type_annotation? EQ expr {
|
2019-06-01 08:37:43 +00:00
|
|
|
let let_rhs = $5 in
|
2019-06-01 11:29:31 +00:00
|
|
|
let ident_pattern = PVar $1 in
|
|
|
|
let (hd , tl) = $2 in
|
2019-09-27 13:33:25 +00:00
|
|
|
let start = $1.region in
|
|
|
|
let stop = expr_to_region $5 in
|
|
|
|
let region = cover start stop in
|
|
|
|
({bindings= (ident_pattern :: hd :: tl); lhs_type=$3; eq=$4; let_rhs}, region)
|
2019-05-22 19:38:09 +02:00
|
|
|
}
|
2019-09-27 13:33:25 +00:00
|
|
|
| irrefutable type_annotation? EQ expr {
|
2019-06-01 11:29:31 +00:00
|
|
|
let pattern = $1 in
|
2019-09-27 13:33:25 +00:00
|
|
|
let start = pattern_to_region $1 in
|
|
|
|
let stop = expr_to_region $4 in
|
|
|
|
let region = cover start stop in
|
|
|
|
({bindings = [pattern]; lhs_type=$2; eq=$3; let_rhs=$4}, region)
|
2019-05-12 19:31:22 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type_annotation:
|
2019-09-27 13:33:25 +00:00
|
|
|
COLON type_expr { $1,$2 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
(* Patterns *)
|
|
|
|
|
|
|
|
irrefutable:
|
2019-09-27 13:33:25 +00:00
|
|
|
tuple(sub_irrefutable) {
|
|
|
|
let h, t = $1 in
|
|
|
|
let start = pattern_to_region h in
|
|
|
|
let stop = last (fun (region, _) -> region) t in
|
|
|
|
let region = cover start stop in
|
|
|
|
PTuple { value = $1; region }
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
| sub_irrefutable { $1 }
|
|
|
|
|
|
|
|
sub_irrefutable:
|
2019-09-27 13:33:25 +00:00
|
|
|
Ident { PVar $1 }
|
|
|
|
| WILD { PWild $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
| unit { PUnit $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| record_pattern { PRecord $1 }
|
2019-05-20 21:42:11 +02:00
|
|
|
| par(closed_irrefutable) { PPar $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
closed_irrefutable:
|
2019-05-22 19:38:09 +02:00
|
|
|
irrefutable { $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| constr_pattern { PConstr $1 }
|
|
|
|
| typed_pattern { PTyped $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
typed_pattern:
|
2019-09-27 13:33:25 +00:00
|
|
|
irrefutable COLON type_expr {
|
|
|
|
let start = pattern_to_region $1 in
|
|
|
|
let stop = type_expr_to_region $3 in
|
|
|
|
let region = cover start stop in
|
|
|
|
{
|
|
|
|
value = {
|
|
|
|
pattern = $1;
|
|
|
|
colon = $2;
|
|
|
|
type_expr = $3
|
|
|
|
};
|
|
|
|
region
|
|
|
|
}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
pattern:
|
2019-09-27 13:33:25 +00:00
|
|
|
sub_pattern CONS tail {
|
|
|
|
let start = pattern_to_region $1 in
|
|
|
|
let stop = pattern_to_region $3 in
|
|
|
|
let region = cover start stop in
|
|
|
|
let val_ = {value = $1, $2, $3; region} in
|
|
|
|
PList (PCons val_)
|
|
|
|
}
|
|
|
|
| tuple(sub_pattern) {
|
|
|
|
let h, t = $1 in
|
|
|
|
let start = pattern_to_region h in
|
|
|
|
let stop = last (fun (region, _) -> region) t in
|
|
|
|
let region = cover start stop in
|
|
|
|
PTuple { value = $1; region }
|
|
|
|
}
|
|
|
|
| core_pattern { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
sub_pattern:
|
2019-05-22 19:38:09 +02:00
|
|
|
par(tail) { PPar $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
| core_pattern { $1 }
|
|
|
|
|
|
|
|
core_pattern:
|
2019-09-27 13:33:25 +00:00
|
|
|
Ident { PVar $1 }
|
|
|
|
| WILD { PWild $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
| unit { PUnit $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| Int { PInt $1 }
|
|
|
|
| True { PTrue $1 }
|
|
|
|
| False { PFalse $1 }
|
|
|
|
| Str { PString $1 }
|
2019-05-22 19:38:09 +02:00
|
|
|
| par(ptuple) { PPar $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| list(tail) { PList (Sugar $1) }
|
|
|
|
| constr_pattern { PConstr $1 }
|
|
|
|
| record_pattern { PRecord $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
record_pattern:
|
2019-09-27 13:33:25 +00:00
|
|
|
LBRACE sep_or_term_list(field_pattern,SEMI) RBRACE {
|
2019-05-12 19:31:22 +02:00
|
|
|
let elements, terminator = $2 in
|
2019-09-27 13:33:25 +00:00
|
|
|
let region = cover $1 $3 in
|
|
|
|
let value = {
|
|
|
|
opening = LBrace $1;
|
|
|
|
elements = Some elements;
|
|
|
|
terminator;
|
|
|
|
closing = RBrace $3}
|
|
|
|
in
|
|
|
|
{region; value}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
field_pattern:
|
2019-09-27 13:33:25 +00:00
|
|
|
field_name EQ sub_pattern {
|
|
|
|
let start = $1.region in
|
|
|
|
let stop = pattern_to_region $3 in
|
|
|
|
let region = cover start stop in
|
|
|
|
{ value = {field_name=$1; eq=$2; pattern=$3}; region }
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
constr_pattern:
|
2019-09-27 13:33:25 +00:00
|
|
|
Constr sub_pattern {
|
|
|
|
let region = cover $1.region (pattern_to_region $2) in
|
|
|
|
{ value = $1, Some $2; region } }
|
|
|
|
| Constr { { value = $1, None; region = $1.region } }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
ptuple:
|
2019-09-27 13:33:25 +00:00
|
|
|
tuple(tail) {
|
|
|
|
let h, t = $1 in
|
|
|
|
let start = pattern_to_region h in
|
|
|
|
let stop = last (fun (region, _) -> region) t in
|
|
|
|
let region = cover start stop in
|
|
|
|
PTuple { value = $1; region }
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
unit:
|
2019-09-27 13:33:25 +00:00
|
|
|
LPAR RPAR {
|
|
|
|
let the_unit = ghost, ghost in
|
|
|
|
let region = cover $1 $2 in
|
|
|
|
{ value = the_unit; region }
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
tail:
|
2019-09-27 13:33:25 +00:00
|
|
|
sub_pattern CONS tail {
|
|
|
|
let start = pattern_to_region $1 in
|
|
|
|
let end_ = pattern_to_region $3 in
|
|
|
|
let region = cover start end_ in
|
|
|
|
PList (PCons {value = ($1, $2, $3); region} )
|
|
|
|
}
|
2019-05-13 17:35:31 +02:00
|
|
|
| sub_pattern { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
(* Expressions *)
|
|
|
|
|
2019-06-03 17:43:25 +02:00
|
|
|
interactive_expr:
|
|
|
|
expr EOF { $1 }
|
|
|
|
|
2019-05-12 19:31:22 +02:00
|
|
|
expr:
|
2019-05-13 17:35:31 +02:00
|
|
|
base_cond__open(expr) { $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| match_expr(base_cond) { ECase $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
base_cond__open(x):
|
|
|
|
base_expr(x)
|
|
|
|
| conditional(x) { $1 }
|
|
|
|
|
|
|
|
base_cond:
|
|
|
|
base_cond__open(base_cond) { $1 }
|
|
|
|
|
|
|
|
base_expr(right_expr):
|
|
|
|
let_expr(right_expr)
|
|
|
|
| fun_expr(right_expr)
|
|
|
|
| disj_expr_level { $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| tuple(disj_expr_level) {
|
|
|
|
let h, t = $1 in
|
|
|
|
let start = expr_to_region h in
|
|
|
|
let stop = last (fun (region, _) -> region) t in
|
|
|
|
let region = cover start stop in
|
|
|
|
ETuple { value = $1; region }
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
conditional(right_expr):
|
2019-09-27 13:33:25 +00:00
|
|
|
if_then_else(right_expr)
|
|
|
|
| if_then(right_expr) { ECond $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
if_then(right_expr):
|
2019-09-27 13:33:25 +00:00
|
|
|
If expr Then right_expr {
|
2019-05-13 17:35:31 +02:00
|
|
|
let the_unit = ghost, ghost in
|
2019-09-27 13:33:25 +00:00
|
|
|
let start = $1 in
|
|
|
|
let stop = expr_to_region $4 in
|
|
|
|
let region = cover start stop in
|
2019-05-13 17:35:31 +02:00
|
|
|
let ifnot = EUnit {region=ghost; value=the_unit} in
|
2019-09-27 13:33:25 +00:00
|
|
|
{
|
|
|
|
value = {
|
|
|
|
kwd_if = $1;
|
|
|
|
test = $2;
|
|
|
|
kwd_then = $3;
|
|
|
|
ifso = $4;
|
|
|
|
kwd_else = ghost;
|
|
|
|
ifnot
|
|
|
|
};
|
|
|
|
region
|
|
|
|
}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
if_then_else(right_expr):
|
2019-09-27 13:33:25 +00:00
|
|
|
If expr Then closed_if Else right_expr {
|
|
|
|
let region = cover $1 (expr_to_region $6) in
|
|
|
|
{
|
|
|
|
value = {
|
|
|
|
kwd_if = $1;
|
|
|
|
test = $2;
|
|
|
|
kwd_then = $3;
|
|
|
|
ifso = $4;
|
|
|
|
kwd_else = $5;
|
|
|
|
ifnot = $6
|
|
|
|
};
|
|
|
|
region
|
|
|
|
}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
base_if_then_else__open(x):
|
|
|
|
base_expr(x) { $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| if_then_else(x) { ECond $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
base_if_then_else:
|
|
|
|
base_if_then_else__open(base_if_then_else) { $1 }
|
|
|
|
|
|
|
|
closed_if:
|
|
|
|
base_if_then_else__open(closed_if) { $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| match_expr(base_if_then_else) { ECase $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
match_expr(right_expr):
|
2019-09-27 13:33:25 +00:00
|
|
|
Match expr With VBAR? cases(right_expr) {
|
|
|
|
let cases = Utils.nsepseq_rev $5 in
|
|
|
|
let start = $1 in
|
|
|
|
let stop = match $5 with (* TODO: move to separate function *)
|
|
|
|
| {region; _}, [] -> region
|
|
|
|
| _, tl -> last (fun (region,_) -> region) tl
|
|
|
|
in
|
|
|
|
let region = cover start stop in
|
|
|
|
{ value = {
|
|
|
|
kwd_match = $1;
|
|
|
|
expr = $2;
|
|
|
|
opening = With $3;
|
|
|
|
lead_vbar = $4;
|
|
|
|
cases = {
|
|
|
|
value = cases;
|
|
|
|
region = nsepseq_to_region (fun {region; _} -> region) $5
|
|
|
|
};
|
|
|
|
closing = End ghost
|
|
|
|
};
|
|
|
|
region
|
|
|
|
}
|
|
|
|
}
|
|
|
|
| MatchNat expr With VBAR? cases(right_expr) {
|
|
|
|
let cases = Utils.nsepseq_rev $5 in
|
2019-05-13 17:35:31 +02:00
|
|
|
let cast = EVar {region=ghost; value="assert_pos"} in
|
2019-05-14 16:04:03 +02:00
|
|
|
let cast = ECall {region=ghost; value=cast,($2,[])} in
|
2019-09-27 13:33:25 +00:00
|
|
|
let start = $1 in
|
|
|
|
let stop = match $5 with (* TODO: move to separate function *)
|
|
|
|
| {region; _}, [] -> region
|
|
|
|
| _, tl -> last (fun (region,_) -> region) tl
|
|
|
|
in
|
|
|
|
let region = cover start stop in
|
|
|
|
{
|
|
|
|
value = {
|
|
|
|
kwd_match = $1;
|
|
|
|
expr = cast;
|
|
|
|
opening = With $3;
|
|
|
|
lead_vbar = $4;
|
|
|
|
cases = {
|
|
|
|
value = cases;
|
|
|
|
region = nsepseq_to_region (fun {region; _} -> region) $5
|
|
|
|
};
|
|
|
|
closing = End ghost
|
|
|
|
};
|
|
|
|
region
|
|
|
|
}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
cases(right_expr):
|
2019-09-27 13:33:25 +00:00
|
|
|
case_clause(right_expr) {
|
|
|
|
let start = pattern_to_region $1.pattern in
|
|
|
|
let stop = expr_to_region $1.rhs in
|
|
|
|
let region = cover start stop in
|
|
|
|
{ value = $1; region }, []
|
|
|
|
}
|
|
|
|
| cases(base_cond) VBAR case_clause(right_expr) {
|
|
|
|
let start = match $1 with
|
|
|
|
| {region; _}, [] -> region
|
|
|
|
| _, tl -> last (fun (region,_) -> region) tl
|
|
|
|
in
|
|
|
|
let stop = expr_to_region $3.rhs in
|
|
|
|
let region = cover start stop in
|
|
|
|
let h,t = $1 in { value = $3; region}, ($2, h)::t
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
2019-05-13 17:35:31 +02:00
|
|
|
case_clause(right_expr):
|
2019-09-27 13:33:25 +00:00
|
|
|
pattern ARROW right_expr {
|
|
|
|
{
|
|
|
|
pattern = $1;
|
|
|
|
arrow = $2;
|
|
|
|
rhs=$3
|
|
|
|
}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
let_expr(right_expr):
|
2019-09-27 13:33:25 +00:00
|
|
|
Let let_binding In right_expr {
|
|
|
|
let kwd_let = $1 in
|
|
|
|
let (binding, _) = $2 in
|
|
|
|
let kwd_in = $3 in
|
|
|
|
let body = $4 in
|
|
|
|
let stop = expr_to_region $4 in
|
|
|
|
let region = cover $1 stop in
|
2019-05-20 21:42:11 +02:00
|
|
|
let let_in = {kwd_let; binding; kwd_in; body}
|
2019-09-27 13:33:25 +00:00
|
|
|
in ELetIn {region; value=let_in} }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
fun_expr(right_expr):
|
2019-09-27 13:33:25 +00:00
|
|
|
Fun nseq(irrefutable) ARROW right_expr {
|
|
|
|
let kwd_fun = $1 in
|
|
|
|
let bindings = $2 in
|
|
|
|
let arrow = $3 in
|
|
|
|
let body = $4 in
|
|
|
|
let stop = expr_to_region $4 in
|
|
|
|
let region = cover $1 stop in
|
2019-06-01 11:29:31 +00:00
|
|
|
let (hd , tl) = bindings in
|
|
|
|
let f = {
|
|
|
|
kwd_fun ;
|
|
|
|
params = hd :: tl ;
|
|
|
|
p_annot = None ;
|
|
|
|
arrow ;
|
|
|
|
body ;
|
|
|
|
} in
|
2019-09-27 13:33:25 +00:00
|
|
|
EFun { region; value=f }
|
2019-06-01 11:29:31 +00:00
|
|
|
}
|
2019-06-03 17:43:25 +02:00
|
|
|
|
2019-05-12 19:31:22 +02:00
|
|
|
disj_expr_level:
|
2019-09-27 13:33:25 +00:00
|
|
|
disj_expr { ELogic (BoolExpr (Or $1)) }
|
2019-05-12 19:31:22 +02:00
|
|
|
| conj_expr_level { $1 }
|
|
|
|
|
|
|
|
bin_op(arg1,op,arg2):
|
2019-09-27 13:33:25 +00:00
|
|
|
arg1 op arg2 {
|
|
|
|
let start = expr_to_region $1 in
|
|
|
|
let stop = expr_to_region $3 in
|
|
|
|
let region = cover start stop in
|
|
|
|
{ value = { arg1=$1; op=$2; arg2=$3}; region }
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
disj_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(disj_expr_level, BOOL_OR, conj_expr_level)
|
|
|
|
| bin_op(disj_expr_level, Or, conj_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
conj_expr_level:
|
2019-09-27 13:33:25 +00:00
|
|
|
conj_expr { ELogic (BoolExpr (And $1)) }
|
2019-05-12 19:31:22 +02:00
|
|
|
| comp_expr_level { $1 }
|
|
|
|
|
|
|
|
conj_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(conj_expr_level, BOOL_AND, comp_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
comp_expr_level:
|
2019-09-27 13:33:25 +00:00
|
|
|
lt_expr { ELogic (CompExpr (Lt $1)) }
|
|
|
|
| le_expr { ELogic (CompExpr (Leq $1)) }
|
|
|
|
| gt_expr { ELogic (CompExpr (Gt $1)) }
|
|
|
|
| ge_expr { ELogic (CompExpr (Geq $1)) }
|
|
|
|
| eq_expr { ELogic (CompExpr (Equal $1)) }
|
|
|
|
| ne_expr { ELogic (CompExpr (Neq $1)) }
|
2019-05-12 19:31:22 +02:00
|
|
|
| cat_expr_level { $1 }
|
|
|
|
|
|
|
|
lt_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(comp_expr_level, LT, cat_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
le_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(comp_expr_level, LE, cat_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
gt_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(comp_expr_level, GT, cat_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
ge_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(comp_expr_level, GE, cat_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
eq_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(comp_expr_level, EQ, cat_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
ne_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(comp_expr_level, NE, cat_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
cat_expr_level:
|
2019-09-27 13:33:25 +00:00
|
|
|
cat_expr { EString (Cat $1) }
|
2019-05-15 15:03:15 +02:00
|
|
|
(*| reg(append_expr) { EList (Append $1) } *)
|
2019-05-13 12:28:10 +02:00
|
|
|
| cons_expr_level { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
cat_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(cons_expr_level, CAT, cat_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
2019-05-15 15:03:15 +02:00
|
|
|
(*
|
2019-05-12 19:31:22 +02:00
|
|
|
append_expr:
|
|
|
|
cons_expr_level sym(APPEND) cat_expr_level { $1,$2,$3 }
|
2019-05-15 15:03:15 +02:00
|
|
|
*)
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
cons_expr_level:
|
2019-09-27 13:33:25 +00:00
|
|
|
cons_expr { EList (Cons $1) }
|
2019-05-13 12:28:10 +02:00
|
|
|
| add_expr_level { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
cons_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(add_expr_level, CONS, cons_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
add_expr_level:
|
2019-09-27 13:33:25 +00:00
|
|
|
plus_expr { EArith (Add $1) }
|
|
|
|
| minus_expr { EArith (Sub $1) }
|
2019-05-12 19:31:22 +02:00
|
|
|
| mult_expr_level { $1 }
|
|
|
|
|
|
|
|
plus_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(add_expr_level, PLUS, mult_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
minus_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(add_expr_level, MINUS, mult_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
mult_expr_level:
|
2019-09-27 13:33:25 +00:00
|
|
|
times_expr { EArith (Mult $1) }
|
|
|
|
| div_expr { EArith (Div $1) }
|
|
|
|
| mod_expr { EArith (Mod $1) }
|
2019-05-12 19:31:22 +02:00
|
|
|
| unary_expr_level { $1 }
|
|
|
|
|
|
|
|
times_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(mult_expr_level, TIMES, unary_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
div_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(mult_expr_level, SLASH, unary_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
mod_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
bin_op(mult_expr_level, Mod, unary_expr_level) { $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
unary_expr_level:
|
2019-09-27 13:33:25 +00:00
|
|
|
MINUS call_expr_level {
|
|
|
|
let start = $1 in
|
|
|
|
let end_ = expr_to_region $2 in
|
|
|
|
let region = cover start end_
|
|
|
|
and value = {op = $1; arg = $2}
|
|
|
|
in EArith (Neg {region; value})
|
|
|
|
}
|
|
|
|
| Not call_expr_level {
|
|
|
|
let start = $1 in
|
|
|
|
let end_ = expr_to_region $2 in
|
|
|
|
let region = cover start end_
|
|
|
|
and value = {op = $1; arg = $2} in
|
|
|
|
ELogic (BoolExpr (Not ({region; value})))
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
| call_expr_level { $1 }
|
|
|
|
|
|
|
|
call_expr_level:
|
2019-09-27 13:33:25 +00:00
|
|
|
call_expr { ECall $1 }
|
|
|
|
| constr_expr { EConstr $1 }
|
2019-05-14 15:56:08 +02:00
|
|
|
| core_expr { $1 }
|
|
|
|
|
|
|
|
constr_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
Constr core_expr? {
|
|
|
|
let start = $1.region in
|
|
|
|
let stop = match $2 with
|
|
|
|
| Some c -> expr_to_region c
|
|
|
|
| None -> start
|
|
|
|
in
|
|
|
|
let region = cover start stop in
|
|
|
|
{ value = $1,$2; region}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
call_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
core_expr nseq(core_expr) {
|
|
|
|
let start = expr_to_region $1 in
|
|
|
|
let stop = match $2 with
|
|
|
|
| e, [] -> expr_to_region e
|
|
|
|
| _, l -> last expr_to_region l
|
|
|
|
in
|
|
|
|
let region = cover start stop in
|
|
|
|
{ value = $1,$2; region }
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
core_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
Int { EArith (Int $1) }
|
|
|
|
| Mtz { EArith (Mtz $1) }
|
|
|
|
| Nat { EArith (Nat $1) }
|
|
|
|
| Ident | module_field { EVar $1 }
|
|
|
|
| projection { EProj $1 }
|
|
|
|
| Str { EString (String $1) }
|
2019-05-13 17:35:31 +02:00
|
|
|
| unit { EUnit $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| False { ELogic (BoolExpr (False $1)) }
|
|
|
|
| True { ELogic (BoolExpr (True $1)) }
|
|
|
|
| list(expr) { EList (List $1) }
|
2019-05-14 15:56:08 +02:00
|
|
|
| par(expr) { EPar $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| sequence { ESeq $1 }
|
|
|
|
| record_expr { ERecord $1 }
|
|
|
|
| par(expr COLON type_expr {$1,$3}) {
|
2019-05-14 15:56:08 +02:00
|
|
|
EAnnot {$1 with value=$1.value.inside} }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
2019-05-13 17:35:31 +02:00
|
|
|
module_field:
|
2019-09-27 13:33:25 +00:00
|
|
|
module_name DOT field_name {
|
|
|
|
let region = cover $1.region $3.region in
|
|
|
|
{ value = $1.value ^ "." ^ $3.value; region }
|
|
|
|
}
|
2019-05-13 17:35:31 +02:00
|
|
|
|
|
|
|
projection:
|
2019-09-27 13:33:25 +00:00
|
|
|
struct_name DOT nsepseq(selection,DOT) {
|
|
|
|
let start = $1.region in
|
|
|
|
let stop = nsepseq_to_region (function
|
|
|
|
| FieldName f -> f.region
|
|
|
|
| Component c -> c.region) $3
|
|
|
|
in
|
|
|
|
let region = cover start stop in
|
|
|
|
{ value =
|
|
|
|
{
|
|
|
|
struct_name = $1;
|
|
|
|
selector = $2;
|
|
|
|
field_path = $3
|
|
|
|
};
|
|
|
|
region
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
}
|
2019-09-27 13:33:25 +00:00
|
|
|
| module_name DOT field_name DOT nsepseq(selection,DOT) {
|
2019-05-13 17:35:31 +02:00
|
|
|
let open Region in
|
2019-09-27 13:33:25 +00:00
|
|
|
let module_name = $1 in
|
|
|
|
let field_name = $3 in
|
2019-05-13 17:35:31 +02:00
|
|
|
let value = module_name.value ^ "." ^ field_name.value in
|
|
|
|
let struct_name = {$1 with value} in
|
2019-09-27 13:33:25 +00:00
|
|
|
let start = $1.region in
|
|
|
|
let stop = nsepseq_to_region (function
|
|
|
|
| FieldName f -> f.region
|
|
|
|
| Component c -> c.region) $5
|
|
|
|
in
|
|
|
|
let region = cover start stop in
|
|
|
|
{
|
|
|
|
value = {
|
|
|
|
struct_name;
|
|
|
|
selector = $4;
|
|
|
|
field_path = $5
|
|
|
|
};
|
|
|
|
region
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-05-12 19:31:22 +02:00
|
|
|
selection:
|
2019-05-14 15:56:08 +02:00
|
|
|
field_name { FieldName $1 }
|
2019-09-27 13:33:25 +00:00
|
|
|
| par(Int) { Component $1 }
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
record_expr:
|
2019-09-27 13:33:25 +00:00
|
|
|
LBRACE sep_or_term_list(field_assignment,SEMI) RBRACE {
|
2019-05-12 19:31:22 +02:00
|
|
|
let elements, terminator = $2 in
|
2019-09-27 13:33:25 +00:00
|
|
|
let region = cover $1 $3 in
|
|
|
|
{value =
|
|
|
|
{
|
|
|
|
opening = LBrace $1;
|
|
|
|
elements = Some elements;
|
|
|
|
terminator;
|
|
|
|
closing = RBrace $3
|
|
|
|
};
|
|
|
|
region}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
field_assignment:
|
2019-09-27 13:33:25 +00:00
|
|
|
field_name EQ expr {
|
|
|
|
let start = $1.region in
|
|
|
|
let stop = expr_to_region $3 in
|
|
|
|
let region = cover start stop in
|
|
|
|
{ value =
|
|
|
|
{
|
|
|
|
field_name = $1;
|
|
|
|
assignment = $2;
|
|
|
|
field_expr = $3
|
|
|
|
};
|
|
|
|
region
|
|
|
|
}
|
|
|
|
}
|
2019-05-12 19:31:22 +02:00
|
|
|
|
|
|
|
sequence:
|
2019-09-27 13:33:25 +00:00
|
|
|
Begin sep_or_term_list(expr,SEMI) End {
|
2019-05-12 19:31:22 +02:00
|
|
|
let elements, terminator = $2 in
|
2019-09-27 13:33:25 +00:00
|
|
|
let start = $1 in
|
|
|
|
let stop = $3 in
|
|
|
|
let region = cover start stop in
|
|
|
|
{
|
|
|
|
value = {
|
|
|
|
opening = Begin $1;
|
|
|
|
elements = Some elements;
|
|
|
|
terminator;
|
|
|
|
closing = End $3
|
|
|
|
};
|
|
|
|
region
|
|
|
|
}
|
|
|
|
}
|