ligo/src/passes/1-parser/pascaligo/Parser.mly

1063 lines
29 KiB
OCaml
Raw Normal View History

2019-05-13 00:56:22 +04:00
%{
(* START HEADER *)
[@@@warning "-42"]
open Region
open AST
2020-01-20 13:57:07 +04:00
(*
type statement_attributes_mixed =
2020-01-16 23:36:04 +04:00
PInstr of instruction
| PData of data_decl
2020-01-20 13:57:07 +04:00
| PAttr of attributes
2020-01-16 23:36:04 +04:00
let attributes_to_statement (statement, statements) =
2020-01-20 13:57:07 +04:00
match statements with
[] ->
(match statement with
| PInstr i -> Instr i, []
| PData d -> Data d, []
| PAttr a ->
raise (Scoping.Error (Scoping.Detached_attributes a)))
| _ -> (
2020-01-16 23:36:04 +04:00
let statements = (Region.ghost, statement) :: statements in
let rec inner result = function
2020-01-20 13:57:07 +04:00
| (t, PData (LocalConst const)) :: (_, PAttr a) :: rest ->
2020-01-16 23:36:04 +04:00
inner (result @ [(t, Data (LocalConst {const with value = {const.value with attributes = a}}))]) rest
2020-01-20 13:57:07 +04:00
| (t, PData (LocalFun func)) :: (_, PAttr a) :: rest ->
inner (result @ [(t, Data (LocalFun {func with value = {func.value with attributes = a}}))]) rest
2020-01-16 23:36:04 +04:00
| (t, PData d) :: rest ->
inner (result @ [(t, Data d)]) rest
| (t, PInstr i) :: rest ->
inner (result @ [(t, Instr i)]) rest
2020-01-20 13:57:07 +04:00
| (_, PAttr _) :: rest ->
2020-01-16 23:36:04 +04:00
inner result rest
2020-01-20 13:57:07 +04:00
| [] ->
2020-01-16 23:36:04 +04:00
result
2020-01-20 13:57:07 +04:00
in
2020-01-16 23:36:04 +04:00
let result = inner [] statements in
(snd (List.hd result), List.tl result)
)
2020-01-20 13:57:07 +04:00
*)
2020-01-16 23:36:04 +04:00
(* END HEADER *)
2019-05-13 00:56:22 +04:00
%}
(* See [ParToken.mly] for the definition of tokens. *)
(* Entry points *)
%start contract interactive_expr
%type <AST.t> contract
%type <AST.expr> interactive_expr
%%
(* 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]. *)
2019-05-13 00:56:22 +04:00
sep_or_term_list(item,sep):
nsepseq(item,sep) {
$1, None
2019-05-13 00:56:22 +04:00
}
| 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 }
2019-05-13 00:56:22 +04:00
(* Compound constructs *)
par(X):
"(" X ")" {
2019-05-13 00:56:22 +04:00
let region = cover $1 $3
and value = {
lpar = $1;
inside = $2;
rpar = $3}
in {region; value} }
2019-05-13 00:56:22 +04:00
brackets(X):
"[" X "]" {
2019-05-13 00:56:22 +04:00
let region = cover $1 $3
and value = {
lbracket = $1;
inside = $2;
rbracket = $3}
in {region; value} }
2019-05-13 00:56:22 +04: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(X):
(**) { [] }
| X seq(X) { $1::$2 }
(* Non-empty sequence of items *)
nseq(X):
X seq(X) { $1,$2 }
(* Non-empty separated sequence of items *)
nsepseq(X,Sep):
X { $1, [] }
| X Sep nsepseq(X,Sep) { let h,t = $3 in $1, ($2,h)::t }
(* Possibly empy separated sequence of items *)
sepseq(X,Sep):
(**) { None }
| nsepseq(X,Sep) { Some $1 }
(* Inlines *)
%inline var : "<ident>" { $1 }
%inline type_name : "<ident>" { $1 }
%inline fun_name : "<ident>" { $1 }
%inline field_name : "<ident>" { $1 }
%inline struct_name : "<ident>" { $1 }
2019-05-13 00:56:22 +04:00
(* Main *)
contract:
nseq(declaration) EOF { {decl=$1; eof=$2} }
2019-05-13 00:56:22 +04:00
declaration:
type_decl { TypeDecl $1 }
| const_decl { ConstDecl $1 }
2020-01-20 13:57:07 +04:00
| fun_decl { FunDecl $1 }
2019-05-13 00:56:22 +04:00
(* Type declarations *)
type_decl:
"type" type_name "is" type_expr ";"? {
Scoping.check_reserved_name $2;
2019-05-13 00:56:22 +04:00
let stop =
match $5 with
Some region -> region
| None -> type_expr_to_region $4 in
let region = cover $1 stop in
let value = {kwd_type = $1;
name = $2;
kwd_is = $3;
type_expr = $4;
terminator = $5}
in {region; value} }
2019-05-13 00:56:22 +04:00
type_expr:
sum_type | record_type | cartesian { $1 }
2019-05-13 00:56:22 +04:00
cartesian:
function_type { $1 }
| function_type "*" nsepseq(function_type,"*") {
let value = Utils.nsepseq_cons $1 $2 $3 in
let region = nsepseq_to_region type_expr_to_region value
in TProd {region; value} }
2019-05-13 00:56:22 +04:00
function_type:
core_type { $1 }
| core_type "->" function_type {
let start = type_expr_to_region $1
and stop = type_expr_to_region $3 in
let region = cover start stop in
TFun {region; value = $1,$2,$3} }
2019-05-13 00:56:22 +04:00
core_type:
type_name { TVar $1 }
| par(type_expr) { TPar $1 }
2019-05-13 00:56:22 +04:00
| type_name type_tuple {
let region = cover $1.region $2.region
in TApp {region; value = $1,$2}
}
| "map" type_tuple {
2019-05-13 00:56:22 +04:00
let region = cover $1 $2.region in
let type_constr = {value="map"; region=$1}
in TApp {region; value = type_constr, $2}
}
| "big_map" type_tuple {
2019-10-08 14:22:22 +04:00
let region = cover $1 $2.region in
let type_constr = {value="big_map"; region=$1}
in TApp {region; value = type_constr, $2}
}
| "set" par(type_expr) {
2019-05-13 00:56:22 +04:00
let total = cover $1 $2.region in
let type_constr = {value="set"; region=$1} in
let {region; value = {lpar; inside; rpar}} = $2 in
let tuple = {region; value={lpar; inside=inside,[]; rpar}}
in TApp {region=total; value = type_constr, tuple}
}
| "list" par(type_expr) {
2019-05-13 00:56:22 +04:00
let total = cover $1 $2.region in
let type_constr = {value="list"; region=$1} in
let {region; value = {lpar; inside; rpar}} = $2 in
let tuple = {region; value={lpar; inside=inside,[]; rpar}}
in TApp {region=total; value = type_constr, tuple}
}
type_tuple:
par(nsepseq(type_expr,",")) { $1 }
2019-05-13 00:56:22 +04:00
sum_type:
"|"? nsepseq(variant,"|") {
Scoping.check_variants (Utils.nsepseq_to_list $2);
2019-05-13 00:56:22 +04:00
let region = nsepseq_to_region (fun x -> x.region) $2
in TSum {region; value=$2} }
2019-05-13 00:56:22 +04:00
variant:
"<constr>" { {$1 with value = {constr=$1; arg=None}} }
| "<constr>" "of" cartesian {
let region = cover $1.region (type_expr_to_region $3)
and value = {constr=$1; arg = Some ($2,$3)}
in {region; value} }
2019-05-13 00:56:22 +04:00
record_type:
"record" sep_or_term_list(field_decl,";") "end" {
let ne_elements, terminator = $2 in
let () = Utils.nsepseq_to_list ne_elements
|> Scoping.check_fields in
let region = cover $1 $3
and value = {opening = Kwd $1;
ne_elements;
terminator;
closing = End $3}
in TRecord {region; value}
2019-05-13 00:56:22 +04:00
}
| "record" "[" sep_or_term_list(field_decl,";") "]" {
let ne_elements, terminator = $3 in
let region = cover $1 $4
and value = {opening = KwdBracket ($1,$2);
ne_elements;
terminator;
closing = RBracket $4}
in TRecord {region; value} }
2019-05-13 00:56:22 +04:00
field_decl:
field_name ":" type_expr {
2019-05-13 00:56:22 +04:00
let stop = type_expr_to_region $3 in
let region = cover $1.region stop
and value = {field_name=$1; colon=$2; field_type=$3}
2019-05-13 00:56:22 +04:00
in {region; value} }
2020-01-20 13:57:07 +04:00
fun_expr:
"function" parameters ":" type_expr "is" expr {
let stop = expr_to_region $6 in
2019-05-13 00:56:22 +04:00
let region = cover $1 stop
and value = {kwd_function = $1;
param = $2;
colon = $3;
ret_type = $4;
kwd_is = $5;
2020-01-16 23:36:04 +04:00
return = $6
}
in {region; value} }
(* Function declarations *)
open_fun_decl:
"function" fun_name parameters ":" type_expr "is"
block
"with" expr {
Scoping.check_reserved_name $2;
let stop = expr_to_region $9 in
let region = cover $1 stop
and value = {kwd_function = $1;
fun_name = $2;
param = $3;
colon = $4;
ret_type = $5;
kwd_is = $6;
block_with = Some ($7, $8);
return = $9;
2020-01-16 23:36:04 +04:00
terminator = None;
2020-01-20 13:57:07 +04:00
attributes = None}
Refactoring of comments (for [dune build @doc]). Refactoring of parsing command-line arguments * The type [options] is now abstract and implemented as an object type to avoid struggling with scoping and type inference when record types share some common field names. Refactoring of ParserLog for PascaLIGO and CameLIGO * The immediate motivation behind that refactoring was to remove the use of a couple of global references. A consequence is that we have a nicer and more compact code, by threading a state. The files [pascaligo/Tests/pp.ligo] and [ligodity/Tests/pp.mligo]. * Another consequence is that the choice of making strings from AST nodes depends on the CLI (offsets? mode?). After this refactoring, that choice is hardcoded in the simplifiers in a few places (TODO), waiting for a general solution that would have all CL options flow through the compiler. * I removed the use of vendors [x_option.ml], [x_map.ml] and [x_list.ml] when handling optional values. (Less dependencies this way.) Refactoring of the ASTs * I removed the node [local_decl], which was set to [[]] already in a previous commit (which removed local declarations as being redundant, as statements could already be instructions or declarations). * I changed [StrLit] to [String] in the AST of CameLIGO and ReasonLIGO. * I also changed the type [fun_expr] so now either a block is present, and therefore followed by the [with] keyword, or it is not. (Before, the presence of a block was not enforced in the type with the presence of the keyword.) Notes * [LexerMain.ml] and [ParserMain.ml] for CameLIGO and PascaLIGO are almost identical and differ in the same way (language name and file extension), which suggests that they should be in the [shared] folder and instanciated as a functor in the future (TODO). * I removed the blank characters at the end of many lines in the parser of ReasonLIGO.
2019-12-13 15:21:52 +04:00
in {region; value} }
| "function" fun_name parameters ":" type_expr "is" expr {
Scoping.check_reserved_name $2;
let stop = expr_to_region $7 in
let region = cover $1 stop
and value = {kwd_function = $1;
fun_name = $2;
param = $3;
colon = $4;
ret_type = $5;
kwd_is = $6;
block_with = None;
return = $7;
2020-01-16 23:36:04 +04:00
terminator = None;
2020-01-20 13:57:07 +04:00
attributes = None}
in {region; value} }
fun_decl:
2020-01-20 13:57:07 +04:00
open_fun_decl maybe_attributes? {
match $2 with
None -> $1
| Some (terminator, attributes) ->
let value = {$1.value with terminator; attributes}
in {$1 with value} }
2019-05-13 00:56:22 +04:00
parameters:
par(nsepseq(param_decl,";")) {
let params =
Utils.nsepseq_to_list ($1.value: _ par).inside
in Scoping.check_parameters params;
$1 }
2019-05-13 00:56:22 +04:00
param_decl:
"var" var ":" param_type {
Scoping.check_reserved_name $2;
2019-05-13 00:56:22 +04:00
let stop = type_expr_to_region $4 in
let region = cover $1 stop
and value = {kwd_var = $1;
var = $2;
colon = $3;
param_type = $4}
2019-05-13 00:56:22 +04:00
in ParamVar {region; value}
}
| "const" var ":" param_type {
Scoping.check_reserved_name $2;
2019-05-13 00:56:22 +04:00
let stop = type_expr_to_region $4 in
let region = cover $1 stop
and value = {kwd_const = $1;
var = $2;
colon = $3;
param_type = $4}
in ParamConst {region; value} }
2019-05-13 00:56:22 +04:00
param_type:
cartesian { $1 }
2019-05-13 00:56:22 +04:00
block:
"begin" sep_or_term_list(statement,";") "end" {
let statements, terminator = $2 in
let region = cover $1 $3
and value = {opening = Begin $1;
2020-01-20 13:57:07 +04:00
statements (*= attributes_to_statement statements*);
terminator;
closing = End $3}
in {region; value}
2019-05-13 00:56:22 +04:00
}
| "block" "{" sep_or_term_list(statement,";") "}" {
let statements, terminator = $3 in
let region = cover $1 $4
and value = {opening = Block ($1,$2);
2020-01-20 13:57:07 +04:00
statements (*= attributes_to_statement statements*);
terminator;
closing = Block $4}
in {region; value} }
2019-05-13 00:56:22 +04:00
statement:
2020-01-20 13:57:07 +04:00
instruction { (*P*)Instr $1 }
| open_data_decl { (*P*)Data $1 }
(*| attributes { PAttr $1 }*)
2019-05-13 00:56:22 +04:00
open_data_decl:
open_const_decl { LocalConst $1 }
| open_var_decl { LocalVar $1 }
| open_fun_decl { LocalFun $1 }
2019-05-13 00:56:22 +04:00
open_const_decl:
"const" unqualified_decl("=") {
2019-05-13 00:56:22 +04:00
let name, colon, const_type, equal, init, stop = $2 in
let region = cover $1 stop
and value = {kwd_const = $1;
name;
colon;
const_type;
equal;
init;
2020-01-16 23:36:04 +04:00
terminator = None;
2020-01-20 13:57:07 +04:00
attributes = None}
in {region; value} }
2019-05-13 00:56:22 +04:00
open_var_decl:
"var" unqualified_decl(":=") {
2019-05-13 00:56:22 +04:00
let name, colon, var_type, assign, init, stop = $2 in
let region = cover $1 stop
and value = {kwd_var = $1;
name;
colon;
var_type;
assign;
init;
2020-01-20 13:57:07 +04:00
terminator=None}
in {region; value} }
2019-05-13 00:56:22 +04:00
unqualified_decl(OP):
var ":" type_expr OP expr {
Scoping.check_reserved_name $1;
let region = expr_to_region $5
in $1, $2, $3, $4, $5, region }
2019-05-13 00:56:22 +04:00
2020-01-20 13:57:07 +04:00
attributes:
ne_injection("attributes","<string>") { $1 }
2020-01-16 23:36:04 +04:00
2020-01-20 13:57:07 +04:00
maybe_attributes:
";" { Some $1, None }
| ";" attributes ";" { Some $1, Some $2 }
2020-01-16 23:36:04 +04:00
2019-05-13 00:56:22 +04:00
const_decl:
2020-01-20 13:57:07 +04:00
open_const_decl maybe_attributes? {
match $2 with
None -> $1
| Some (terminator, attributes) ->
let value = {$1.value with terminator; attributes}
in {$1 with value} }
2019-05-13 00:56:22 +04:00
instruction:
conditional { Cond $1 }
| case_instr { CaseInstr $1 }
| assignment { Assign $1 }
| loop { Loop $1 }
| proc_call { ProcCall $1 }
| "skip" { Skip $1 }
2019-05-13 00:56:22 +04:00
| record_patch { RecordPatch $1 }
| map_patch { MapPatch $1 }
| set_patch { SetPatch $1 }
| map_remove { MapRemove $1 }
| set_remove { SetRemove $1 }
set_remove:
"remove" expr "from" "set" path {
2019-05-13 00:56:22 +04:00
let region = cover $1 (path_to_region $5) in
let value = {
kwd_remove = $1;
element = $2;
kwd_from = $3;
kwd_set = $4;
set = $5}
in {region; value} }
2019-05-13 00:56:22 +04:00
map_remove:
"remove" expr "from" "map" path {
2019-05-13 00:56:22 +04:00
let region = cover $1 (path_to_region $5) in
let value = {
kwd_remove = $1;
key = $2;
kwd_from = $3;
kwd_map = $4;
map = $5}
in {region; value} }
2019-05-13 00:56:22 +04:00
set_patch:
"patch" path "with" ne_injection("set",expr) {
2019-05-13 00:56:22 +04:00
let region = cover $1 $4.region in
let value = {
kwd_patch = $1;
path = $2;
kwd_with = $3;
set_inj = $4}
in {region; value} }
2019-05-13 00:56:22 +04:00
map_patch:
"patch" path "with" ne_injection("map",binding) {
2019-05-13 00:56:22 +04:00
let region = cover $1 $4.region in
let value = {
kwd_patch = $1;
path = $2;
kwd_with = $3;
map_inj = $4}
in {region; value} }
2019-05-13 00:56:22 +04:00
injection(Kind,element):
Kind sep_or_term_list(element,";") "end" {
let elements, terminator = $2 in
let region = cover $1 $3
2019-05-13 00:56:22 +04:00
and value = {
opening = Kwd $1;
elements = Some elements;
2019-05-13 00:56:22 +04:00
terminator;
closing = End $3}
2019-05-13 00:56:22 +04:00
in {region; value}
}
| Kind "end" {
2019-05-13 00:56:22 +04:00
let region = cover $1 $2
and value = {
opening = Kwd $1;
elements = None;
terminator = None;
closing = End $2}
in {region; value}
}
| Kind "[" sep_or_term_list(element,";") "]" {
let elements, terminator = $3 in
let region = cover $1 $4
2019-05-13 00:56:22 +04:00
and value = {
opening = KwdBracket ($1,$2);
elements = Some elements;
2019-05-13 00:56:22 +04:00
terminator;
closing = RBracket $4}
2019-05-13 00:56:22 +04:00
in {region; value}
}
| Kind "[" "]" {
2019-05-13 00:56:22 +04:00
let region = cover $1 $3
and value = {
opening = KwdBracket ($1,$2);
elements = None;
terminator = None;
closing = RBracket $3}
in {region; value} }
2019-05-13 00:56:22 +04:00
ne_injection(Kind,element):
Kind sep_or_term_list(element,";") "end" {
let ne_elements, terminator = $2 in
let region = cover $1 $3
and value = {
opening = Kwd $1;
ne_elements;
terminator;
closing = End $3}
in {region; value}
}
| Kind "[" sep_or_term_list(element,";") "]" {
let ne_elements, terminator = $3 in
let region = cover $1 $4
and value = {
opening = KwdBracket ($1,$2);
ne_elements;
terminator;
closing = RBracket $4}
in {region; value} }
2019-05-13 00:56:22 +04:00
binding:
expr "->" expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {
source = $1;
arrow = $2;
image = $3}
in {region; value} }
2019-05-13 00:56:22 +04:00
record_patch:
"patch" path "with" ne_injection("record",field_assignment) {
2019-05-13 00:56:22 +04:00
let region = cover $1 $4.region in
let value = {
kwd_patch = $1;
path = $2;
kwd_with = $3;
record_inj = $4}
in {region; value} }
2019-05-13 00:56:22 +04:00
proc_call:
fun_call { $1 }
conditional:
"if" expr "then" if_clause ";"? "else" if_clause {
2019-05-13 00:56:22 +04:00
let region = cover $1 (if_clause_to_region $7) in
let value : AST.conditional = {
2019-05-13 00:56:22 +04:00
kwd_if = $1;
test = $2;
kwd_then = $3;
ifso = $4;
terminator = $5;
kwd_else = $6;
ifnot = $7}
in {region; value} }
if_clause:
2019-10-17 20:33:58 +04:00
instruction { ClauseInstr $1 }
| clause_block { ClauseBlock $1 }
clause_block:
block { LongBlock $1 }
| "{" sep_or_term_list(statement,";") "}" {
2020-01-16 23:36:04 +04:00
let statements, terminator = $2 in
2019-10-17 20:33:58 +04:00
let region = cover $1 $3 in
let value = {lbrace = $1;
2020-01-20 13:57:07 +04:00
inside = (*attributes_to_statement*) statements, terminator;
rbrace = $3} in
2019-10-17 20:33:58 +04:00
ShortBlock {value; region} }
2019-05-13 00:56:22 +04:00
case_instr:
case(if_clause) { $1 if_clause_to_region }
2019-05-13 00:56:22 +04:00
case(rhs):
"case" expr "of" "|"? cases(rhs) "end" {
2019-05-13 00:56:22 +04:00
fun rhs_to_region ->
let region = cover $1 $6 in
let value = {kwd_case = $1;
expr = $2;
opening = Kwd $3;
lead_vbar = $4;
cases = $5 rhs_to_region;
closing = End $6}
2019-05-13 00:56:22 +04:00
in {region; value}
}
| "case" expr "of" "[" "|"? cases(rhs) "]" {
2019-05-13 00:56:22 +04:00
fun rhs_to_region ->
let region = cover $1 $7 in
let value = {kwd_case = $1;
expr = $2;
opening = KwdBracket ($3,$4);
lead_vbar = $5;
cases = $6 rhs_to_region;
closing = RBracket $7}
in {region; value} }
2019-05-13 00:56:22 +04:00
cases(rhs):
nsepseq(case_clause(rhs),"|") {
2019-05-13 00:56:22 +04:00
fun rhs_to_region ->
let mk_clause pre_clause = pre_clause rhs_to_region in
let value = Utils.nsepseq_map mk_clause $1 in
let region = nsepseq_to_region (fun x -> x.region) value
in {region; value} }
2019-05-13 00:56:22 +04:00
case_clause(rhs):
pattern "->" rhs {
Scoping.check_pattern $1;
2019-05-13 00:56:22 +04:00
fun rhs_to_region ->
let start = pattern_to_region $1 in
let region = cover start (rhs_to_region $3)
and value = {pattern=$1; arrow=$2; rhs=$3}
in {region; value} }
2019-05-13 00:56:22 +04:00
assignment:
lhs ":=" rhs {
2019-05-13 00:56:22 +04:00
let stop = rhs_to_region $3 in
let region = cover (lhs_to_region $1) stop
and value = {lhs = $1; assign = $2; rhs = $3}
in {region; value} }
2019-05-13 00:56:22 +04:00
rhs:
expr { $1 }
2019-05-13 00:56:22 +04:00
lhs:
path { Path $1 }
| map_lookup { MapPath $1 }
loop:
while_loop { $1 }
| for_loop { $1 }
while_loop:
"while" expr block {
2019-05-13 00:56:22 +04:00
let region = cover $1 $3.region
and value = {kwd_while=$1; cond=$2; block=$3}
in While {region; value} }
2019-05-13 00:56:22 +04:00
for_loop:
"for" var_assign "to" expr block {
let region = cover $1 $5.region in
let value = {kwd_for = $1;
assign = $2;
kwd_to = $3;
bound = $4;
block = $5}
2019-05-13 00:56:22 +04:00
in For (ForInt {region; value})
}
| "for" var arrow_clause? "in" collection expr block {
Scoping.check_reserved_name $2;
let region = cover $1 $7.region in
let value = {kwd_for = $1;
var = $2;
bind_to = $3;
kwd_in = $4;
collection = $5;
expr = $6;
block = $7}
in For (ForCollect {region; value}) }
2019-05-13 00:56:22 +04:00
collection:
"map" { Map $1 }
| "set" { Set $1 }
| "list" { List $1 }
2019-05-13 00:56:22 +04:00
var_assign:
var ":=" expr {
Scoping.check_reserved_name $1;
let region = cover $1.region (expr_to_region $3)
and value = {name=$1; assign=$2; expr=$3}
in {region; value} }
2019-05-13 00:56:22 +04:00
arrow_clause:
"->" var { Scoping.check_reserved_name $2; ($1,$2) }
2019-05-13 00:56:22 +04:00
(* Expressions *)
interactive_expr:
expr EOF { $1 }
expr:
case(expr) { ECase ($1 expr_to_region) }
| cond_expr { $1 }
2019-07-31 12:19:24 +04:00
| disj_expr { $1 }
| fun_expr { EFun $1 }
2019-05-13 00:56:22 +04:00
cond_expr:
"if" expr "then" expr ";"? "else" expr {
let region = cover $1 (expr_to_region $7) in
let value : AST.cond_expr = {
kwd_if = $1;
test = $2;
kwd_then = $3;
ifso = $4;
terminator = $5;
kwd_else = $6;
ifnot = $7}
in ECond {region; value} }
2019-05-13 00:56:22 +04:00
disj_expr:
conj_expr { $1 }
| disj_expr "or" conj_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1=$1; op=$2; arg2=$3} in
ELogic (BoolExpr (Or {region; value})) }
2019-05-13 00:56:22 +04:00
conj_expr:
set_membership { $1 }
| conj_expr "and" set_membership {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1=$1; op=$2; arg2=$3}
in ELogic (BoolExpr (And {region; value})) }
2019-05-13 00:56:22 +04:00
set_membership:
comp_expr { $1 }
| core_expr "contains" set_membership {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop in
let value = {set=$1; kwd_contains=$2; element=$3}
in ESet (SetMem {region; value}) }
2019-05-13 00:56:22 +04:00
comp_expr:
comp_expr "<" cat_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in ELogic (CompExpr (Lt {region; value}))
}
| comp_expr "<=" cat_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in ELogic (CompExpr (Leq {region; value}))
}
| comp_expr ">" cat_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in ELogic (CompExpr (Gt {region; value}))
}
| comp_expr ">=" cat_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in ELogic (CompExpr (Geq {region; value}))
}
| comp_expr "=" cat_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in ELogic (CompExpr (Equal {region; value}))
}
| comp_expr "=/=" cat_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in ELogic (CompExpr (Neq {region; value}))
}
| cat_expr { $1 }
cat_expr:
cons_expr "^" cat_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in EString (Cat {region; value})
}
| cons_expr { $1 }
cons_expr:
add_expr "#" cons_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
2019-11-06 20:23:49 +04:00
in EList (ECons {region; value})
2019-05-13 00:56:22 +04:00
}
| add_expr { $1 }
add_expr:
add_expr "+" mult_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in EArith (Add {region; value})
}
| add_expr "-" mult_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in EArith (Sub {region; value})
}
| mult_expr { $1 }
mult_expr:
mult_expr "*" unary_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in EArith (Mult {region; value})
}
| mult_expr "/" unary_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in EArith (Div {region; value})
}
| mult_expr "mod" unary_expr {
2019-05-13 00:56:22 +04:00
let start = expr_to_region $1
and stop = expr_to_region $3 in
let region = cover start stop
and value = {arg1 = $1; op = $2; arg2 = $3}
in EArith (Mod {region; value})
}
| unary_expr { $1 }
unary_expr:
"-" core_expr {
2019-05-13 00:56:22 +04:00
let stop = expr_to_region $2 in
let region = cover $1 stop
and value = {op = $1; arg = $2}
in EArith (Neg {region; value})
}
| "not" core_expr {
2019-05-13 00:56:22 +04:00
let stop = expr_to_region $2 in
let region = cover $1 stop
and value = {op = $1; arg = $2} in
ELogic (BoolExpr (Not {region; value}))
}
| core_expr { $1 }
core_expr:
"<int>" { EArith (Int $1) }
| "<nat>" { EArith (Nat $1) }
| "<mutez>" { EArith (Mutez $1) }
| var { EVar $1 }
| "<string>" { EString (String $1) }
| "<bytes>" { EBytes $1 }
| "False" { ELogic (BoolExpr (False $1)) }
| "True" { ELogic (BoolExpr (True $1)) }
| "Unit" { EUnit $1 }
| annot_expr { EAnnot $1 }
| tuple_expr { ETuple $1 }
| list_expr { EList $1 }
| "None" { EConstr (NoneExpr $1) }
| fun_call_or_par_or_projection { $1 }
| map_expr { EMap $1 }
| set_expr { ESet $1 }
| record_expr { ERecord $1 }
2020-01-09 21:23:37 +04:00
| update_record { EUpdate $1 }
| "<constr>" arguments {
2019-05-13 00:56:22 +04:00
let region = cover $1.region $2.region in
EConstr (ConstrApp {region; value = $1, Some $2})
}
| "<constr>" {
EConstr (ConstrApp {region=$1.region; value = $1,None})
2019-05-13 00:56:22 +04:00
}
| "Some" arguments {
2019-05-13 00:56:22 +04:00
let region = cover $1 $2.region in
EConstr (SomeApp {region; value = $1,$2}) }
fun_call_or_par_or_projection:
par(expr) arguments? {
let parenthesized = EPar $1 in
match $2 with
None -> parenthesized
| Some args ->
let region_1 = $1.region in
let region = cover region_1 args.region in
ECall {region; value = parenthesized,args}
}
| projection arguments? {
let project = EProj $1 in
match $2 with
None -> project
| Some args ->
let region_1 = $1.region in
let region = cover region_1 args.region
in ECall {region; value = project,args}
}
| fun_call { ECall $1 }
annot_expr:
"(" disj_expr ":" type_expr ")" {
let start = expr_to_region $2
and stop = type_expr_to_region $4 in
let region = cover start stop
and value = $2, $4
in {region; value} }
2019-05-13 00:56:22 +04:00
set_expr:
injection("set",expr) { SetInj $1 }
2019-05-13 00:56:22 +04:00
map_expr:
map_lookup { MapLookUp $1 }
| injection("map",binding) { MapInj $1 }
| injection("big_map",binding) { BigMapInj $1 }
2019-05-13 00:56:22 +04:00
map_lookup:
path brackets(expr) {
let region = cover (path_to_region $1) $2.region in
let value = {path=$1; index=$2}
in {region; value} }
2019-05-13 00:56:22 +04:00
path:
var { Name $1 }
| projection { Path $1 }
projection:
struct_name "." nsepseq(selection,".") {
2019-05-13 00:56:22 +04:00
let stop = nsepseq_to_region selection_to_region $3 in
let region = cover $1.region stop
and value = {struct_name = $1;
selector = $2;
field_path = $3}
in {region; value} }
2019-05-13 00:56:22 +04:00
selection:
field_name { FieldName $1 }
| "<int>" { Component $1 }
2019-05-13 00:56:22 +04:00
record_expr:
"record" sep_or_term_list(field_assignment,";") "end" {
2019-11-06 20:23:49 +04:00
let ne_elements, terminator = $2 in
let region = cover $1 $3
2019-11-06 20:23:49 +04:00
and value : field_assign AST.reg ne_injection = {
2019-05-13 00:56:22 +04:00
opening = Kwd $1;
2019-11-06 20:23:49 +04:00
ne_elements;
2019-05-13 00:56:22 +04:00
terminator;
closing = End $3}
2019-05-13 00:56:22 +04:00
in {region; value}
}
| "record" "[" sep_or_term_list(field_assignment,";") "]" {
2019-11-06 20:23:49 +04:00
let ne_elements, terminator = $3 in
let region = cover $1 $4
2019-11-06 20:23:49 +04:00
and value : field_assign AST.reg ne_injection = {
2019-05-13 00:56:22 +04:00
opening = KwdBracket ($1,$2);
2019-11-06 20:23:49 +04:00
ne_elements;
2019-05-13 00:56:22 +04:00
terminator;
closing = RBracket $4}
2019-05-13 00:56:22 +04:00
in {region; value} }
2020-01-09 21:23:37 +04:00
update_record:
path "with" ne_injection("record",field_assignment){
let region = cover (path_to_region $1) $3.region in
let value = {
record = $1;
kwd_with = $2;
updates = $3}
in {region; value} }
2019-05-13 00:56:22 +04:00
field_assignment:
field_name "=" expr {
2019-05-13 00:56:22 +04:00
let region = cover $1.region (expr_to_region $3)
and value = {field_name = $1;
equal = $2;
field_expr = $3}
in {region; value} }
2019-05-13 00:56:22 +04:00
fun_call:
fun_name arguments {
let region = cover $1.region $2.region
in {region; value = (EVar $1),$2} }
2019-05-13 00:56:22 +04:00
tuple_expr:
par(tuple_comp) { $1 }
2019-05-13 00:56:22 +04:00
tuple_comp:
expr "," nsepseq(expr,",") { Utils.nsepseq_cons $1 $2 $3 }
2019-05-13 00:56:22 +04:00
arguments:
par(nsepseq(expr,",")) { $1 }
2019-05-13 00:56:22 +04:00
list_expr:
injection("list",expr) { EListComp $1 }
| "nil" { ENil $1 }
2019-05-13 00:56:22 +04:00
(* Patterns *)
pattern:
core_pattern { $1 }
| core_pattern "#" nsepseq(core_pattern,"#") {
let value = Utils.nsepseq_cons $1 $2 $3 in
let region = nsepseq_to_region pattern_to_region value
in PList (PCons {region; value}) }
2019-05-13 00:56:22 +04:00
core_pattern:
var { PVar $1 }
| "_" { PWild $1 }
| "<int>" { PInt $1 }
| "<nat>" { PNat $1 }
| "<bytes>" { PBytes $1 }
| "<string>" { PString $1 }
| list_pattern { PList $1 }
| tuple_pattern { PTuple $1 }
| constr_pattern { PConstr $1 }
2019-05-13 00:56:22 +04:00
list_pattern:
injection("list",core_pattern) { PListComp $1 }
| "nil" { PNil $1 }
| par(cons_pattern) { PParCons $1 }
2019-05-13 00:56:22 +04:00
cons_pattern:
core_pattern "#" pattern { $1,$2,$3 }
2019-05-13 00:56:22 +04:00
tuple_pattern:
par(nsepseq(core_pattern,",")) { $1 }
2019-05-13 00:56:22 +04:00
constr_pattern:
"Unit" { PUnit $1 }
| "False" { PFalse $1 }
| "True" { PTrue $1 }
| "None" { PNone $1 }
| "Some" par(core_pattern) {
2019-11-06 20:23:49 +04:00
let region = cover $1 $2.region
in PSomeApp {region; value = $1,$2}
}
| "<constr>" tuple_pattern {
let region = cover $1.region $2.region in
PConstrApp {region; value = $1, Some $2}
}
| "<constr>" {
PConstrApp {region=$1.region; value=$1,None} }