improved support for raw symbols;
authorwenzelm
Sat, 29 May 2004 15:06:19 +0200
changeset 14834 e47744683560
parent 14833 30556b84af7c
child 14835 695ee8ad0bb6
improved support for raw symbols;
src/Pure/General/symbol.ML
--- a/src/Pure/General/symbol.ML	Sat May 29 15:06:04 2004 +0200
+++ b/src/Pure/General/symbol.ML	Sat May 29 15:06:19 2004 +0200
@@ -27,6 +27,9 @@
   val is_ascii_digit: symbol -> bool
   val is_ascii_quasi: symbol -> bool
   val is_ascii_blank: symbol -> bool
+  val is_raw: symbol -> bool
+  val decode_raw: symbol -> string
+  val encode_raw: string -> symbol list
   datatype kind = Letter | Digit | Quasi | Blank | Other
   val kind: symbol -> kind
   val is_letter: symbol -> bool
@@ -46,14 +49,12 @@
   val bump_init: string -> string
   val bump_string: string -> string
   val length: symbol list -> int
+  val plain_output: string -> string
+  val default_output: string -> string * real
   val default_indent: string * int -> string
-  val add_mode: string -> (string -> string * real) * (string * int -> string) -> unit
+  val default_raw: string -> string
   val symbolsN: string
   val xsymbolsN: string
-  val plain_output: string -> string
-  val output: string -> string
-  val output_width: string -> string * real
-  val indent: string * int -> string
 end;
 
 structure Symbol: SYMBOL =
@@ -64,20 +65,19 @@
 (*Symbols, which are considered the smallest entities of any Isabelle
   string, may be of the following form:
 
-    (a) ASCII symbols: a
-    (b) printable symbols: \<ident>
-    (c) control symbols: \<^ident>
-    (d) raw control symbols: \<^raw:...>, where "..." may be any printable
-        character excluding ">"
+    (1) ASCII symbols: a
+    (2) printable symbols: \<ident>
+    (3) control symbols: \<^ident>
+    (4) raw control symbols: \<^raw:...>, where "..." may be any printable
+        character excluding ">", or \<^rawNNN> where NNN are digits
 
   Output is subject to the print_mode variable (default: verbatim),
   actual interpretation in display is up to front-end tools.
 
-  Symbols (b),(c) and (d) may optionally start with "\\" instead of
-  just "\" for compatibility with ML string literals (e.g. used in
-  old-style theory files and ML proof scripts).  To be on the safe
-  side, the default output of these symbols will also start with the
-  double "\\".
+  Proper symbols may optionally start with "\\" instead of just "\"
+  for compatibility with ML string literals (e.g. used in old-style
+  theory files and ML proof scripts).  To be on the safe side, the
+  default output of these symbols will start with the double "\\".
 *)
 
 type symbol = string;
@@ -130,6 +130,42 @@
     | _ => false;
 
 
+(* raw symbols *)
+
+fun is_raw s =
+  String.isPrefix "\\<^raw" s andalso String.substring (s, size s - 1, 1) = ">";
+
+fun decode_raw s =
+  if not (is_raw s) then "*** BAD RAW OUTPUT " ^ s ^ " ***"
+  else if String.isPrefix "\\<^raw:" s then String.substring (s, 7, size s - 8)
+  else chr (#1 (Library.read_int (explode (String.substring (s, 6, size s - 7)))));
+
+local
+
+fun raw_chr c = ord space <= ord c andalso ord c <= ord "~" andalso c <> ">";
+
+val raw1 = enclose "\\<^raw:" ">" o implode;
+val raw2 = enclose "\\<^raw" ">" o string_of_int o ord;
+
+fun encode cs = enc (take_prefix raw_chr cs)
+and enc ([], []) = []
+  | enc (cs, []) = [raw1 cs]
+  | enc ([], d :: ds) = raw2 d :: encode ds
+  | enc (cs, d :: ds) = raw1 cs :: raw2 d :: encode ds;
+
+in
+
+val scan_raw =
+ (Scan.this (explode "raw:") -- Scan.any raw_chr ||
+  Scan.this (explode "raw") -- Scan.any1 is_ascii_digit) >> (implode o op @);
+
+fun encode_raw s =
+  if exists_string (not o raw_chr) s then encode (explode s)
+  else [enclose "\\<^raw:" ">" s];
+
+end;
+
+
 (* standard symbol kinds *)
 
 datatype kind = Letter | Digit | Quasi | Blank | Other;
@@ -327,10 +363,7 @@
 val scan_encoded_newline =
   $$ "\r" -- $$ "\n" >> K "\n" ||
   $$ "\r" >> K "\n" ||
-  Scan.optional ($$ "\\") "" -- Scan.list (explode "\\<^newline>") >> K "\n";
-
-fun raw_body c = ord space <= ord c andalso ord c <= ord "~" andalso c <> ">";
-val scan_raw = Scan.list (explode "raw:") -- Scan.any raw_body >> (implode o op @);
+  Scan.optional ($$ "\\") "" -- Scan.this (explode "\\<^newline>") >> K "\n";
 
 in
 
@@ -415,15 +448,29 @@
 
 (* default output *)
 
+local
+
 fun string_size s = (s, real (size s));
 
-fun sym_escape s = if is_char s then s else "\\" ^ s;
+fun sym_output s =
+  if is_char s then s
+  else if is_raw s then decode_raw s
+  else "\\" ^ s;
+
+in
 
 fun default_output s =
   if not (exists_string (equal "\\") s) then string_size s
-  else string_size (implode (map sym_escape (sym_explode s)));
+  else string_size (implode (map sym_output (sym_explode s)));
+
+end;
+
+val plain_output = #1 o default_output;
 
 fun default_indent (_: string, k) = spaces k;
+val default_raw = implode o encode_raw;
+
+val _ = Output.add_mode "" (default_output, default_indent, default_raw);
 
 
 (* print modes *)
@@ -431,28 +478,6 @@
 val symbolsN = "symbols";
 val xsymbolsN = "xsymbols";
 
-val modes =
-  ref (Symtab.empty: ((string -> string * real) * (string * int -> string)) Symtab.table);
-
-fun lookup_mode name = Symtab.lookup (! modes, name);
-
-fun add_mode name m =
- (if is_none (lookup_mode name) then ()
-  else warning ("Redeclaration of symbol print mode " ^ quote name);
-  modes := Symtab.update ((name, m), ! modes));
-
-fun get_mode () =
-  if_none (get_first lookup_mode (! print_mode)) (default_output, default_indent);
-
-
-(* mode output *)
-
-fun output_width x = #1 (get_mode ()) x;
-val output = #1 o output_width;
-val plain_output = #1 o default_output;
-
-fun indent x = #2 (get_mode ()) x;
-
 
 (*final declarations of this structure!*)
 val length = sym_length;