--- /dev/null
+(* $Id$ *)
+
+open Parser
+
+type tags = [`none|`control|`define|`structure|`char|`infix|`label|`uident]
+
+let colors : (tags * GDraw.color) list Lazy.t =
+ lazy
+ (List.map ~f:(fun (tag,col) -> tag, `COLOR (GDraw.color (`NAME col)))
+ [ `control, "blue";
+ `define, "forestgreen";
+ `structure, "purple";
+ `char, "gray40";
+ `infix, "indianred4";
+ `label, "brown";
+ `uident, "midnightblue";
+ `none, "black" ])
+
+let tag ?(start=0) ?stop:pend (tw : GEdit.text) =
+ let pend = Gaux.default tw#length ~opt:pend in
+ let colors = Lazy.force colors in
+ tw#freeze ();
+ let position = tw#position
+ and text = tw#get_chars ~start ~stop:pend in
+ let replace ~start:pstart ~stop:pend ~tag =
+ if pend > pstart then begin
+ tw#delete_text ~start:(start+pstart) ~stop:(start+pend);
+ tw#set_point (start+pstart);
+ tw#insert ~foreground:(List.assoc tag colors)
+ (String.sub text ~pos:pstart ~len:(pend-pstart));
+ end
+ and next_lf = ref (-1) in
+ let colorize ~start:rstart ~stop:rend ~tag =
+ let rstart = ref rstart in
+ while !rstart < rend do
+ if !next_lf < !rstart then begin
+ try next_lf := String.index_from text !rstart '\n'
+ with Not_found -> next_lf := pend-start
+ end;
+ replace ~start:!rstart ~stop:(min !next_lf rend) ~tag;
+ rstart := !next_lf + 1
+ done
+ in
+ let buffer = Lexing.from_string text
+ and last = ref (EOF, 0, 0)
+ and last_pos = ref 0 in
+ try
+ while true do
+ let token = Lexer.token buffer
+ and start = Lexing.lexeme_start buffer
+ and stop = Lexing.lexeme_end buffer in
+ let tag =
+ match token with
+ AMPERAMPER
+ | AMPERSAND
+ | BARBAR
+ | DO | DONE
+ | DOWNTO
+ | ELSE
+ | FOR
+ | IF
+ | LAZY
+ | MATCH
+ | OR
+ | THEN
+ | TO
+ | TRY
+ | WHEN
+ | WHILE
+ | WITH
+ -> `control
+ | AND
+ | AS
+ | BAR
+ | CLASS
+ | CONSTRAINT
+ | EXCEPTION
+ | EXTERNAL
+ | FUN
+ | FUNCTION
+ | FUNCTOR
+ | IN
+ | INHERIT
+ | INITIALIZER
+ | LET
+ | METHOD
+ | MODULE
+ | MUTABLE
+ | NEW
+ | OF
+ | PARSER
+ | PRIVATE
+ | REC
+ | TYPE
+ | VAL
+ | VIRTUAL
+ -> `define
+ | BEGIN
+ | END
+ | INCLUDE
+ | OBJECT
+ | OPEN
+ | SIG
+ | STRUCT
+ -> `structure
+ | CHAR _
+ | STRING _
+ -> `char
+ | BACKQUOTE
+ | INFIXOP1 _
+ | INFIXOP2 _
+ | INFIXOP3 _
+ | INFIXOP4 _
+ | PREFIXOP _
+ | QUESTION2
+ | SHARP
+ -> `infix
+ | LABEL _
+ | OPTLABEL _
+ | QUESTION
+ | TILDE
+ -> `label
+ | UIDENT _ -> `uident
+ | LIDENT _ ->
+ begin match !last with
+ (QUESTION | TILDE), _, _ -> `label
+ | _ -> `none
+ end
+ | COLON ->
+ begin match !last with
+ LIDENT _, lstart, lstop when lstop = start ->
+ colorize ~tag:`none ~start:!last_pos ~stop:lstart;
+ colorize ~tag:`label ~start:lstart ~stop;
+ last_pos := stop;
+ `none
+ | _ -> `none
+ end
+ | EOF -> raise End_of_file
+ | _ -> `none
+ in
+ if tag <> `none then begin
+ colorize ~tag:`none ~start:!last_pos ~stop:start;
+ colorize ~tag ~start ~stop;
+ last_pos := stop
+ end;
+ last := (token, start, stop)
+ done
+ with exn ->
+ colorize ~tag:`none ~start:!last_pos ~stop:(pend-start);
+ tw#thaw ();
+ tw#set_position position;
+ tw#set_point position;
+ match exn with
+ End_of_file | Lexer.Error _ -> ()
+ | _ -> raise exn