let min_precedence = 0
let max_precedence = 100
-let default_precedence = 50
-
-let let_in_prec = 10
-let binder_prec = 20
-let apply_prec = 70
-let simple_prec = 90
-
-let let_in_assoc = Gramext.NonA
-let binder_assoc = Gramext.RightA
-let apply_assoc = Gramext.LeftA
-let simple_assoc = Gramext.NonA
let level1_pattern =
Grammar.Entry.create level1_pattern_grammar "level1_pattern"
let level2_ast = Grammar.Entry.create level2_ast_grammar "level2_ast"
let term = Grammar.Entry.create level2_ast_grammar "term"
+let let_defs = Grammar.Entry.create level2_ast_grammar "let_defs"
let level2_meta = Grammar.Entry.create level2_meta_grammar "level2_meta"
-let level3_term = Grammar.Entry.create level2_ast_grammar "level3_term"
-let notation = (* level1 <-> level 2 *)
- Grammar.Entry.create level2_ast_grammar "notation"
-let interpretation = (* level2 <-> level 3 *)
- Grammar.Entry.create level2_ast_grammar "interpretation"
-let phrase = Grammar.Entry.create level2_ast_grammar "phrase"
-
let return_term loc term = ()
-let fail floc msg =
- let (x, y) = loc_of_floc floc in
- failwith (sprintf "Error at characters %d - %d: %s" x y msg)
-
let int_of_string s =
try
Pervasives.int_of_string s
in
aux pattern
-let level_of_int precedence =
+let level_of precedence associativity =
if precedence < min_precedence || precedence > max_precedence then
raise (Level_not_found precedence);
- string_of_int precedence
+ let assoc_string =
+ match associativity with
+ | Gramext.NonA -> "N"
+ | Gramext.LeftA -> "L"
+ | Gramext.RightA -> "R"
+ in
+ string_of_int precedence ^ assoc_string
type rule_id = Token.t Gramext.g_symbol list
(* mapping: rule_id -> owned keywords. (rule_id, string list) Hashtbl.t *)
let owned_keywords = Hashtbl.create 23
-let extend level1_pattern ?(precedence = default_precedence)
- ?associativity action
-=
+let extend level1_pattern ~precedence ~associativity action =
let p_bindings, p_atoms =
List.split (extract_term_production level1_pattern)
in
- let level = level_of_int precedence in
+ let level = level_of precedence associativity in
let p_names = flatten_opt p_bindings in
let _ =
Grammar.extend
[ Grammar.Entry.obj (term: 'a Grammar.Entry.e),
Some (Gramext.Level level),
[ None,
- associativity,
+ Some associativity,
[ p_atoms,
(make_action
(fun (env: CicNotationEnv.t) (loc: location) -> (action env loc))
let parse_level2_ast_ref = ref (fun _ -> assert false)
let parse_level2_meta_ref = ref (fun _ -> assert false)
+let fold_cluster binder terms ty body =
+ List.fold_right
+ (fun term body -> Binder (binder, (term, ty), body))
+ terms body (* terms are names: either Ident or FreshVar *)
+
let fold_binder binder pt_names body =
- let fold_cluster binder terms ty body =
- List.fold_right
- (fun term body -> Binder (binder, (term, ty), body))
- terms body (* terms are names: either Ident or FreshVar *)
- in
List.fold_right
(fun (names, ty) body -> fold_cluster binder names ty body)
pt_names body
let mk_level_list first last =
let rec aux acc = function
| i when i < first -> acc
- | i -> aux ((Some (string_of_int i), None, []) :: acc) (i - 1)
+ | i ->
+ aux
+ ((Some (string_of_int i ^ "N"), Some Gramext.NonA, [])
+ :: (Some (string_of_int i ^ "L"), Some Gramext.LeftA, [])
+ :: (Some (string_of_int i ^ "R"), Some Gramext.RightA, [])
+ :: acc)
+ (i - 1)
in
aux [] last
in
| SYMBOL "\\frac"; p1 = SELF; p2 = SELF ->
return_term loc (Layout (Frac (p1, p2)))
| SYMBOL "\\sqrt"; p = SELF -> return_term loc (Layout (Sqrt p))
- | SYMBOL "\\root"; index = SELF; SYMBOL "\\OF"; arg = SELF ->
+ | SYMBOL "\\root"; index = SELF; SYMBOL "\\of"; arg = SELF ->
return_term loc (Layout (Root (arg, index)))
| "hbox"; LPAREN; p = l1_pattern; RPAREN ->
return_term loc (Layout (Box ((H, false, false), p)))
END
(* }}} *)
-
+(* {{{ Grammar for ast magics, notation level 2 *)
EXTEND
GLOBAL: level2_meta;
l2_variable: [
]
];
END
+(* }}} *)
-EXTEND
- GLOBAL: level2_ast term
- level3_term
- notation interpretation
- phrase;
(* {{{ Grammar for ast patterns, notation level 2 *)
+EXTEND
+ GLOBAL: level2_ast term let_defs;
level2_ast: [ [ p = term -> p ] ];
sort: [
[ "Prop" -> `Prop
| "Set" -> `Set
| "Type" -> `Type
+ | "CProp" -> `CProp
]
];
explicit_subst: [
[ SYMBOL "["; substs = LIST0 meta_subst; SYMBOL "]" -> substs ]
];
possibly_typed_name: [
- [ LPAREN; id = bound_name; SYMBOL ":"; typ = term; RPAREN ->
+ [ LPAREN; id = single_arg; SYMBOL ":"; typ = term; RPAREN ->
id, Some typ
- | id = bound_name -> id, None
+ | arg = single_arg -> arg, None
]
];
match_pattern: [
| SYMBOL <:unicode<lambda>> (* λ *) -> `Lambda
]
];
- bound_name: [
- [ i = IDENT -> Ident (i, None)
- | SYMBOL "\\FRESH"; i = IDENT -> Variable (FreshVar i)
- ]
+ arg: [
+ [ LPAREN; names = LIST1 IDENT SEP SYMBOL ",";
+ SYMBOL ":"; ty = term; RPAREN ->
+ List.map (fun n -> Ident (n, None)) names, Some ty
+ | name = IDENT -> [Ident (name, None)], None
+ | blob = UNPARSED_META ->
+ let meta = !parse_level2_meta_ref (Stream.of_string blob) in
+ match meta with
+ | Variable (FreshVar _) -> [meta], None
+ | Variable (TermVar "_") -> [Ident ("_", None)], None
+ | _ -> failwith "Invalid bound name."
+ ]
];
- bound_names: [
- [ vars = LIST1 bound_name SEP SYMBOL ",";
- ty = OPT [ SYMBOL ":"; p = term -> p ] ->
- [ vars, ty ]
- | clusters = LIST1 [
- LPAREN;
- vars = LIST1 bound_name SEP SYMBOL ",";
- ty = OPT [ SYMBOL ":"; p = term -> p ];
- RPAREN ->
- vars, ty
- ] ->
- clusters
+ single_arg: [
+ [ name = IDENT -> Ident (name, None)
+ | blob = UNPARSED_META ->
+ let meta = !parse_level2_meta_ref (Stream.of_string blob) in
+ match meta with
+ | Variable (FreshVar _) -> meta
+ | Variable (TermVar "_") -> Ident ("_", None)
+ | _ -> failwith "Invalid index name."
]
];
induction_kind: [
];
let_defs: [
[ defs = LIST1 [
- name = bound_name; args = bound_names;
- index_name = OPT [ "on"; id = bound_name -> id ];
+ name = single_arg;
+ args = LIST1 arg;
+ index_name = OPT [ "on"; id = single_arg -> id ];
ty = OPT [ SYMBOL ":" ; p = term -> p ];
SYMBOL <:unicode<def>> (* ≝ *); body = term ->
let body = fold_binder `Lambda args body in
let index =
match index_name with
| None -> 0
- | Some name -> find_arg name 0 args
+ | Some index_name -> find_arg index_name 0 args
in
(name, ty), body, index
] SEP "and" ->
defs
]
];
- term: LEVEL "10" (* let in *)
- [ "10" NONA
- [ "let"; var = possibly_typed_name; SYMBOL <:unicode<def>> (* ≝ *);
- p1 = term; "in"; p2 = term ->
- return_term loc (LetIn (var, p1, p2))
- | "let"; k = induction_kind; defs = let_defs; "in";
- body = term ->
- return_term loc (LetRec (k, defs, body))
- ]
- ];
- term: LEVEL "20" (* binder *)
- [ "20" RIGHTA
- [ b = binder; names = bound_names; SYMBOL "."; body = term ->
- return_term loc (fold_binder b names body)
+ binder_vars: [
+ [ vars = [
+ l = LIST1 single_arg SEP SYMBOL "," -> l
+ | SYMBOL "_" -> [Ident ("_", None)] ];
+ typ = OPT [ SYMBOL ":"; t = term -> t ] -> (vars, typ)
+ | LPAREN;
+ vars = [
+ l = LIST1 single_arg SEP SYMBOL "," -> l
+ | SYMBOL "_" -> [Ident ("_", None)] ];
+ typ = OPT [ SYMBOL ":"; t = term -> t ];
+ RPAREN -> (vars, typ)
+ ]
+ ];
+ term: LEVEL "10N" [ (* let in *)
+ [ "let"; var = possibly_typed_name; SYMBOL <:unicode<def>> (* ≝ *);
+ p1 = term; "in"; p2 = term ->
+ return_term loc (LetIn (var, p1, p2))
+ | "let"; k = induction_kind; defs = let_defs; "in";
+ body = term ->
+ return_term loc (LetRec (k, defs, body))
+ ]
+ ];
+ term: LEVEL "20R" (* binder *)
+ [
+ [ b = binder; (vars, typ) = binder_vars; SYMBOL "."; body = term ->
+ return_term loc (fold_cluster b vars typ body)
]
];
- term: LEVEL "70" (* apply *)
- [ "70" LEFTA
+ term: LEVEL "70L" (* apply *)
+ [
[ p1 = term; p2 = term ->
let rec aux = function
| Appl (hd :: tl)
return_term loc (Appl (aux p1 @ [p2]))
]
];
- term: LEVEL "90" (* simple *)
- [ "90" NONA
+ term: LEVEL "90N" (* simple *)
+ [
[ id = IDENT -> return_term loc (Ident (id, None))
| id = IDENT; s = explicit_subst -> return_term loc (Ident (id, Some s))
| s = CSYMBOL -> return_term loc (Symbol (s, 0))
| u = URI -> return_term loc (Uri (u, None))
| n = NUMBER -> return_term loc (Num (n, 0))
| IMPLICIT -> return_term loc (Implicit)
+ | PLACEHOLDER -> return_term loc UserInput
| m = META -> return_term loc (Meta (int_of_string m, []))
| m = META; s = meta_substs -> return_term loc (Meta (int_of_string m, s))
| s = sort -> return_term loc (Sort s)
| outtyp = OPT [ SYMBOL "["; ty = term; SYMBOL "]" -> ty ];
"match"; t = term;
- indty_ident = OPT [ SYMBOL ":"; id = IDENT -> id ];
+ indty_ident = OPT [ "in"; id = IDENT -> id ];
"with"; SYMBOL "[";
patterns = LIST0 [
lhs = match_pattern; SYMBOL <:unicode<Rightarrow>> (* ⇒ *);
SYMBOL "]" ->
return_term loc (Case (t, indty_ident, outtyp, patterns))
| LPAREN; p1 = term; SYMBOL ":"; p2 = term; RPAREN ->
- return_term loc (Appl [ Symbol ("cast", 0); p1; p2 ])
+ return_term loc (Cast (p1, p2))
| LPAREN; p = term; RPAREN -> p
| blob = UNPARSED_META -> !parse_level2_meta_ref (Stream.of_string blob)
]
];
-(* }}} *)
-(* {{{ Grammar for interpretation, notation level 3 *)
- argument: [
- [ id = IDENT -> IdentArg (0, id)
- | l = LIST1 [ SYMBOL <:unicode<eta>> (* η *) -> () ] SEP SYMBOL ".";
- SYMBOL "."; id = IDENT ->
- IdentArg (List.length l, id)
- ]
- ];
- level3_term: [
- [ u = URI -> UriPattern (UriManager.uri_of_string u)
- | id = IDENT -> VarPattern id
- | LPAREN; terms = LIST1 SELF; RPAREN ->
- (match terms with
- | [] -> assert false
- | [term] -> term
- | terms -> ApplPattern terms)
- ]
- ];
-(* }}} *)
-(* {{{ Notation glues *)
- associativity: [
- [ IDENT "left"; IDENT "associative" -> Gramext.LeftA
- | IDENT "right"; IDENT "associative" -> Gramext.RightA
- | IDENT "non"; IDENT "associative" -> Gramext.NonA
- ]
- ];
- precedence: [
- [ "with"; IDENT "precedence"; n = NUMBER -> int_of_string n ]
- ];
- notation: [
- [ s = QSTRING;
- assoc = OPT associativity; prec = OPT precedence;
- IDENT "for";
- p2 =
- [ blob = UNPARSED_AST -> !parse_level2_ast_ref (Stream.of_string blob)
- | blob = UNPARSED_META ->
- !parse_level2_meta_ref (Stream.of_string blob) ]
- ->
- (!parse_level1_pattern_ref (Stream.of_string s), assoc, prec, p2)
- ]
- ];
- interpretation: [
- [ s = CSYMBOL; args = LIST1 argument; SYMBOL "="; t = level3_term ->
- (s, args, t)
- ]
- ];
-(* }}} *)
-(* {{{ Top-level phrases *)
- phrase: [
- [ IDENT "print"; t = term; SYMBOL "." -> Print t
- | IDENT "notation"; (l1, assoc, prec, l2) = notation; SYMBOL "." ->
- Notation (l1, assoc, prec, l2)
- | IDENT "interpretation"; (symbol, args, l3) = interpretation; SYMBOL "." ->
- Interpretation ((symbol, args), l3)
- | IDENT "render"; u = URI; SYMBOL "." -> Render (UriManager.uri_of_string u)
- | IDENT "dump"; SYMBOL "." -> Dump
- ]
- ];
-(* }}} *)
END
+(* }}} *)
(** {2 API implementation} *)
exc_located_wrapper (fun () -> Grammar.Entry.parse level2_ast stream)
let parse_level2_meta stream =
exc_located_wrapper (fun () -> Grammar.Entry.parse level2_meta stream)
-let parse_interpretation stream =
- exc_located_wrapper (fun () -> Grammar.Entry.parse level3_term stream)
-let parse_phrase stream =
- exc_located_wrapper (fun () -> Grammar.Entry.parse phrase stream)
let _ =
parse_level1_pattern_ref := parse_level1_pattern;