src/Pure/General/comment.ML
author wenzelm
Sat Feb 03 20:34:26 2018 +0100 (16 months ago)
changeset 67571 f858fe5531ac
parent 67506 30233285270a
child 67572 a93cf1d6ba87
permissions -rw-r--r--
more uniform treatment of formal comments within document source;
more robust nesting;
     1 (*  Title:      Pure/General/comment.ML
     2     Author:     Makarius
     3 
     4 Formal comments.
     5 *)
     6 
     7 signature COMMENT =
     8 sig
     9   datatype kind = Comment | Cancel | Latex
    10   val markups: kind -> Markup.T list
    11   val is_symbol: Symbol.symbol -> bool
    12   val scan_comment: (kind * Symbol_Pos.T list) scanner
    13   val scan_cancel: (kind * Symbol_Pos.T list) scanner
    14   val scan_latex: (kind * Symbol_Pos.T list) scanner
    15   val scan: (kind * Symbol_Pos.T list) scanner
    16   val read_body: Symbol_Pos.T list -> (kind option * Symbol_Pos.T list) list option
    17 end;
    18 
    19 structure Comment: COMMENT =
    20 struct
    21 
    22 (* kinds *)
    23 
    24 datatype kind = Comment | Cancel | Latex;
    25 
    26 val kinds =
    27   [(Comment,
    28      {symbol = Symbol.comment, blanks = true,
    29       markups = [Markup.language_document true]}),
    30    (Cancel,
    31      {symbol = Symbol.cancel, blanks = false,
    32       markups = [Markup.language_text true]}),
    33    (Latex,
    34      {symbol = Symbol.latex, blanks = false,
    35       markups = [Markup.language_latex true, Markup.no_words]})];
    36 
    37 val get_kind = the o AList.lookup (op =) kinds;
    38 val print_kind = quote o #symbol o get_kind;
    39 val markups = #markups o get_kind;
    40 
    41 fun is_symbol sym = exists (fn (_, {symbol, ...}) => symbol = sym) kinds;
    42 
    43 
    44 (* scan *)
    45 
    46 local
    47 
    48 open Basic_Symbol_Pos;
    49 
    50 val err_prefix = "Error in formal comment: ";
    51 
    52 val scan_blanks = Scan.many (Symbol.is_blank o Symbol_Pos.symbol);
    53 
    54 fun scan_symbol kind =
    55   let val {blanks, symbol, ...} = get_kind kind
    56   in if blanks then $$$ symbol @@@ scan_blanks else $$$ symbol end;
    57 
    58 fun scan_strict kind =
    59   scan_symbol kind @@@
    60     Symbol_Pos.!!! (fn () => err_prefix ^ "cartouche expected after " ^ print_kind kind)
    61       (Symbol_Pos.scan_cartouche err_prefix) >> pair kind;
    62 
    63 fun scan_permissive kind =
    64   scan_symbol kind -- Scan.option (Symbol_Pos.scan_cartouche err_prefix) >>
    65     (fn (ss, NONE) => (NONE, ss) | (_, SOME ss) => (SOME kind, ss));
    66 
    67 in
    68 
    69 val scan_comment = scan_strict Comment;
    70 val scan_cancel = scan_strict Cancel;
    71 val scan_latex = scan_strict Latex;
    72 val scan = scan_comment || scan_cancel || scan_latex;
    73 
    74 val scan_body =
    75   Scan.many1 (fn (s, _) => not (is_symbol s) andalso Symbol.not_eof s) >> pair NONE ||
    76   scan_permissive Comment || scan_permissive Cancel || scan_permissive Latex;
    77 
    78 fun read_body syms =
    79   if exists (is_symbol o Symbol_Pos.symbol) syms then
    80     Scan.read Symbol_Pos.stopper (Scan.repeat scan_body) syms
    81   else NONE;
    82 
    83 end;
    84 
    85 end;