(* $Id: xstrp4_here_lexer.mll 23 2004-07-13 21:03:13Z gerd $
* ----------------------------------------------------------------------
*
*)
{
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']* )?
( ( ['L' 'l' 'n'] [ 'd' 'i' 'u' 'x' 'X' 'o' ])
| [ 'd' 'i' 'u' 'x' 'X' 's' 'c' 'f' 'e' 'E' 'g' 'G' 'b' 'a' 't' ]
)
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
let start_p = Lexing.lexeme_start_p lexbuf in
let end_p = Lexing.lexeme_end_p lexbuf in
Variable (parse_val_id value_identifier buf,
"%s",
({ start_p with Lexing.pos_cnum = start_p.Lexing.pos_cnum (* + 1 *) },
end_p))
}
| '$' '{' ( 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
let start_p = Lexing.lexeme_start_p lexbuf in
let end_p = Lexing.lexeme_end_p lexbuf in
let start = Lexing.lexeme_start lexbuf in
Variable (parse_val_id value_identifier buf,
fmt,
({ 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) *) })
)
}
| '$'
{ failwith "Bad $ expander" }
| '\\' '\n'
{ Literal("", (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf)) }
| '\\' '$'
{ Literal("$", (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf)) }
| '\\' [ '0'-'9' ] [ '0'-'9' ] [ '0'-'9' ]
{ 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))
}
(*
| '\\' 'o' [ '0'-'7' ] [ '0'-'7' ] [ '0'-'7' ]
{ 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)
)
}
*)
| '\\' 'x' [ '0'-'9' 'a'-'f' 'A'-'F' ] [ '0'-'9' 'a'-'f' 'A'-'F' ]
{ 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))
}
| '\\' _
{ let lit = Lexing.lexeme lexbuf in
Literal(lit, (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf))
}
| [^ '$' '\\']+
{ let lit = Lexing.lexeme lexbuf in
Literal(lit, (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf))
}
| eof
{ Textend }
| _
{ let lit = Lexing.lexeme lexbuf in
Literal(lit, (Lexing.lexeme_start_p lexbuf, Lexing.lexeme_end_p lexbuf))
}
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 }