summaryrefslogtreecommitdiffstats
path: root/tools/cvt_emit.mll
blob: 723274c4adc1714ed8bf8cd8d0ea64cd70562212 (plain)
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
(***********************************************************************)
(*                                                                     *)
(*                                OCaml                                *)
(*                                                                     *)
(*            Xavier Leroy, projet Cristal, INRIA Rocquencourt         *)
(*                                                                     *)
(*  Copyright 1996 Institut National de Recherche en Informatique et   *)
(*  en Automatique.  All rights reserved.  This file is distributed    *)
(*  under the terms of the Q Public License version 1.0.               *)
(*                                                                     *)
(***********************************************************************)

(* $Id$ *)

{
let first_item = ref false
let command_beginning = ref 0

let add_semicolon () =
  if !first_item
  then first_item := false
  else print_string "; "

let print_unescaped_string s =
  let l = String.length s in
  let i = ref 0 in
  while !i < l do
    if s.[!i] = '\\'
    && !i+1 < l
    && (let c = s.[!i+1] in c = '{' || c = '`') (* ` *)
    then i := !i+1;
    print_char s.[!i];
    i := !i + 1
  done
}

rule main = parse
    "`" { command_beginning := Lexing.lexeme_start lexbuf;
          first_item := true;
          print_char '(';
          command lexbuf;
          print_char ')';
          main lexbuf }
  | "\\`"
        { print_string "`"; main lexbuf }
  | eof { () }
  | _   { print_char(Lexing.lexeme_char lexbuf 0); main lexbuf }

and command = parse
    "`" { () }
  | eof { prerr_string "Unterminated `...` at character ";
          prerr_int !command_beginning;
          prerr_newline();
          exit 2 }
  | "{" [^ '}'] * "}"
        { let s = Lexing.lexeme lexbuf in
          add_semicolon();
          print_string (String.sub s 1 (String.length s - 2));
          command lexbuf }
  | ( [^ '`' '{' '\\'] |
      '\\' ['\\' '"' 'n' 't' 'b' 'r' '`' '{' ] |
      '\\' ['0'-'9'] ['0'-'9'] ['0'-'9'] |
      '\\' ('\n' | "\r\n")) +
        { let s = Lexing.lexeme lexbuf in
          add_semicolon();
          (* Optimise one-character strings *)
          if String.length s = 1 && s.[0] <> '\\' && s.[0] <> '\''
          || String.length s = 2 && s.[0] = '\\' && s.[1] <> '`' && s.[1]<>'{'
          (* ` *)
          then begin
            print_string "emit_char '";
            print_unescaped_string s;
            print_string "'"
          end else begin
            print_string "emit_string \"";
            print_unescaped_string s;
            print_string "\""
          end;
          command lexbuf }

{
let _ = main(Lexing.from_channel stdin)

let _ = exit (0)
}