right_assoc(item,op) ::= item | item op right_assoc(item,op) left_assoc(item,op) ::= right_assoc(item,op) option(item) := (**) | item series(item,sep,term) ::= item after_item(item,sep,term) after_item(item,sep,term) ::= sep item_or_closing(item,sep,term) | term item_or_closing(item,sep,term) ::= term | series(item,sep,term) (* Compound constructs *) par(item) ::= LPAR item RPAR brackets(item) ::= LBRACKET item RBRACKET (* Sequences *) (* Possibly empty sequence of items LL(1) constraint: item not in Follow(seq), where Follow(seq) = Follow(nseq) = {EOF, Begin, Block} *) seq(item) ::= option(nseq(item)) (* Non-empty sequence of items *) nseq(item) ::= item seq(item) (* Non-empty separated sequence of items *) nsepseq(item,Sep) ::= item | item Sep nsepseq(item,Sep) (* Main *) contract ::= nseq(declaration) EOF (* LL(1) constraint: SEMI not in Follow(declaration), where Follow(declaration) = {EOF} U First(declaration) = {EOF} U First(type_decl) U First(const_decl) U First(lambda_decl) = {EOF} U {Type} U {Const} U First(fun_decl) U First(proc_decl) U First(entry_decl) = {EOF,Type,Const,Function,Procedure,Entrypoint}. *) declaration ::= type_decl option(SEMI) | const_decl option(SEMI) | lambda_decl option(SEMI) (* Type declarations *) type_decl ::= Type Ident Is type_expr type_expr ::= cartesian | nsepseq(variant,VBAR) | VBAR nsepseq(variant,VBAR) | Record record_type_expr record_type_expr ::= series(field_decl,SEMI,End) | LBRACKET series(field_decl,SEMI,RBRACKET) (* LL(1) constraint: Of not in Follow(variant). "Of" only occurs after {Constr, expr}. *) variant ::= Constr option(of_cartesian) of_cartesian ::= Of cartesian cartesian ::= nsepseq(function_type,TIMES) function_type ::= right_assoc(core_type,ARROW) (* LL(1) constraint: LPAR not in Follow(core_type), where Follow(core_type) = {ARROW} U Follow(function_type) = {ARROW} U {TIMES} U Follow(cartesian) = {ARROW,TIMES} U Follow(of_cartesian) U Follow(type_expr) U Follow(param_type) = {ARROW,TIMES} U Follow(variant) U {RPAR,COMMA,Is,EQUAL,ASS} U Follow(field_decl) U Follow(paren_expr_1) U Follow(type_decl) U Follow(param_decl) U Follow(entry_param_decl) = {ARROW,TIMES,RPAR,COMMA,Is,EQUAL,ASS,VBAR, SEMI,End,RBRACKET} U Follow(paren_expr) U {SEMI} U Follow(declaration) = {ARROW,TIMES,RPAR,COMMA,Is,EQUAL,ASS,VBAR, SEMI,End,RBRACKET,EOF,Type,Const, Function,Procedure,Entrypoint}. *) core_type ::= Ident (* type_name *) option(type_tuple) | Map type_tuple | Set par(type_expr) | List par(type_expr) | par(type_expr) type_tuple ::= par(nsepseq(type_expr,COMMA)) field_decl ::= Ident (* field_name *) COLON type_expr (* Function and procedure declarations *) lambda_decl ::= fun_decl | proc_decl | entry_decl fun_decl ::= Function Ident parameters COLON type_expr Is seq(local_decl) block With expr entry_decl ::= Entrypoint Ident entry_params COLON type_expr Is seq(local_decl) block With expr entry_params ::= par(nsepseq(entry_param_decl,SEMI)) proc_decl ::= Procedure Ident parameters Is seq(local_decl) block parameters ::= par(nsepseq(param_decl,SEMI)) param_decl ::= Var Ident COLON param_type | Const Ident COLON param_type entry_param_decl ::= param_decl | Storage Ident COLON param_type param_type ::= cartesian block ::= Begin series(statement,SEMI,End) | Block LBRACE series(statement,SEMI,RBRACE) statement ::= instruction | data_decl data_decl ::= const_decl | var_decl const_decl ::= Const unqualified_decl(EQUAL) var_decl ::= Var unqualified_decl(ASS) (* LL(1) constraint: SEMI not in Follow(local_decl), where Follow(local_decl) = First(local_decl) U First(block) = First(fun_decl) U First(proc_decl) U First(data_decl) U {BEGIN,Block} = {Function,Procedure,BEGIN,Block} U First(const_decl) U First(var_decl) = {Function,Procedure,BEGIN,Block,Const,Var}. *) local_decl ::= fun_decl option(SEMI) | proc_decl option(SEMI) | data_decl option(SEMI) unqualified_decl(op) ::= Ident (* var *) COLON type_expr op expr instruction ::= block | If expr Then if_clause option(SEMI) Else if_clause | case(instruction) | Ident instruction_1 | loop | Fail expr | Skip | Patch path With structure | Remove expr From remove_suffix remove_suffix ::= Map path | Set path instruction_1 ::= arguments | ASS expr | brackets(expr) ASS expr | selections option(brackets(expr)) ASS expr (* LL(1) constraint: First(selections) not in Follow(path), where First(selections) = {DOT} and Follow(path) = {With} U Follow(remove_suffix) = {With} U Follow(instruction) = {With} U Follow(statement) U Follow(if_clause) U Follow(case_clause(instruction)) = {With,SEMI,End,Else,VBAR} U Follow(cases(instruction)) = {With,SEMI,End,Else,VBAR,RBRACKET}. *) path ::= Ident option(selections) selections ::= DOT nsepseq(selection,DOT) injection(Kind,element) ::= Kind inj_sufffix(element) inj_suffix(element) ::= series(element,SEMI,End) | End | LBRACKET bracketed(element) bracketed(element) ::= series(element,SEMI,RBRACKET) | RBRACKET binding ::= expr ARROW expr if_clause ::= instruction | LBRACE series(statement,COMMA,RBRACE) case(rhs) ::= Case expr Of case_suffix(rhs) case_suffix(rhs) ::= cases(rhs) End | LBRACKET cases(rhs) RBRACKET cases(rhs) ::= nsepseq(case_clause(rhs),VBAR) | VBAR nsepseq(case_clause(rhs),VBAR) case_clause(rhs) ::= pattern ARROW rhs loop ::= While expr block | For Ident for_suffix for_suffix ::= ASS expr option(Down) To expr option(step_clause) block | In expr block | ARROW Ident In expr block step_clause ::= Step expr (* Expressions *) interactive_expr ::= expr EOF expr ::= case(expr) | disj_expr disj_expr ::= left_assoc(conj_expr,Or) conj_expr ::= left_assoc(set_membership,And) set_membership ::= comp_expr option(contains_clause) (* Enlarged the language *) contains_clause ::= Contains set_membership comp_expr ::= left_assoc(cat_expr,op_comp) op_comp ::= LT | LEQ | GT | GEQ | EQUAL | NEQ cat_expr ::= right_assoc(cons_expr,CAT) cons_expr ::= left_assoc(add_expr,CONS) add_expr ::= left_assoc(mult_expr,add_op) add_op ::= PLUS | MINUS mult_expr ::= left_assoc(unary_expr,mult_op) mult_op ::= TIMES | SLASH | Mod unary_expr ::= MINUS core_expr | Not core_expr | core_expr (* LL(1) constraint: First(core_suffix) not in Follow(core_expr) First(core_suffix) = XXX *) core_expr ::= Int | Nat | Mtz | Ident option(core_suffix) | String | Bytes | C_False | C_True | C_Unit | C_None | C_Some arguments | Constr option(arguments) | par(paren_expr) | injection(List,expr) | Nil | structure core_suffix ::= brackets(expr) (* lookup *) | DOT nsepseq(selection,DOT) option(brackets(expr)) | arguments paren_expr ::= disj_expr option(paren_expr_1) | case(expr) option(paren_expr_2) paren_expr_1 ::= COLON type_expr | COMMA nsepseq(expr,COMMA) paren_expr_2 ::= COMMA nsepseq(expr,COMMA) structure ::= injection(Map,binding) | injection(Set,expr) | record_expr selection ::= Ident (* field_name *) | Int record_expr ::= Record record_expr_suffix record_expr_suffix ::= series(field_assignment,SEMI,End) | LBRACKET series(field_assignment,SEMI,RBRACKET) field_assignment ::= Ident (* field_name *) EQUAL expr arguments ::= par(nsepseq(expr,COMMA)) (* Patterns *) pattern ::= nsepseq(core_pattern,CONS) core_pattern ::= Ident (* var *) | WILD | Int | String | C_Unit | C_False | C_True | C_None | C_Some par(core_pattern) | Constr option(tuple_pattern) | injection(List,core_pattern) | Nil | par(option(paren_pattern)) paren_pattern ::= core_pattern paren_pattern_suffix paren_pattern_suffix ::= CONS pattern | COMMA nsepseq(core_pattern,COMMA) tuple_pattern ::= par(nsepseq(core_pattern,COMMA))