-
Notifications
You must be signed in to change notification settings - Fork 86
/
Copy pathparse.ml
106 lines (91 loc) · 4.27 KB
/
parse.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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
(**************************************************************************)
(* *)
(* 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 GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
(* Entry points in the parser *)
(* Skip tokens to the end of the phrase *)
let last_token = ref Parser.EOF
let token lexbuf =
let token = Lexer.token lexbuf in
last_token := token;
token
let rec skip_phrase lexbuf =
match token lexbuf with
| Parser.SEMISEMI | Parser.EOF -> ()
| _ -> skip_phrase lexbuf
| exception (Lexer.Error (Lexer.Unterminated_comment _, _)
| Lexer.Error (Lexer.Unterminated_string, _)
| Lexer.Error (Lexer.Reserved_sequence _, _)
| Lexer.Error (Lexer.Unterminated_string_in_comment _, _)
| Lexer.Error (Lexer.Illegal_character _, _)) ->
skip_phrase lexbuf
let maybe_skip_phrase lexbuf =
match !last_token with
| Parser.SEMISEMI | Parser.EOF -> ()
| _ -> skip_phrase lexbuf
type 'a parser =
(Lexing.lexbuf -> Parser.token) -> Lexing.lexbuf -> 'a
let wrap (parser : 'a parser) lexbuf : 'a =
try
Docstrings.init ();
Lexer.init ();
let ast = parser token lexbuf in
Parsing.clear_parser();
Docstrings.warn_bad_docstrings ();
last_token := Parser.EOF;
ast
with
| Lexer.Error(Lexer.Illegal_character _, _) as err
when !Location.input_name = "//toplevel//"->
skip_phrase lexbuf;
raise err
| Syntaxerr.Error _ as err
when !Location.input_name = "//toplevel//" ->
maybe_skip_phrase lexbuf;
raise err
| Parsing.Parse_error | Syntaxerr.Escape_error ->
let loc = Location.curr lexbuf in
if !Location.input_name = "//toplevel//"
then maybe_skip_phrase lexbuf;
raise(Syntaxerr.Error(Syntaxerr.Other loc))
(* We pass [--strategy simplified] to Menhir, which means that we wish to use
its "simplified" strategy for handling errors. When a syntax error occurs,
the current token is replaced with an [error] token. The parser then
continues shifting and reducing, as far as possible. After (possibly)
shifting the [error] token, though, the parser remains in error-handling
mode, and does not request the next token, so the current token remains
[error].
In OCaml's grammar, the [error] token always appears at the end of a
production, and this production always raises an exception. In such
a situation, the strategy described above means that:
- either the parser will not be able to shift [error],
and will raise [Parser.Error];
- or it will be able to shift [error] and will then reduce
a production whose semantic action raises an exception.
In either case, the parser will not attempt to read one token past
the syntax error. *)
let implementation = wrap Parser.implementation
and interface = wrap Parser.interface
and toplevel_phrase = wrap Parser.toplevel_phrase
and use_file = wrap Parser.use_file
and core_type = wrap Parser.parse_core_type
and expression = wrap Parser.parse_expression
and pattern = wrap Parser.parse_pattern
let module_type = wrap Parser.parse_module_type
let module_expr = wrap Parser.parse_module_expr
let longident = wrap Parser.parse_any_longident
let val_ident = wrap Parser.parse_val_longident
let constr_ident= wrap Parser.parse_constr_longident
let extended_module_path = wrap Parser.parse_mod_ext_longident
let simple_module_path = wrap Parser.parse_mod_longident
let type_ident = wrap Parser.parse_mty_longident