aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHugo Herbelin2019-12-25 14:00:16 +0100
committerHugo Herbelin2020-02-15 22:23:08 +0100
commitaf8ddf0038e0caac1763da7ef510e4d5fdd4b8e7 (patch)
tree1739d127ac013589739f61723d19cd45cd855ca8
parent44ec3c8fd02f27d1dc7123bfbe5f5018937d6b86 (diff)
Fixing a precedence printing bug with custom entries.
Insertion of coercion to manage precedence of custom entries are treated in constrextern.ml, while ppconstr.ml is only about the management of precedences for constr.
-rw-r--r--vernac/metasyntax.ml33
1 files changed, 25 insertions, 8 deletions
diff --git a/vernac/metasyntax.ml b/vernac/metasyntax.ml
index ecfebec6b8..c8c2376155 100644
--- a/vernac/metasyntax.ml
+++ b/vernac/metasyntax.ml
@@ -298,6 +298,7 @@ let precedence_of_position_and_level from_level = function
| NumLevel n, InternalProd -> n, Prec n
| NextLevel, _ -> from_level, L
+(** Computing precedences of subentries for parsing *)
let precedence_of_entry_type (from_custom,from_level) = function
| ETConstr (custom,_,x) when notation_entry_eq custom from_custom ->
precedence_of_position_and_level from_level x
@@ -309,6 +310,22 @@ let precedence_of_entry_type (from_custom,from_level) = function
| ETPattern (_,n) -> let n = match n with None -> 0 | Some n -> n in n, Prec n
| _ -> 0, E (* should not matter *)
+(** Computing precedences for future insertion of parentheses at
+ the time of printing using hard-wired constr levels *)
+let unparsing_precedence_of_entry_type from_level = function
+ | ETConstr (InConstrEntry,_,x) ->
+ (* Possible insertion of parentheses at printing time to deal
+ with precedence in a constr entry is managed using [prec_less]
+ in [ppconstr.ml] *)
+ snd (precedence_of_position_and_level from_level x)
+ | ETConstr (custom,_,_) ->
+ (* Precedence of printing for a custom entry is managed using
+ explicit insertion of entry coercions at the time of building
+ a [constr_expr] *)
+ Any
+ | ETPattern (_,n) -> (* in constr *) Prec (match n with Some n -> n | None -> 0)
+ | _ -> Any (* should not matter *)
+
(* Some breaking examples *)
(* "x = y" : "x /1 = y" (breaks before any symbol) *)
(* "x =S y" : "x /1 =S /1 y" (protect from confusion; each side for symmetry)*)
@@ -374,7 +391,7 @@ let check_open_binder isopen sl m =
let unparsing_metavar i from typs =
let x = List.nth typs (i-1) in
- let prec = snd (precedence_of_entry_type from x) in
+ let prec = unparsing_precedence_of_entry_type from x in
match x with
| ETConstr _ | ETGlobal | ETBigint ->
UnpMetaVar (i,prec)
@@ -389,12 +406,12 @@ let unparsing_metavar i from typs =
let index_id id l = List.index Id.equal id l
-let make_hunks etyps symbols from =
+let make_hunks etyps symbols from_level =
let vars,typs = List.split etyps in
let rec make b = function
| NonTerminal m :: prods ->
let i = index_id m vars in
- let u = unparsing_metavar i from typs in
+ let u = unparsing_metavar i from_level typs in
if is_next_non_terminal b prods then
(None, u) :: add_break_if_none 1 b (make b prods)
else
@@ -428,7 +445,7 @@ let make_hunks etyps symbols from =
| SProdList (m,sl) :: prods ->
let i = index_id m vars in
let typ = List.nth typs (i-1) in
- let _,prec = precedence_of_entry_type from typ in
+ let prec = unparsing_precedence_of_entry_type from_level typ in
let sl' =
(* If no separator: add a break *)
if List.is_empty sl then add_break 1 []
@@ -555,7 +572,7 @@ let read_recursive_format sl fmt =
the names in the notation *)
slfmt, res
-let hunks_of_format (from,(vars,typs)) symfmt =
+let hunks_of_format (from_level,(vars,typs)) symfmt =
let rec aux = function
| symbs, (_,(UnpTerminal s' as u)) :: fmt
when String.equal s' (String.make (String.length s') ' ') ->
@@ -565,13 +582,13 @@ let hunks_of_format (from,(vars,typs)) symfmt =
let symbs, l = aux (symbs,fmt) in symbs, UnpTerminal s :: l
| NonTerminal s :: symbs, (_,UnpTerminal s') :: fmt when Id.equal s (Id.of_string s') ->
let i = index_id s vars in
- let symbs, l = aux (symbs,fmt) in symbs, unparsing_metavar i from typs :: l
+ let symbs, l = aux (symbs,fmt) in symbs, unparsing_metavar i from_level typs :: l
| symbs, (_,(UnpCut _ as u)) :: fmt ->
let symbs, l = aux (symbs,fmt) in symbs, u :: l
| SProdList (m,sl) :: symbs, fmt when has_ldots fmt ->
let i = index_id m vars in
let typ = List.nth typs (i-1) in
- let _,prec = precedence_of_entry_type from typ in
+ let prec = unparsing_precedence_of_entry_type from_level typ in
let loc_slfmt,rfmt = read_recursive_format sl fmt in
let sl, slfmt = aux (sl,loc_slfmt) in
if not (List.is_empty sl) then error_format ?loc:(find_prod_list_loc loc_slfmt fmt) ();
@@ -1454,7 +1471,7 @@ let make_syntax_rules (sd : SynData.syn_data) = let open SynData in
let ntn_for_grammar, prec_for_grammar, need_squash = sd.not_data in
let custom,level,_,_ = sd.level in
let pa_rule = make_pa_rule prec_for_grammar sd.pa_syntax_data ntn_for_grammar need_squash in
- let pp_rule = make_pp_rule (custom,level) sd.pp_syntax_data sd.format in {
+ let pp_rule = make_pp_rule level sd.pp_syntax_data sd.format in {
synext_level = sd.level;
synext_notation = fst sd.info;
synext_notgram = { notgram_onlyprinting = sd.only_printing; notgram_rules = pa_rule };