src/Pure/Syntax/syntax_ext.ML
changeset 80904 05f17df447b6
parent 80899 51c338103975
child 80905 47793a46d06c
equal deleted inserted replaced
80903:756fa442b7f3 80904:05f17df447b6
   119 datatype mfix = Mfix of Symbol_Pos.T list * typ * string * int list * int * Position.T;
   119 datatype mfix = Mfix of Symbol_Pos.T list * typ * string * int list * int * Position.T;
   120 
   120 
   121 
   121 
   122 (* properties *)
   122 (* properties *)
   123 
   123 
       
   124 fun show_names names =
       
   125   commas_quote (map (fn (name, pos) => Markup.markup (Position.markup pos) name) names);
       
   126 
   124 local
   127 local
   125 
   128 
   126 open Basic_Symbol_Pos;
   129 open Basic_Symbol_Pos;
   127 
   130 
   128 val err_prefix = "Error in mixfix block properties: ";
   131 val err_prefix = "Error in mixfix block properties: ";
   137 val scan_blanks = Scan.many (Symbol.is_blank o Symbol_Pos.symbol);
   140 val scan_blanks = Scan.many (Symbol.is_blank o Symbol_Pos.symbol);
   138 val scan_item =
   141 val scan_item =
   139   scan_blanks |-- scan_atom --| scan_blanks
   142   scan_blanks |-- scan_atom --| scan_blanks
   140     >> (fn ss => (Symbol_Pos.content ss, #1 (Symbol_Pos.range ss)));
   143     >> (fn ss => (Symbol_Pos.content ss, #1 (Symbol_Pos.range ss)));
   141 
   144 
   142 val scan_prop =
   145 val scan_prop = scan_item -- Scan.option ($$ "=" |-- !!! scan_item);
   143   scan_item -- Scan.optional ($$ "=" |-- !!! scan_item >> #1) "true"
   146 
   144     >> (fn ((x, pos), y) => (x, (y, pos)));
   147 fun get_property default0 default1 parse name props =
   145 
   148   (case find_first (fn ((a, _), _) => a = name) props of
   146 fun get_property default parse name props =
   149     NONE => default0
   147   (case AList.lookup (op =) props name of
   150   | SOME (_, NONE) => default1
   148     NONE => default
   151   | SOME ((_, pos1), SOME (b, pos2)) =>
   149   | SOME (s, pos) =>
   152       (parse (b, pos2) handle Fail msg =>
   150       (parse s handle Fail msg =>
   153         error (msg ^ " for property " ^ quote name ^ Position.here_list [pos1, pos2])));
   151         error (msg ^ " for property " ^ quote name ^ Position.here pos)));
       
   152 
   154 
   153 in
   155 in
   154 
   156 
   155 fun read_properties ss =
   157 fun read_properties ss =
   156   let
   158   let
   157     val props =
   159     val props =
   158       (case Scan.error (Scan.finite Symbol_Pos.stopper (Scan.repeat scan_prop)) ss of
   160       (case Scan.error (Scan.finite Symbol_Pos.stopper (Scan.repeat scan_prop)) ss of
   159         (props, []) => props
   161         (props, []) => props
   160       | (_, (_, pos) :: _) => error (err_prefix ^ "bad input" ^ Position.here pos));
   162       | (_, (_, pos) :: _) => error (err_prefix ^ "bad input" ^ Position.here pos));
       
   163     fun ok (_, bs) = length bs <= 1;
   161     val _ =
   164     val _ =
   162       (case AList.group (op =) props |> filter (fn (_, [_]) => false | _ => true) of
   165       (case AList.group (eq_fst op =) props |> filter_out ok of
   163         [] => ()
   166         [] => ()
   164       | dups => error ("Duplicate properties: " ^ commas_quote (map #1 dups) ^
   167       | dups => error ("Duplicate properties: " ^ show_names (map #1 dups)));
   165           Position.here_list (map #2 (maps #2 dups))));
       
   166   in props end;
   168   in props end;
   167 
   169 
   168 val get_string = get_property "" I;
   170 val get_string = get_property "" "" #1;
   169 val get_bool = get_property false Value.parse_bool;
   171 val get_bool = get_property false true (Value.parse_bool o #1);
   170 val get_nat = get_property 0 Value.parse_nat;
   172 val get_nat = get_property 0 1 (Value.parse_nat o #1);
   171 
   173 
   172 end;
   174 end;
   173 
   175 
   174 
   176 
   175 (* read mixfix annotations *)
   177 (* read mixfix annotations *)
   212 fun read_block_properties ss =
   214 fun read_block_properties ss =
   213   let
   215   let
   214     val props = read_properties ss;
   216     val props = read_properties ss;
   215 
   217 
   216     val markup_name = get_string Markup.markupN props;
   218     val markup_name = get_string Markup.markupN props;
   217     val markup_props = fold (AList.delete (op =)) Markup.block_properties props;
   219     val markup_props = props |> map_filter (fn (a, opt_b) =>
   218     val markup = (markup_name, map (apsnd #1) markup_props);
   220       if member (op =) Markup.block_properties (#1 a) then NONE
       
   221       else SOME (a, the_default ("", Position.none) opt_b));
       
   222     val markup = (markup_name, map (apply2 #1) markup_props);
   219     val _ =
   223     val _ =
   220       if markup_name = "" andalso not (null markup_props) then
   224       if markup_name = "" andalso not (null markup_props) then
   221         error ("Markup name required for block properties: " ^
   225         error ("Markup name required for block properties: " ^ show_names (map #1 markup_props))
   222           commas_quote (map #1 markup_props) ^ Position.here_list (map (#2 o #2) markup_props))
       
   223       else ();
   226       else ();
   224 
   227 
   225     val consistent = get_bool Markup.consistentN props;
   228     val consistent = get_bool Markup.consistentN props;
   226     val unbreakable = get_bool Markup.unbreakableN props;
   229     val unbreakable = get_bool Markup.unbreakableN props;
   227     val indent = get_nat Markup.indentN props;
   230     val indent = get_nat Markup.indentN props;