-
Notifications
You must be signed in to change notification settings - Fork 1
/
sedlex_menhir.ml
80 lines (69 loc) · 2.14 KB
/
sedlex_menhir.ml
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
(*
Boilerplate for using sedlex with Menhir, based on
https://github.com/Drup/llvm/blob/3c43000f4e86af5b9b368f50721604957d403750/test/Bindings/OCaml/kaleidoscope/src/syntax.ml
*)
(** The state of the parser, a stream and a position. *)
type lexbuf = {
stream : Sedlexing.lexbuf ;
mutable pos : Lexing.position ;
}
(** Initialize with the null position. *)
let create_lexbuf ?(file="") stream =
let pos = {Lexing.
pos_fname = file;
pos_lnum = 1; (* Start lines at 1, not 0 *)
pos_bol = 0;
pos_cnum = 0;
}
in { pos ; stream }
(** Register a new line in the lexer's position. *)
let new_line ?(n=0) lexbuf =
let open Lexing in
let lcp = lexbuf.pos in
lexbuf.pos <-
{lcp with
pos_lnum = lcp.pos_lnum + 1;
pos_bol = lcp.pos_cnum;
}
(** Update the position with the stream. *)
let update lexbuf =
let new_pos = Sedlexing.lexeme_end lexbuf.stream in
let p = lexbuf.pos in
lexbuf.pos <- {p with Lexing.pos_cnum = new_pos }
(** The last matched word. *)
let lexeme { stream } = Sedlexing.Utf8.lexeme stream
(** [ParseError (file, line, col, token)] *)
exception ParseError of (string * int * int * string)
let string_of_ParseError (file, line, cnum, tok) =
let file_to_string file =
if file = "" then ""
else " on file " ^ file
in
Printf.sprintf
"Parse error%s line %i, column %i, token %s"
(file_to_string file)
line cnum tok
let raise_ParseError lexbuf =
let { pos } = lexbuf in
let tok = lexeme lexbuf in
let open Lexing in
let line = pos.pos_lnum in
let col = pos.pos_cnum - pos.pos_bol in
Printf.fprintf stderr "Parse error: %s\n" (string_of_ParseError (pos.pos_fname, line, col, tok));
raise @@ ParseError (pos.pos_fname, line, col, tok)
let sedlex_with_menhir lexer' parser' lexbuf =
let lexer () =
let ante_position = lexbuf.pos in
let token = lexer' lexbuf in
let post_position = lexbuf.pos
in (token, ante_position, post_position) in
let parser =
MenhirLib.Convert.Simplified.traditional2revised parser'
in
try
parser lexer
with
| Parser.Error
| Sedlexing.MalFormed
| Sedlexing.InvalidCodepoint _
-> raise_ParseError lexbuf