aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--Makefile5
-rw-r--r--contrib/interface/name_to_ast.ml2
-rw-r--r--contrib/interface/xlate.ml6
-rw-r--r--interp/symbols.ml11
-rw-r--r--interp/symbols.mli3
-rw-r--r--parsing/extend.ml66
-rw-r--r--parsing/extend.mli18
-rw-r--r--parsing/g_basevernac.ml413
-rw-r--r--parsing/g_vernac.ml49
-rw-r--r--parsing/g_vernacnew.ml424
-rw-r--r--parsing/pcoq.ml431
-rw-r--r--toplevel/command.ml23
-rw-r--r--toplevel/metasyntax.ml113
-rw-r--r--toplevel/metasyntax.mli6
-rw-r--r--toplevel/vernacexpr.ml4
-rw-r--r--translate/ppvernacnew.ml19
16 files changed, 237 insertions, 116 deletions
diff --git a/Makefile b/Makefile
index fc0499ccf..82a7e8d53 100644
--- a/Makefile
+++ b/Makefile
@@ -158,11 +158,10 @@ TACTICS=\
TOPLEVEL=\
toplevel/himsg.cmo toplevel/cerrors.cmo toplevel/class.cmo \
+ toplevel/vernacexpr.cmo toplevel/metasyntax.cmo \
toplevel/command.cmo toplevel/record.cmo toplevel/recordobj.cmo \
- toplevel/discharge.cmo toplevel/vernacexpr.cmo \
- translate/ppvernacnew.cmo \
+ toplevel/discharge.cmo translate/ppvernacnew.cmo \
toplevel/vernacinterp.cmo toplevel/mltop.cmo \
- toplevel/metasyntax.cmo \
toplevel/vernacentries.cmo toplevel/vernac.cmo \
toplevel/line_oriented_parser.cmo toplevel/protectedtoplevel.cmo \
toplevel/toplevel.cmo toplevel/usage.cmo \
diff --git a/contrib/interface/name_to_ast.ml b/contrib/interface/name_to_ast.ml
index ed6980657..ff361e8f4 100644
--- a/contrib/interface/name_to_ast.ml
+++ b/contrib/interface/name_to_ast.ml
@@ -116,7 +116,7 @@ let convert_one_inductive sp tyi =
let env = Global.env () in
let envpar = push_rel_context params env in
let sp = sp_of_global (IndRef (sp, tyi)) in
- (basename sp,
+ (basename sp, None,
convert_env(List.rev params),
(extern_constr true envpar arity),
convert_constructors envpar cstrnames cstrtypes);;
diff --git a/contrib/interface/xlate.ml b/contrib/interface/xlate.ml
index 07deebf4a..5692f780d 100644
--- a/contrib/interface/xlate.ml
+++ b/contrib/interface/xlate.ml
@@ -1536,10 +1536,12 @@ let xlate_vernac =
*)
| VernacInductive (isind, lmi) ->
let co_or_ind = if isind then "Inductive" else "CoInductive" in
- let strip_mutind (s, parameters, c, constructors) =
+ let strip_mutind (s, notopt, parameters, c, constructors) =
+ if notopt = None then
CT_ind_spec
(xlate_ident s, cvt_vernac_binders parameters, xlate_formula c,
- build_constructors constructors) in
+ build_constructors constructors)
+ else xlate_error "TODO: Notation in Inductive" in
CT_mind_decl
(CT_co_ind co_or_ind, CT_ind_spec_list (List.map strip_mutind lmi))
| VernacFixpoint [] -> xlate_error "mutual recursive"
diff --git a/interp/symbols.ml b/interp/symbols.ml
index 0c988f315..ef2cf6b0b 100644
--- a/interp/symbols.ml
+++ b/interp/symbols.ml
@@ -396,6 +396,17 @@ let locate_notation prraw ntn =
fnl ()))
l
+let find_notation_level ntn =
+ let l =
+ Stringmap.fold
+ (fun _ sc l ->
+ try fst (snd (Stringmap.find ntn sc.notations)) :: l
+ with Not_found -> l) !scope_map [] in
+ match l with
+ | [] -> raise Not_found
+ | [prec] -> prec
+ | prec::_ -> warning ("Several parsing rules for notation \""^ntn^"\""); prec
+
(**********************************************************************)
(* Mapping notations to concrete syntax *)
diff --git a/interp/symbols.mli b/interp/symbols.mli
index 42eedaf81..fa3d778f1 100644
--- a/interp/symbols.mli
+++ b/interp/symbols.mli
@@ -117,6 +117,9 @@ val pr_scope : (rawconstr -> std_ppcmds) -> scope_name -> std_ppcmds
val pr_scopes : (rawconstr -> std_ppcmds) -> std_ppcmds
val locate_notation : (rawconstr -> std_ppcmds) -> notation -> std_ppcmds
+(* [raise Not_found] if non existing notation *)
+val find_notation_level : notation -> level
+
(**********************************************************************)
(*s Printing rules for notations *)
diff --git a/parsing/extend.ml b/parsing/extend.ml
index 076f7f026..6a557f368 100644
--- a/parsing/extend.ml
+++ b/parsing/extend.ml
@@ -24,14 +24,20 @@ type production_position =
| BorderProd of bool * Gramext.g_assoc option (* true=left; false=right *)
| InternalProd
-type 'pos constr_entry_key =
+type production_level =
+ | NextLevel
+ | NumLevel of int
+
+type ('lev,'pos) constr_entry_key =
| ETIdent | ETReference | ETBigint
- | ETConstr of (int * 'pos)
+ | ETConstr of ('lev * 'pos)
| ETPattern
| ETOther of string * string
-type constr_production_entry = production_position constr_entry_key
-type constr_entry = unit constr_entry_key
+type constr_production_entry =
+ (production_level,production_position) constr_entry_key
+type constr_entry = (int,unit) constr_entry_key
+type simple_constr_production_entry = (production_level,unit) constr_entry_key
type nonterm_prod =
| ProdList0 of nonterm_prod
@@ -80,10 +86,10 @@ let act_of_ast vars = function
let to_act_check_vars = act_of_ast
type syntax_modifier =
- | SetItemLevel of string list * int
+ | SetItemLevel of string list * production_level
| SetLevel of int
| SetAssoc of Gramext.g_assoc
- | SetEntryType of string * constr_entry
+ | SetEntryType of string * simple_constr_production_entry
| SetOnlyParsing
type nonterm =
@@ -162,44 +168,50 @@ let rename_command_entry nt =
(* This translates constr0, constr1, ... level into camlp4 levels of constr *)
-let explicitize_prod_entry pos univ nt =
+let explicitize_prod_entry inj pos univ nt =
if univ = "prim" & nt = "var" then ETIdent else
if univ = "prim" & nt = "bigint" then ETBigint else
if univ <> "constr" then ETOther (univ,nt) else
match nt with
- | "constr0" -> ETConstr (0,pos)
- | "constr1" -> ETConstr (1,pos)
- | "constr2" -> ETConstr (2,pos)
- | "constr3" -> ETConstr (3,pos)
- | "lassoc_constr4" -> ETConstr (4,pos)
- | "constr5" -> ETConstr (5,pos)
- | "constr6" -> ETConstr (6,pos)
- | "constr7" -> ETConstr (7,pos)
- | "constr8" -> ETConstr (8,pos)
- | "constr" when !Options.v7 -> ETConstr (8,pos)
- | "constr9" -> ETConstr (9,pos)
- | "constr10" | "lconstr" -> ETConstr (10,pos)
+ | "constr0" -> ETConstr (inj 0,pos)
+ | "constr1" -> ETConstr (inj 1,pos)
+ | "constr2" -> ETConstr (inj 2,pos)
+ | "constr3" -> ETConstr (inj 3,pos)
+ | "lassoc_constr4" -> ETConstr (inj 4,pos)
+ | "constr5" -> ETConstr (inj 5,pos)
+ | "constr6" -> ETConstr (inj 6,pos)
+ | "constr7" -> ETConstr (inj 7,pos)
+ | "constr8" -> ETConstr (inj 8,pos)
+ | "constr" when !Options.v7 -> ETConstr (inj 8,pos)
+ | "constr9" -> ETConstr (inj 9,pos)
+ | "constr10" | "lconstr" -> ETConstr (inj 10,pos)
| "pattern" -> ETPattern
| "ident" -> ETIdent
| "global" -> ETReference
| _ -> ETOther (univ,nt)
-let explicitize_entry = explicitize_prod_entry ()
+let explicitize_entry = explicitize_prod_entry (fun x -> x) ()
(* Express border sub entries in function of the from level and an assoc *)
(* We're cheating: not necessarily the same assoc on right and left *)
let clever_explicitize_prod_entry pos univ from en =
- let t = explicitize_prod_entry pos univ en in
+ let t = explicitize_prod_entry (fun x -> NumLevel x) pos univ en in
match from with
| ETConstr (from,()) ->
(match t with
- | ETConstr (n,BorderProd (left,None)) when (n=from & left) ->
+ | ETConstr (n,BorderProd (left,None))
+ when (n=NumLevel from & left) ->
ETConstr (n,BorderProd (left,Some Gramext.LeftA))
- | ETConstr (n,BorderProd (left,None)) when (n=from-1 & not left) ->
- ETConstr (n+1,BorderProd (left,Some Gramext.LeftA))
- | ETConstr (n,BorderProd (left,None)) when (n=from-1 & left) ->
- ETConstr (n+1,BorderProd (left,Some Gramext.RightA))
- | ETConstr (n,BorderProd (left,None)) when (n=from & not left) ->
+ | ETConstr (NumLevel n,BorderProd (left,None))
+ when (n=from-1 & not left) ->
+ ETConstr
+ (NumLevel (n+1),BorderProd (left,Some Gramext.LeftA))
+ | ETConstr (NumLevel n,BorderProd (left,None))
+ when (n=from-1 & left) ->
+ ETConstr
+ (NumLevel (n+1),BorderProd (left,Some Gramext.RightA))
+ | ETConstr (n,BorderProd (left,None))
+ when (n=NumLevel from & not left) ->
ETConstr (n,BorderProd (left,Some Gramext.RightA))
| t -> t)
| _ -> t
diff --git a/parsing/extend.mli b/parsing/extend.mli
index 808e50158..ef685ffb1 100644
--- a/parsing/extend.mli
+++ b/parsing/extend.mli
@@ -25,14 +25,20 @@ type production_position =
| BorderProd of bool * Gramext.g_assoc option (* true=left; false=right *)
| InternalProd
-type 'pos constr_entry_key =
+type production_level =
+ | NextLevel
+ | NumLevel of int
+
+type ('lev,'pos) constr_entry_key =
| ETIdent | ETReference | ETBigint
- | ETConstr of (int * 'pos)
+ | ETConstr of ('lev * 'pos)
| ETPattern
| ETOther of string * string
-type constr_production_entry = production_position constr_entry_key
-type constr_entry = unit constr_entry_key
+type constr_production_entry =
+ (production_level,production_position) constr_entry_key
+type constr_entry = (int,unit) constr_entry_key
+type simple_constr_production_entry = (production_level,unit) constr_entry_key
type nonterm_prod =
| ProdList0 of nonterm_prod
@@ -68,10 +74,10 @@ val set_constr_globalizer :
(entry_context -> constr_expr -> constr_expr) -> unit
type syntax_modifier =
- | SetItemLevel of string list * int
+ | SetItemLevel of string list * production_level
| SetLevel of int
| SetAssoc of Gramext.g_assoc
- | SetEntryType of string * constr_entry
+ | SetEntryType of string * simple_constr_production_entry
| SetOnlyParsing
type nonterm =
diff --git a/parsing/g_basevernac.ml4 b/parsing/g_basevernac.ml4
index 3db24bcd1..13d4a623b 100644
--- a/parsing/g_basevernac.ml4
+++ b/parsing/g_basevernac.ml4
@@ -214,7 +214,7 @@ END
(* automatic translation of levels *)
let adapt_level n = n*10
let map_modl = function
- | SetItemLevel(ids,n) -> SetItemLevel(ids,adapt_level n)
+ | SetItemLevel(ids,NumLevel n) -> SetItemLevel(ids,NumLevel (adapt_level n))
| SetLevel n -> SetLevel(adapt_level n)
| m -> m
@@ -305,11 +305,14 @@ GEXTEND Gram
locality:
[ [ IDENT "Local" -> true | -> false ] ]
;
+ level:
+ [ [ IDENT "level"; n = natural -> NumLevel n
+ | IDENT "next"; IDENT "level" -> NextLevel ] ]
+ ;
syntax_modifier:
- [ [ x = IDENT; IDENT "at"; IDENT "level"; n = natural ->
- SetItemLevel ([x],n)
- | x = IDENT; ","; l = LIST1 IDENT SEP ","; IDENT "at"; IDENT "level";
- n = natural -> SetItemLevel (x::l,n)
+ [ [ x = IDENT; IDENT "at"; lev = level -> SetItemLevel ([x],lev)
+ | x = IDENT; ","; l = LIST1 IDENT SEP ","; IDENT "at"; lev = level ->
+ SetItemLevel (x::l,lev)
| IDENT "at"; IDENT "level"; n = natural -> SetLevel n
| IDENT "left"; IDENT "associativity" -> SetAssoc Gramext.LeftA
| IDENT "right"; IDENT "associativity" -> SetAssoc Gramext.RightA
diff --git a/parsing/g_vernac.ml4 b/parsing/g_vernac.ml4
index 2d1fcdd30..5b88cee39 100644
--- a/parsing/g_vernac.ml4
+++ b/parsing/g_vernac.ml4
@@ -216,8 +216,9 @@ GEXTEND Gram
(id,c,lc) ] ]
;
oneind:
- [ [ id = base_ident; indpar = simple_binders_list; ":"; c = constr; ":=";
- lc = constructor_list -> (id,indpar,c,lc) ] ]
+ [ [ ntn = OPT [ ntn = STRING; ":=" -> (ntn,None) ];
+ id = base_ident; indpar = simple_binders_list; ":"; c = constr; ":=";
+ lc = constructor_list -> (id,ntn,indpar,c,lc) ] ]
;
simple_binders_list:
[ [ bl = ne_simple_binders_list -> bl
@@ -298,7 +299,7 @@ GEXTEND Gram
gallina_ext:
[ [ IDENT "Mutual"; bl = ne_simple_binders_list ; f = finite_token;
indl = block_old_style ->
- let indl' = List.map (fun (id,ar,c) -> (id,bl,ar,c)) indl in
+ let indl' = List.map (fun (id,ar,c) -> (id,None,bl,ar,c)) indl in
VernacInductive (f,indl')
| record_token; oc = opt_coercion; name = base_ident;
ps = simple_binders_list; ":";
@@ -316,7 +317,7 @@ GEXTEND Gram
| IDENT "Scheme"; l = schemes -> VernacScheme l
| f = finite_token; s = csort; id = base_ident;
indpar = simple_binders_list; ":="; lc = constructor_list ->
- VernacInductive (f,[id,indpar,s,lc]) ] ]
+ VernacInductive (f,[id,None,indpar,s,lc]) ] ]
;
csort:
[ [ s = sort -> CSort (loc,s) ] ]
diff --git a/parsing/g_vernacnew.ml4 b/parsing/g_vernacnew.ml4
index 0e9e8dabb..4a6d3ca69 100644
--- a/parsing/g_vernacnew.ml4
+++ b/parsing/g_vernacnew.ml4
@@ -103,7 +103,7 @@ GEXTEND Gram
test_plurial_form bl;
VernacAssumption (stre, bl)
(* Gallina inductive declarations *)
- | OPT[IDENT "Mutual"]; f = finite_token;
+ | (* Non porté (?) : OPT[IDENT "Mutual"];*) f = finite_token;
indl = LIST1 inductive_definition SEP "with" ->
VernacInductive (f,indl)
| "Fixpoint"; recs = LIST1 rec_definition SEP "with" ->
@@ -118,9 +118,11 @@ GEXTEND Gram
s = lconstr; ":="; cstr = OPT base_ident; "{";
fs = LIST0 local_decl_expr; "}" ->
VernacRecord ((oc,name),ps,s,cstr,fs)
+(* Non porté ?
| f = finite_token; s = csort; id = base_ident;
indpar = LIST0 simple_binder; ":="; lc = constructor_list ->
- VernacInductive (f,[id,indpar,s,lc])
+ VernacInductive (f,[id,None,indpar,s,lc])
+*)
] ]
;
thm_token:
@@ -171,17 +173,20 @@ GEXTEND Gram
;
(* Inductives and records *)
inductive_definition:
- [ [ id = base_ident; indpar = LIST0 simple_binder; ":"; c = lconstr; ":=";
- lc = constructor_list -> (id,indpar,c,lc) ] ]
+ [ [ ntn = OPT [ ntn = STRING -> (ntn,None) ];
+ id = base_ident; indpar = LIST0 simple_binder; ":"; c = lconstr; ":=";
+ lc = constructor_list -> (id,ntn,indpar,c,lc) ] ]
;
constructor_list:
[ [ "|"; l = LIST1 constructor_binder SEP "|" -> l
| l = LIST1 constructor_binder SEP "|" -> l
| -> [] ] ]
;
+(*
csort:
[ [ s = sort -> CSort (loc,s) ] ]
;
+*)
opt_coercion:
[ [ ">" -> true
| -> false ] ]
@@ -699,11 +704,14 @@ GEXTEND Gram
[ [ univ = IDENT ->
set_default_action_parser (parser_type_from_name univ); univ ] ]
;
+ level:
+ [ [ IDENT "level"; n = natural -> NumLevel n
+ | IDENT "next"; IDENT "level" -> NextLevel ] ]
+ ;
syntax_modifier:
- [ [ x = IDENT; IDENT "at"; IDENT "level"; n = natural ->
- SetItemLevel ([x],n)
- | x = IDENT; ","; l = LIST1 IDENT SEP ","; IDENT "at"; IDENT "level";
- n = natural -> SetItemLevel (x::l,n)
+ [ [ x = IDENT; IDENT "at"; lev = level -> SetItemLevel ([x],lev)
+ | x = IDENT; ","; l = LIST1 IDENT SEP ","; IDENT "at";
+ lev = level -> SetItemLevel (x::l,lev)
| IDENT "at"; IDENT "level"; n = natural -> SetLevel n
| IDENT "left"; IDENT "associativity" -> SetAssoc Gramext.LeftA
| IDENT "right"; IDENT "associativity" -> SetAssoc Gramext.RightA
diff --git a/parsing/pcoq.ml4 b/parsing/pcoq.ml4
index d160734ea..39047e688 100644
--- a/parsing/pcoq.ml4
+++ b/parsing/pcoq.ml4
@@ -542,22 +542,27 @@ let camlp4_assoc = function
s.t. if [cur] is set then [n] is the same as the [from] level *)
let adjust_level assoc from = function
(* Associativity is None means force the level *)
- | (n,BorderProd (_,None)) -> Some (Some (n,true))
+ | (NumLevel n,BorderProd (_,None)) -> Some (Some (n,true))
(* Compute production name on the right side *)
(* If NonA or LeftA on the right-hand side, set to NEXT *)
- | (n,BorderProd (false,Some (Gramext.NonA|Gramext.LeftA))) -> Some None
+ | (NumLevel n,BorderProd (false,Some (Gramext.NonA|Gramext.LeftA))) ->
+ Some None
(* If RightA on the right-hand side, set to the explicit (current) level *)
- | (n,BorderProd (false,Some Gramext.RightA)) -> Some (Some (n,true))
+ | (NumLevel n,BorderProd (false,Some Gramext.RightA)) ->
+ Some (Some (n,true))
(* Compute production name on the left side *)
(* If NonA on the left-hand side, adopt the current assoc ?? *)
- | (n,BorderProd (true,Some Gramext.NonA)) -> None
+ | (NumLevel n,BorderProd (true,Some Gramext.NonA)) -> None
(* If the expected assoc is the current one, set to SELF *)
- | (n,BorderProd (true,Some a)) when a = camlp4_assoc assoc -> None
+ | (NumLevel n,BorderProd (true,Some a)) when a = camlp4_assoc assoc ->
+ None
(* Otherwise, force the level, n or n-1, according to expected assoc *)
- | (n,BorderProd (true,Some a)) ->
+ | (NumLevel n,BorderProd (true,Some a)) ->
if a = Gramext.LeftA then Some (Some (n,true)) else Some None
+ (* None means NEXT *)
+ | (NextLevel,_) -> Some None
(* Compute production name elsewhere *)
- | (n,InternalProd) ->
+ | (NumLevel n,InternalProd) ->
match from with
| ETConstr (p,()) when p = n+1 -> Some None
| ETConstr (p,()) -> Some (Some (n,n=p))
@@ -609,7 +614,7 @@ let compute_entry allow_create adjust = function
(* This computes the name of the level where to add a new rule *)
let get_constr_entry en =
match en with
- ETConstr(200,_) when not !Options.v7 ->
+ ETConstr(200,()) when not !Options.v7 ->
snd (get_entry (get_univ "constr") "binder_constr"),
None,
false
@@ -620,7 +625,7 @@ let get_constr_entry en =
let get_constr_production_entry ass from en =
(* first 2 cases to help factorisation *)
match en with
- | ETConstr (10,q) when !Options.v7 ->
+ | ETConstr (NumLevel 10,q) when !Options.v7 ->
weaken_entry Constr.lconstr, None, false
(*
| ETConstr (8,q) when !Options.v7 ->
@@ -643,9 +648,9 @@ let constr_prod_level assoc cur lev =
let is_self from e =
match from, e with
- ETConstr(n,_), ETConstr(n',
+ ETConstr(n,()), ETConstr(NumLevel n',
BorderProd(false, _ (* Some(Gramext.NonA|Gramext.LeftA) *))) -> false
- | ETConstr(n,_), ETConstr(n',BorderProd(true,_)) -> n=n'
+ | ETConstr(n,()), ETConstr(NumLevel n',BorderProd(true,_)) -> n=n'
| (ETIdent,ETIdent | ETReference, ETReference | ETBigint,ETBigint
| ETPattern, ETPattern) -> true
| ETOther(s1,s2), ETOther(s1',s2') -> s1=s1' & s2=s2'
@@ -653,7 +658,7 @@ let is_self from e =
let is_binder_level from e =
match from, e with
- ETConstr(200,_), ETConstr(200,_) -> not !Options.v7
+ ETConstr(200,()), ETConstr(NumLevel 200,_) -> not !Options.v7
| _ -> false
let symbol_of_production assoc from typ =
@@ -667,3 +672,5 @@ let symbol_of_production assoc from typ =
| (eobj,Some None,_) -> Gramext.Snext
| (eobj,Some (Some (lev,cur)),_) ->
Gramext.Snterml (Gram.Entry.obj eobj,constr_prod_level assoc cur lev)
+
+
diff --git a/toplevel/command.ml b/toplevel/command.ml
index ed77973c2..337e321df 100644
--- a/toplevel/command.ml
+++ b/toplevel/command.ml
@@ -178,7 +178,7 @@ let corecursive_message v =
let interp_mutual lparams lnamearconstrs finite =
let allnames =
List.fold_left
- (fun acc (id,_,l) -> id::(List.map fst l)@acc) [] lnamearconstrs in
+ (fun acc (id,_,_,l) -> id::(List.map fst l)@acc) [] lnamearconstrs in
if not (list_distinct allnames) then
error "Two inductive objects have the same name";
let nparams = List.length lparams
@@ -201,7 +201,7 @@ let interp_mutual lparams lnamearconstrs finite =
in
let (ind_env,ind_impls,arityl) =
List.fold_left
- (fun (env, ind_impls, arl) (recname, arityc,_) ->
+ (fun (env, ind_impls, arl) (recname, _, arityc, _) ->
let arity = interp_type sigma env_params arityc in
let fullarity =
prod_it arity (List.map (fun (id,_,ty) -> (id,ty)) params) in
@@ -213,10 +213,19 @@ let interp_mutual lparams lnamearconstrs finite =
(env', (recname,impls)::ind_impls, (arity::arl)))
(env0, [], []) lnamearconstrs
in
+ let lparnames = List.map (fun (na,_,_) -> na) params in
+ let fs = States.freeze() in
+ List.iter2 (fun (recname,ntnopt,_,_) ar ->
+ option_iter
+ (fun (df,scope) ->
+ let larnames = lparnames @ List.map fst (fst (decompose_prod ar)) in
+ Metasyntax.add_notation_interpretation df
+ (AVar recname,larnames) scope) ntnopt)
+ lnamearconstrs arityl;
let ind_env_params = push_rel_context params ind_env in
let mispecvec =
List.map2
- (fun ar (name,_,lname_constr) ->
+ (fun ar (name,_,_,lname_constr) ->
let constrnames, bodies = List.split lname_constr in
let constrs =
List.map
@@ -248,23 +257,23 @@ let extract_coe lc =
let extract_coe_la_lc = function
| [] -> anomaly "Vernacentries: empty list of inductive types"
- | (id,la,ar,lc)::rest ->
+ | (id,ntn,la,ar,lc)::rest ->
let rec check = function
| [] -> [],[]
- | (id,la',ar,lc)::rest ->
+ | (id,ntn,la',ar,lc)::rest ->
if (List.length la = List.length la') &&
(List.for_all2 eq_la la la')
then
let mcoes, mspec = check rest in
let coes, lc' = extract_coe lc in
- (coes::mcoes,(id,ar,lc')::mspec)
+ (coes::mcoes,(id,ntn,ar,lc')::mspec)
else
error ("Parameters should be syntactically the same "^
"for each inductive type")
in
let mcoes, mspec = check rest in
let coes, lc' = extract_coe lc in
- (coes,la,(id,ar,lc'):: mspec)
+ (coes,la,(id,ntn,ar,lc'):: mspec)
let build_mutual lind finite =
let (coes,lparams,lnamearconstructs) = extract_coe_la_lc lind in
diff --git a/toplevel/metasyntax.ml b/toplevel/metasyntax.ml
index c5a0c7a92..ece8acb2b 100644
--- a/toplevel/metasyntax.ml
+++ b/toplevel/metasyntax.ml
@@ -218,11 +218,12 @@ open Symbols
type white_status = Juxtapose | Separate of int | NextIsTerminal
-let precedence_of_entry_type = function
- | ETConstr (n,BorderProd (_,None)) -> n, Prec n
- | ETConstr (n,BorderProd (left,Some a)) ->
+let precedence_of_entry_type from = function
+ | ETConstr (NumLevel n,BorderProd (_,None)) -> n, Prec n
+ | ETConstr (NumLevel n,BorderProd (left,Some a)) ->
n, let (lp,rp) = prec_assoc a in if left then lp else rp
- | ETConstr (n,InternalProd) -> n, Prec n
+ | ETConstr (NumLevel n,InternalProd) -> n, Prec n
+ | ETConstr (NextLevel,_) -> from, L
| ETOther ("constr","annot") -> 10, Prec 10
| _ -> 0, E (* ?? *)
@@ -270,7 +271,7 @@ let add_break n l = UNP_BRK (n,1) :: l
let make_hunks_ast symbols etyps from =
let rec make ws = function
| NonTerminal m :: prods ->
- let _,lp = precedence_of_entry_type (List.assoc m etyps) in
+ let _,lp = precedence_of_entry_type from (List.assoc m etyps) in
let u = PH (meta_pattern (string_of_id m), None, lp) in
if prods <> [] && is_non_terminal (List.hd prods) then
u :: add_break 1 (make CanBreak prods)
@@ -307,12 +308,12 @@ let make_hunks_ast symbols etyps from =
let add_break n l = UnpCut (PpBrk(n,0)) :: l
-let make_hunks etyps symbols =
+let make_hunks etyps symbols from =
let vars,typs = List.split etyps in
let rec make ws = function
| NonTerminal m :: prods ->
let i = list_index m vars in
- let _,prec = precedence_of_entry_type (List.nth typs (i-1)) in
+ let _,prec = precedence_of_entry_type from (List.nth typs (i-1)) in
let u = UnpMetaVar (i ,prec) in
if prods <> [] && is_non_terminal (List.hd prods) then
u :: add_break 1 (make CanBreak prods)
@@ -363,16 +364,18 @@ let string_of_symbol = function
| Terminal s -> [s]
| Break _ -> []
-let assoc_of_type (_,typ) = level_rule (precedence_of_entry_type typ)
+let assoc_of_type n (_,typ) = level_rule (precedence_of_entry_type n typ)
let string_of_assoc = function
| Some(Gramext.RightA) -> "RIGHTA"
| Some(Gramext.LeftA) | None -> "LEFTA"
| Some(Gramext.NonA) -> "NONA"
+let make_anon_notation symbols =
+ String.concat " " (List.flatten (List.map string_of_symbol symbols))
+
let make_symbolic n symbols etyps =
- (n,List.map assoc_of_type etyps),
- (String.concat " " (List.flatten (List.map string_of_symbol symbols)))
+ ((n,List.map (assoc_of_type n) etyps), make_anon_notation symbols)
let rec define_keywords = function
NonTerm(_,Some(_,(ETConstr _|ETOther("constr","binder_constr")))) as n1 ::
@@ -411,7 +414,31 @@ let quote x =
else
x
-let rec find_symbols c_current c_next c_last vars = function
+let rec analyse_tokens = function
+ | [] -> [], []
+ | String x :: sl when Lexer.is_normal_token x ->
+ Lexer.check_ident x;
+ let id = Names.id_of_string x in
+ let (vars,l) = analyse_tokens sl in
+ if List.mem id vars then
+ error ("Variable "^x^" occurs more than once");
+ (id::vars, NonTerminal id :: l)
+ | String s :: sl ->
+ Lexer.check_special_token s;
+ let (vars,l) = analyse_tokens sl in (vars, Terminal (strip s) :: l)
+ | WhiteSpace n :: sl ->
+ let (vars,l) = analyse_tokens sl in (vars, Break n :: l)
+
+let rec find_symbols c_current c_next c_last = function
+ | [] -> []
+ | NonTerminal id :: sl ->
+ let prec = if sl <> [] then c_current else c_last in
+ (id, prec) :: (find_symbols c_next c_next c_last sl)
+ | Terminal s :: sl -> find_symbols c_next c_next c_last sl
+ | Break n :: sl -> find_symbols c_current c_next c_last sl
+
+(*
+let rec find_symbols c_current c_next c_last = function
| [] -> (vars, [])
| String x :: sl when Lexer.is_normal_token x ->
Lexer.check_ident x;
@@ -419,7 +446,7 @@ let rec find_symbols c_current c_next c_last vars = function
if List.mem_assoc id vars then
error ("Variable "^x^" occurs more than once");
let prec = if sl <> [] then c_current else c_last in
- let (vars,l) = find_symbols c_next c_next c_last vars sl in
+ let (vars,l) = find_symbols c_next c_next c_last sl in
((id,prec)::vars, NonTerminal id :: l)
(*
| "_"::sl ->
@@ -432,11 +459,12 @@ let rec find_symbols c_current c_next c_last vars = function
*)
| String s :: sl ->
Lexer.check_special_token s;
- let (vars,l) = find_symbols c_next c_next c_last vars sl in
+ let (vars,l) = find_symbols c_next c_next c_last sl in
(vars, Terminal (strip s) :: l)
| WhiteSpace n :: sl ->
- let (vars,l) = find_symbols c_current c_next c_last vars sl in
+ let (vars,l) = find_symbols c_current c_next c_last sl in
(vars, Break n :: l)
+*)
let make_grammar_rule n assoc typs symbols ntn =
let prod = make_production typs symbols in
@@ -463,8 +491,8 @@ let make_syntax_rule n name symbols typs ast ntn sc =
syn_hunks =
[UNP_SYMBOLIC(sc,ntn,UNP_BOX (PpHOVB 1,make_hunks_ast symbols typs n))]}]
-let make_pp_rule symbols typs =
- [UnpBox (PpHOVB 0, make_hunks symbols typs)]
+let make_pp_rule symbols typs n =
+ [UnpBox (PpHOVB 0, make_hunks symbols typs n)]
(**************************************************************************)
@@ -576,17 +604,18 @@ let recompute_assoc typs =
let add_syntax_extension local df modifiers =
let (assoc,n,etyps,onlyparse) = interp_notation_modifiers modifiers in
- let inner = if !Options.v7 then (10,InternalProd) else
- (200,InternalProd) in
- let (typs,symbs) =
+ let inner = if !Options.v7 then (NumLevel 10,InternalProd) else
+ (NumLevel 200,InternalProd) in
+ let (vars,symbs) = analyse_tokens (split df) in
+ let typs =
find_symbols
- (n,BorderProd(true,assoc)) inner (n,BorderProd(false,assoc))
- [] (split df) in
+ (NumLevel n,BorderProd(true,assoc)) inner
+ (NumLevel n,BorderProd(false,assoc)) symbs in
let typs = List.map (set_entry_type etyps) typs in
let assoc = recompute_assoc typs in
let (prec,notation) = make_symbolic n symbs typs in
let gram_rule = make_grammar_rule n assoc typs symbs notation in
- let pp_rule = if onlyparse then None else Some (make_pp_rule typs symbs) in
+ let pp_rule = if onlyparse then None else Some (make_pp_rule typs symbs n) in
Lib.add_anonymous_leaf
(inSyntaxExtension(local,prec,notation,gram_rule,pp_rule))
@@ -662,12 +691,13 @@ let add_notation_in_scope local df c (assoc,n,etyps,onlyparse) omodv8 sc toks =
let onlyparse = onlyparse or !Options.v7_only in
let scope = match sc with None -> Symbols.default_scope | Some sc -> sc in
let inner =
- if !Options.v7 then (10,InternalProd) else (200,InternalProd) in
- let (typs,symbols) =
+ if !Options.v7 then (NumLevel 10,InternalProd)
+ else (NumLevel 200,InternalProd) in
+ let (vars,symbols) = analyse_tokens toks in
+ let typs =
find_symbols
- (n,BorderProd(true,assoc)) inner (n,BorderProd(false,assoc))
- [] toks in
- let vars = List.map fst typs in
+ (NumLevel n,BorderProd(true,assoc)) inner
+ (NumLevel n,BorderProd(false,assoc)) symbols in
(* To globalize... *)
let a = interp_aconstr vars c in
let typs = List.map (set_entry_type etyps) typs in
@@ -677,11 +707,12 @@ let add_notation_in_scope local df c (assoc,n,etyps,onlyparse) omodv8 sc toks =
let (ppprec,ppn,pptyps,ppsymbols) =
match omodv8 with
Some(toks8,(a8,n8,typs8,_)) when Options.do_translate() ->
- let (typs,symbols) =
+ let (_,symbols) = analyse_tokens toks8 in
+ let typs =
find_symbols
- (n8,BorderProd(true,a8)) (200,InternalProd)
- (n8,BorderProd(false,a8))
- [] toks8 in
+ (NumLevel n8,BorderProd(true,a8)) (NumLevel 200,InternalProd)
+ (NumLevel n8,BorderProd(false,a8))
+ symbols in
let typs = List.map (set_entry_type typs8) typs in
let (prec,notation) = make_symbolic n8 symbols typs in
(prec, n8, typs, symbols)
@@ -689,7 +720,7 @@ let add_notation_in_scope local df c (assoc,n,etyps,onlyparse) omodv8 sc toks =
let gram_rule = make_grammar_rule n assoc typs symbols notation in
let pp_rule =
if onlyparse then None
- else Some (make_pp_rule pptyps ppsymbols) in
+ else Some (make_pp_rule pptyps ppsymbols n) in
Lib.add_anonymous_leaf
(inSyntaxExtension(local,ppprec,notation,gram_rule,pp_rule));
let old_pp_rule =
@@ -722,6 +753,24 @@ let add_notation local df a modifiers mv8 sc =
(toks8,im8)) mv8)
sc toks
+let check_occur l id =
+ if not (List.mem (Name id) l) then error ((string_of_id id)^"is unbound")
+
+let add_notation_interpretation df (c,l) sc =
+ let scope = match sc with None -> Symbols.default_scope | Some sc -> sc in
+ let (vars,symbs) = analyse_tokens (split df) in
+ let notation = make_anon_notation symbs in
+ let old_pp_rule = None in
+ let prec = Symbols.find_notation_level notation in
+ List.iter (check_occur l) vars;
+ let a = AApp (c,List.map (function Name id when List.mem id vars -> AVar id |
+_ -> AHole QuestionMark) l) in
+ let la = List.map (fun id -> id,[]) vars in
+ let onlyparse = false in
+ let local = false in
+ Lib.add_anonymous_leaf
+ (inNotation(local,old_pp_rule,prec,notation,scope,(la,a),onlyparse,df))
+
(* TODO add boxes information in the expression *)
let inject_var x = CRef (Ident (dummy_loc, id_of_string x))
diff --git a/toplevel/metasyntax.mli b/toplevel/metasyntax.mli
index 92f79680e..59e786fe3 100644
--- a/toplevel/metasyntax.mli
+++ b/toplevel/metasyntax.mli
@@ -41,8 +41,10 @@ val add_notation : locality_flag -> string -> constr_expr
-> syntax_modifier list -> (string * syntax_modifier list) option
-> scope_name option -> unit
-val add_syntax_extension : locality_flag -> string -> syntax_modifier list
- -> unit
+val add_notation_interpretation : string -> (aconstr * Names.name list)
+ -> scope_name option -> unit
+
+val add_syntax_extension : locality_flag -> string -> syntax_modifier list -> unit
val print_grammar : string -> string -> unit
diff --git a/toplevel/vernacexpr.ml b/toplevel/vernacexpr.ml
index 99ce8b34e..b2f82854c 100644
--- a/toplevel/vernacexpr.ml
+++ b/toplevel/vernacexpr.ml
@@ -122,11 +122,13 @@ type inductive_flag = bool (* true = Inductive; false = CoInductive *)
type sort_expr = Rawterm.rawsort
+type decl_notation = (string * scope_name option) option
type simple_binder = identifier * constr_expr
type 'a with_coercion = coercion_flag * 'a
type constructor_expr = simple_binder with_coercion
type inductive_expr =
- identifier * simple_binder list * constr_expr * constructor_expr list
+ identifier * decl_notation * simple_binder list * constr_expr
+ * constructor_expr list
type definition_expr =
| ProveBody of local_binder list * constr_expr
| DefineBody of local_binder list * raw_red_expr option * constr_expr
diff --git a/translate/ppvernacnew.ml b/translate/ppvernacnew.ml
index 1b2428a9d..1480c765c 100644
--- a/translate/ppvernacnew.ml
+++ b/translate/ppvernacnew.ml
@@ -299,7 +299,10 @@ let pr_require_token = function
| None -> str "Closed"
let pr_syntax_modifier = function
- | SetItemLevel (l,n) ->
+ | SetItemLevel (l,NextLevel) ->
+ prlist_with_sep sep_v2 str l ++
+ spc() ++ str"at next level"
+ | SetItemLevel (l,NumLevel n) ->
prlist_with_sep sep_v2 str l ++
spc() ++ str"at level" ++ spc() ++ int n
| SetLevel n -> str"at level" ++ spc() ++ int n
@@ -513,7 +516,7 @@ let rec pr_vernac = function
| VernacInductive (f,l) ->
(* Copie simplifiée de command.ml pour recalculer les implicites *)
- let lparams = match l with [] -> assert false | (_,la,_,_)::_ -> la in
+ let lparams = match l with [] -> assert false | (_,_,la,_,_)::_ -> la in
let nparams = List.length lparams
and sigma = Evd.empty
and env0 = Global.env() in
@@ -525,7 +528,7 @@ let rec pr_vernac = function
(Name id,None,p)::params))
(env0,[]) lparams in
let impls = List.map
- (fun (recname, _,arityc,_) ->
+ (fun (recname,_,_,arityc,_) ->
let arity = Constrintern.interp_type sigma env_params arityc in
let fullarity =
Termops.prod_it arity (List.map (fun (id,_,ty) -> (id,ty)) params)
@@ -555,9 +558,13 @@ let rec pr_vernac = function
| _ ->
fnl() ++ str (if List.length l = 1 then " " else " | ") ++
prlist_with_sep (fun _ -> fnl() ++ str" | ") pr_constructor l in
- let pr_oneind key (id,indpar,s,lc) =
- hov 0 (str key ++ spc() ++ pr_id id ++ spc() ++
- pr_sbinders indpar ++ str":" ++ spc() ++
+ let pr_oneind key (id,ntn,indpar,s,lc) =
+ hov 0 (
+ str key ++ spc() ++
+ pr_opt (fun (ntn,scopt) ->
+ str ntn ++ pr_opt (fun sc -> str " :" ++ str sc) scopt ++ spc ())
+ ntn ++
+ pr_id id ++ spc() ++ pr_sbinders indpar ++ str":" ++ spc() ++
pr_lconstr s ++ str" :=") ++ pr_constructor_list lc in
hov 1 (pr_oneind (if f then "Inductive" else "CoInductive") (List.hd l))
++