open Printf;;
open Random;;
(* Add the contents of the line as a new set of substitutions to the wordlist,
and return the new list. *)
let update_wordlist line wordlist =
wordlist @ [ List.filter (fun s -> not (s = ""))
(String.split_on_char ' ' line) ];;
(* Return the next position in the string which is not a digit, if any, or
the length, if none. *)
let rec next_non_digit str pos =
if (String.length str) <= pos || str.[pos] < '0' || str.[pos] > '9' then
pos
else
next_non_digit str (pos + 1);;
(* Take the word list and the index, and choose a random string. If the
index is out of range, return "[error]". Also, paranoia check for the
the chosen list to be empty, in which case the empty string is returned. *)
let find_sub wordlist index =
if (List.length wordlist) <= index then "[error]"
else
let chosen_list = List.nth wordlist index in
if (List.length chosen_list) <= 0 then ""
else List.nth chosen_list (Random.int (List.length chosen_list))
(* Copy the string with substitutions. *)
let rec process_text_line wordlist line =
(* Find the first hash mark denoting the substitution. *)
let numpos = try String.index line '#' with _ -> -1 in
(* If there's no hash mark, just return the string. *)
if numpos = -1 then line
else
(* Isolate the part of the string before the #, the part
after the hash, and the digits making up the list number. *)
let prepart = String.sub line 0 numpos in
let firstkeep = next_non_digit line (numpos + 1) in
let indexpart = String.sub line (numpos + 1) (firstkeep - numpos - 1) in
let postpart =
String.sub line firstkeep ((String.length line) - firstkeep) in
(* The result is the part before the #, the substitution provided by
find_sub, then the part after the #NNN, after passing back through
process_text_line to handle any additional substitutions. If the
index string is empty, use empty string for the substitution. *)
prepart ^
(if indexpart = "" then ""
else (find_sub wordlist (int_of_string indexpart))) ^
(process_text_line wordlist postpart);;
(* Read the wordlist section and update and return the wordlist. *)
let rec read_wordlist stream wordlist =
let line = input_line stream in
if line = "-" then wordlist
else read_wordlist stream (update_wordlist line wordlist);;
(* Take a line and a stream, read the stream and process the instruction
against the line, and return the new line. *)
let rec copy_with_sub stream wordlist =
try
printf "%s\n" (process_text_line wordlist (input_line stream));
copy_with_sub stream wordlist
with _ -> ();;
(* Process the input. *)
let process_input stream =
copy_with_sub stream (read_wordlist stream [ ] );;
(* Start it up. *)
Random.self_init ();
process_input stdin;;