xstrp4_here_lexer.mll 3.6 KB
Newer Older
gerd's avatar
gerd committed
1
(* $Id$
gerd's avatar
gerd committed
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
 * ----------------------------------------------------------------------
 *
 *)

{
  open Xstrp4_here_types

  type val_id = LC of string | UC of string | End_of_id

  let rec parse_val_id f buf =
    let id = f buf in
      match id with
	  UC s -> s :: parse_val_id f buf 
	| LC s -> [s]
	| End_of_id -> []
}

let ucletter = [ 'A' - 'Z' ]
let lcletter = [ 'a' - 'z' '_' ] 
let acletter = ucletter | lcletter

let format = '%'
             [ '0' '-' ' ' ]*    (* no more modifiers are supported by Ocaml *)
             ['0'-'9']* 
             ( '.' ['0'-'9']* )?
27 28 29
	     ( ( ['L' 'l' 'n'] [ 'd' 'i' 'u' 'x' 'X' 'o' ])
	       | [ 'd' 'i' 'u' 'x' 'X' 's' 'c' 'f' 'e' 'E' 'g' 'G' 'b' 'a' 't' ]
	     )
gerd's avatar
gerd committed
30 31 32 33 34

rule token = parse
    '$' ( ucletter acletter* '.' )* lcletter acletter*
      { let s = Lexing.lexeme lexbuf in
	let buf = Lexing.from_string (String.sub s 1 (String.length s - 1)) in
gerd's avatar
gerd committed
35 36
	let start_p = Lexing.lexeme_start_p lexbuf in
	let end_p = Lexing.lexeme_end_p lexbuf in
gerd's avatar
gerd committed
37 38
	  Variable (parse_val_id value_identifier buf, 
		    "%s",
gerd's avatar
gerd committed
39 40
		    ({ start_p with Lexing.pos_cnum = start_p.Lexing.pos_cnum (* + 1 *) },
		    end_p))
gerd's avatar
gerd committed
41 42 43 44 45 46 47 48 49 50 51 52 53 54
      }
  | '$' '{' ( ucletter acletter* '.' )* lcletter acletter*
            ( ',' format )?  
        '}'
      { let s = Lexing.lexeme lexbuf in
	let k_close = String.index s '}' in
	let k_percent = try String.index s '%' with Not_found -> (-1) in
	let buf = Lexing.from_string (String.sub s 2 (k_close - 1)) in
	let fmt = 
	  if k_percent >= 0 then
	    String.sub s k_percent (String.length s - k_percent - 1)
	  else
	    "%s"
	in
gerd's avatar
gerd committed
55 56
	let start_p = Lexing.lexeme_start_p lexbuf in
	let end_p = Lexing.lexeme_end_p lexbuf in
gerd's avatar
gerd committed
57 58 59
	let start = Lexing.lexeme_start lexbuf in
	Variable (parse_val_id value_identifier buf, 
		  fmt,
gerd's avatar
gerd committed
60 61 62 63
		  ({ start_p with Lexing.pos_cnum = start_p.Lexing.pos_cnum (* + 2 *) },
		   { end_p with Lexing.pos_cnum = end_p.Lexing.pos_cnum (* + 
						 (if k_percent >= 0 then k_percent-1 else k_close) *) })
		 )
gerd's avatar
gerd committed
64 65 66 67
      }
  | '$'
      { failwith "Bad $ expander" }
  | '\\' '\n' 
gerd's avatar
gerd committed
68
      { Literal("", (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf)) }
gerd's avatar
gerd committed
69
  | '\\' '$'
gerd's avatar
gerd committed
70
      { Literal("$", (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf)) }
gerd's avatar
gerd committed
71
  | '\\' [ '0'-'9' ] [ '0'-'9' ] [ '0'-'9' ]
gerd's avatar
gerd committed
72 73 74 75
      {  let s = Lexing.lexeme lexbuf in
	 let n = int_of_string(String.sub s 1 3) in
         let lit = Printf.sprintf "%c" (Char.chr n) in
	 Literal(lit, (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf))
gerd's avatar
gerd committed
76
      }
gerd's avatar
gerd committed
77 78
(*
  | '\\' 'o' [ '0'-'7' ] [ '0'-'7' ] [ '0'-'7' ]
gerd's avatar
gerd committed
79 80 81 82 83
      {  Literal (let s = Lexing.lexeme lexbuf in
		  let n = int_of_string("0" ^ String.sub s 1 4) in
                  Printf.sprintf "%c" (Char.chr n)
		 ) 
      }
gerd's avatar
gerd committed
84
*)
gerd's avatar
gerd committed
85
  | '\\' 'x' [ '0'-'9' 'a'-'f' 'A'-'F' ] [ '0'-'9' 'a'-'f' 'A'-'F' ]
gerd's avatar
gerd committed
86 87 88 89
      {  let s = Lexing.lexeme lexbuf in
	 let n = int_of_string("0" ^ String.sub s 1 3) in
         let lit = Printf.sprintf "%c" (Char.chr n) in
	 Literal(lit, (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf))
gerd's avatar
gerd committed
90 91
      }

gerd's avatar
gerd committed
92
  | '\\' _
gerd's avatar
gerd committed
93 94 95
      { let lit = Lexing.lexeme lexbuf in
	 Literal(lit, (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf))
      }
gerd's avatar
gerd committed
96
  | [^ '$' '\\']+
gerd's avatar
gerd committed
97 98 99
      { let lit = Lexing.lexeme lexbuf in
	 Literal(lit, (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf))
      }
gerd's avatar
gerd committed
100 101 102
  | eof 
      { Textend }
  | _ 
gerd's avatar
gerd committed
103 104 105
      { let lit = Lexing.lexeme lexbuf in
	 Literal(lit, (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf))
      }
gerd's avatar
gerd committed
106 107 108 109 110 111 112 113 114 115 116

and value_identifier = parse
    ucletter acletter* '.'
      { let s = Lexing.lexeme lexbuf in
	  UC (String.sub s 0 (String.length s - 1))
      }
  | lcletter acletter*
      { LC(Lexing.lexeme lexbuf) }
  | eof
      { End_of_id }