1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
|
type environment =
| Normal
| Caml
| Verbatim of string * string
| Verbatim_like
let in_quotes = ref false
let is_alpha c =
('A' <= c && c <= 'Z') || ('a' <= c && c <= 'z')
let is_prefix prefix str =
let length_prefix = String.length prefix in
let length_str = String.length str in
if length_prefix > length_str
then false
else (String.sub str 0 length_prefix) = prefix
let escape = function
| ' ' | '\n' -> "\\ "
| '{' -> "{\\char123}"
| '}' -> "{\\char125}"
| '^' -> "{\\char94}"
| '_' -> "{\\char95}"
| '\\' -> "{\\char92}"
| '~' -> "{\\char126}"
| '$' -> "\\$"
| '&' -> "{\\char38}"
| '#' -> "\\#"
| '%' -> "\\%"
| '\'' -> "{\\textquotesingle}"
| '`' -> "{\\textasciigrave}"
| _ -> ""
let process_normal_line line =
let (verb_mark : char option ref) = ref None in
let l = String.length line in
let i = ref 0 in
while !i<l do
match !verb_mark with
| None ->
(match line.[!i] with
| '"' ->
let r = if !in_quotes then "}}" else "{\\machine{" in
print_string r;
in_quotes := not !in_quotes;
incr i;
| '\\' ->
if !in_quotes
then begin
if (!i < l-1) && (line.[!i+1] = '"' || line.[!i+1] = '\\')
then incr i;
let t = escape line.[!i] in
if t<>"" then print_string t else print_char line.[!i];
incr i;
end else if is_prefix "\\verb" (String.sub line !i (l - !i))
&& not (is_alpha line.[!i+5])
then begin
i := !i+5;
verb_mark := Some line.[!i];
print_string "\\verb";
print_char line.[!i];
incr i;
end else (print_char '\\'; incr i)
| _ ->
if !in_quotes && (escape line.[!i] <> "")
then print_string (escape line.[!i])
else print_char line.[!i];
incr i;
)
| Some mark ->
if line.[!i] = mark
then verb_mark := None
else if line.[!i] = '\'' || line.[!i] = '`'
then Printf.eprintf "Warning: %c found in \\verb\n" line.[!i];
print_char line.[!i];
incr i;
done
let process_line line = function
| Normal ->
if is_prefix "\\begin{caml_" line || is_prefix "\\begin{rawhtml}" line
then (print_string line; Verbatim_like)
else if is_prefix "\\begin{camlexample}" line
then (print_endline line; Caml)
else if is_prefix "\\begin{verbatim}" line
then begin
print_string "\\begin{machineenv}";
(Verbatim ("\\end{verbatim}", "\\end{machineenv}"))
end else if is_prefix "\\begin{ocamldoccode}" line
then begin
print_string "\\begin{ocamldoccode}";
(Verbatim ("\\end{ocamldoccode}", "\\end{ocamldoccode}"))
end else begin
process_normal_line line;
if !in_quotes
then print_string (escape '\n')
else print_newline();
Normal
end
| Caml ->
print_endline line;
if is_prefix "\\end{camlexample}" line then Normal else Caml
| Verbatim (verbatim_end_in, verbatim_end_out) as env ->
if is_prefix verbatim_end_in line
then begin
print_string verbatim_end_out;
Normal
end else begin
for i=0 to (String.length line) - 1 do
let c = line.[i] in
let t = escape c in
if c=' ' || c='\n' || t=""
then print_char c
else print_string t
done;
print_newline();
env
end
| Verbatim_like ->
print_endline line;
if is_prefix "\\end{caml_" line || is_prefix "\\end{rawhtml}" line
then Normal
else Verbatim_like
let rec process_input env = match input_line stdin with
| exception End_of_file -> ()
| line ->
let env = process_line line env in
process_input env
let main() =
print_endline "% THIS FILE IS GENERATED.";
print_newline();
process_input Normal
let _ = main()
|