src/Pure/General/antiquote.ML
changeset 53167 4e7ddd76e632
parent 50201 c26369c9eda6
child 55046 9e83995c8e98
equal deleted inserted replaced
53166:1266b6208a5b 53167:4e7ddd76e632
     6 
     6 
     7 signature ANTIQUOTE =
     7 signature ANTIQUOTE =
     8 sig
     8 sig
     9   datatype 'a antiquote =
     9   datatype 'a antiquote =
    10     Text of 'a |
    10     Text of 'a |
    11     Antiq of Symbol_Pos.T list * Position.range |
    11     Antiq of Symbol_Pos.T list * Position.range
    12     Open of Position.T |
       
    13     Close of Position.T
       
    14   val is_text: 'a antiquote -> bool
    12   val is_text: 'a antiquote -> bool
    15   val reports_of: ('a -> Position.report_text list) ->
    13   val reports_of: ('a -> Position.report_text list) ->
    16     'a antiquote list -> Position.report_text list
    14     'a antiquote list -> Position.report_text list
    17   val check_nesting: 'a antiquote list -> unit
       
    18   val scan_antiq: Symbol_Pos.T list -> (Symbol_Pos.T list * Position.range) * Symbol_Pos.T list
    15   val scan_antiq: Symbol_Pos.T list -> (Symbol_Pos.T list * Position.range) * Symbol_Pos.T list
    19   val scan: Symbol_Pos.T list -> 'a antiquote * Symbol_Pos.T list
       
    20   val scan_text: Symbol_Pos.T list -> Symbol_Pos.T list antiquote * Symbol_Pos.T list
    16   val scan_text: Symbol_Pos.T list -> Symbol_Pos.T list antiquote * Symbol_Pos.T list
    21   val read: Symbol_Pos.T list * Position.T -> Symbol_Pos.T list antiquote list
    17   val read: Symbol_Pos.T list * Position.T -> Symbol_Pos.T list antiquote list
    22 end;
    18 end;
    23 
    19 
    24 structure Antiquote: ANTIQUOTE =
    20 structure Antiquote: ANTIQUOTE =
    26 
    22 
    27 (* datatype antiquote *)
    23 (* datatype antiquote *)
    28 
    24 
    29 datatype 'a antiquote =
    25 datatype 'a antiquote =
    30   Text of 'a |
    26   Text of 'a |
    31   Antiq of Symbol_Pos.T list * Position.range |
    27   Antiq of Symbol_Pos.T list * Position.range;
    32   Open of Position.T |
       
    33   Close of Position.T;
       
    34 
    28 
    35 fun is_text (Text _) = true
    29 fun is_text (Text _) = true
    36   | is_text _ = false;
    30   | is_text _ = false;
    37 
    31 
    38 
    32 
    39 (* reports *)
    33 (* reports *)
    40 
    34 
    41 fun reports_of text =
    35 fun reports_of text =
    42   maps
    36   maps (fn Text x => text x | Antiq (_, (pos, _)) => [((pos, Markup.antiq), "")]);
    43     (fn Text x => text x
       
    44       | Antiq (_, (pos, _)) => [((pos, Markup.antiq), "")]
       
    45       | Open pos => [((pos, Markup.antiq), "")]
       
    46       | Close pos => [((pos, Markup.antiq), "")]);
       
    47 
       
    48 
       
    49 (* check_nesting *)
       
    50 
       
    51 fun err_unbalanced pos =
       
    52   error ("Unbalanced antiquotation block parentheses" ^ Position.here pos);
       
    53 
       
    54 fun check_nesting antiqs =
       
    55   let
       
    56     fun check [] [] = ()
       
    57       | check [] (pos :: _) = err_unbalanced pos
       
    58       | check (Open pos :: ants) ps = check ants (pos :: ps)
       
    59       | check (Close pos :: _) [] = err_unbalanced pos
       
    60       | check (Close _ :: ants) (_ :: ps) = check ants ps
       
    61       | check (_ :: ants) ps = check ants ps;
       
    62   in check antiqs [] end;
       
    63 
    37 
    64 
    38 
    65 (* scan *)
    39 (* scan *)
    66 
    40 
    67 open Basic_Symbol_Pos;
    41 open Basic_Symbol_Pos;
    70 
    44 
    71 val err_prefix = "Antiquotation lexical error: ";
    45 val err_prefix = "Antiquotation lexical error: ";
    72 
    46 
    73 val scan_txt =
    47 val scan_txt =
    74   $$$ "@" --| Scan.ahead (~$$$ "{") ||
    48   $$$ "@" --| Scan.ahead (~$$$ "{") ||
    75   Scan.one (fn (s, _) => s <> "@" andalso s <> "\\<lbrace>" andalso s <> "\\<rbrace>"
    49   Scan.one (fn (s, _) => s <> "@" andalso Symbol.is_regular s) >> single;
    76     andalso Symbol.is_regular s) >> single;
       
    77 
    50 
    78 val scan_ant =
    51 val scan_ant =
    79   Scan.trace (Symbol_Pos.scan_string_qq err_prefix || Symbol_Pos.scan_string_bq err_prefix) >> #2 ||
    52   Scan.trace (Symbol_Pos.scan_string_qq err_prefix || Symbol_Pos.scan_string_bq err_prefix) >> #2 ||
    80   Scan.one (fn (s, _) => s <> "}" andalso Symbol.is_regular s) >> single;
    53   Scan.one (fn (s, _) => s <> "}" andalso Symbol.is_regular s) >> single;
    81 
       
    82 val scan_open = Symbol_Pos.scan_pos --| $$$ "\\<lbrace>";
       
    83 val scan_close = Symbol_Pos.scan_pos --| $$$ "\\<rbrace>";
       
    84 
    54 
    85 in
    55 in
    86 
    56 
    87 val scan_antiq =
    57 val scan_antiq =
    88   Symbol_Pos.scan_pos -- ($$$ "@" |-- $$$ "{" |--
    58   Symbol_Pos.scan_pos -- ($$$ "@" |-- $$$ "{" |--
    89     Symbol_Pos.!!! (fn () => err_prefix ^ "missing closing brace")
    59     Symbol_Pos.!!! (fn () => err_prefix ^ "missing closing brace")
    90       (Scan.repeat scan_ant -- ($$$ "}" |-- Symbol_Pos.scan_pos)))
    60       (Scan.repeat scan_ant -- ($$$ "}" |-- Symbol_Pos.scan_pos)))
    91   >> (fn (pos1, (body, pos2)) => (flat body, Position.range pos1 pos2));
    61   >> (fn (pos1, (body, pos2)) => (flat body, Position.range pos1 pos2));
    92 
    62 
    93 fun scan x = (scan_antiq >> Antiq || scan_open >> Open || scan_close >> Close) x;
    63 val scan_text = scan_antiq >> Antiq || Scan.repeat1 scan_txt >> (Text o flat);
    94 val scan_text = scan || Scan.repeat1 scan_txt >> (Text o flat);
       
    95 
    64 
    96 end;
    65 end;
    97 
    66 
    98 
    67 
    99 (* read *)
    68 (* read *)
   100 
    69 
   101 fun read (syms, pos) =
    70 fun read (syms, pos) =
   102   (case Scan.read Symbol_Pos.stopper (Scan.repeat scan_text) syms of
    71   (case Scan.read Symbol_Pos.stopper (Scan.repeat scan_text) syms of
   103     SOME xs => (Position.reports_text (reports_of (K []) xs); check_nesting xs; xs)
    72     SOME xs => (Position.reports_text (reports_of (K []) xs); xs)
   104   | NONE => error ("Malformed quotation/antiquotation source" ^ Position.here pos));
    73   | NONE => error ("Malformed quotation/antiquotation source" ^ Position.here pos));
   105 
    74 
   106 end;
    75 end;