Created
October 2, 2018 21:09
-
-
Save lindig/99e6314cbf2ab99cb1c4f4e37374f806 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
(* short names for important modules *) | |
module L = Lexing | |
module B = Buffer | |
type token = | |
| STR of string | |
| VAR of string | |
let get = L.lexeme | |
let sprintf = Printf.sprintf | |
let position lexbuf = | |
let p = lexbuf.L.lex_curr_p in | |
sprintf "%s:%d:%d" | |
p.L.pos_fname p.L.pos_lnum (p.L.pos_cnum - p.L.pos_bol) | |
let set_filename (fname:string) (lexbuf:L.lexbuf) = | |
( lexbuf.L.lex_curr_p <- | |
{ lexbuf.L.lex_curr_p with L.pos_fname = fname } | |
; lexbuf | |
) | |
exception Error of string | |
let error lexbuf fmt = | |
Printf.kprintf (fun msg -> | |
raise (Error ((position lexbuf)^" "^msg))) fmt | |
} | |
rule string b acc = parse | |
| '{' { let s = B.contents b in | |
let v = variable (B.create 100) 0 lexbuf in | |
string (B.create 100) (VAR(v)::STR(s)::acc) lexbuf | |
} | |
| "\\{" { B.add_string b "{" ; string b acc lexbuf } | |
| "\\}" { B.add_string b "}" ; string b acc lexbuf } | |
| "\\" _ { error lexbuf "unrecognized escape: %s" (get lexbuf) } | |
| _ { B.add_string b (get lexbuf); string b acc lexbuf } | |
| eof { let s = B.contents b in | |
let acc = STR(s)::acc in | |
List.rev acc | |
} | |
and variable b n = parse | |
| '}' { if n = 0 then | |
let s = B.contents b in s | |
else begin | |
B.add_string b (get lexbuf); variable b (n-1) lexbuf | |
end | |
} | |
| '{' { B.add_string b (get lexbuf); variable b (n+1) lexbuf } | |
| _ { B.add_string b (get lexbuf); variable b n lexbuf } | |
| eof { error lexbuf "unexpected end of string" } | |
{ | |
let to_string = function | |
| STR(str) -> sprintf "STR(%s)" str | |
| VAR(str) -> sprintf "VAR(%s)" str | |
let main name = | |
let lexbuf = set_filename name @@ L.from_channel stdin in | |
let buf = B.create 100 in | |
string buf [] lexbuf | |
|> List.map to_string | |
|> String.concat " " | |
|> print_endline | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment