blob: d406b0e699ba883ae313bc5d2f67f00d72cafc60 (
plain)
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
<(** The signature for an expression analyzer.
Every element is mapped to a function, using the tagless final pattern. *)
module type SYM_EXPR = sig
type 'a repr
type 'a obs
type 'a path_repr
val empty : unit -> 'a repr
val expr : 'a repr -> 'a repr
val literal : string -> 'a repr
val integer : string -> 'a repr
val path : 'a path_repr -> 'a -> 'a repr
val concat : 'a repr list ->open StdLabels
module Table = ImportDataTypes.Table
module Path = ImportDataTypes.Path
module ExpressionParser : sig
type 'a path_builder
val path : Path.t path_builder
val column : Path.column path_builder
val of_string :
'a path_builder -> string -> ('a ImportExpression.T.t, string) result
end = struct
module MI = Expression_parser.MenhirInterpreter
module E = MenhirLib.ErrorReports
module L = MenhirLib.LexerUtil
type error = {
message : string;
start_line : int;
start_pos : int;
end_pos : int;
}
let range_message start_pos end_pos message =
let start_c = start_pos.Lexing.pos_cnum - start_pos.Lexing.pos_bol
and end_c = end_pos.Lexing.pos_cnum - end_pos.Lexing.pos_bol in
{
message;
start_line = start_pos.Lexing.pos_bol;
start_pos = start_c;
end_pos = end_c;
}
(** Extract the line in error from the whole expression, and print some
characters just under the faulty part *)
let get_line_error : error -> string -> string =
fun error content ->
let sub_text =
try
let end_pos = String.index_from content error.start_line '\n' in
String.sub content ~pos:error.start_line
~len:(end_pos - error.start_line)
with
| Not_found ->
(* There is no new line, extract the ending part *)
let len = String.length content - error.start_line in
String.sub content ~pos:error.start_line ~len
in
(* I’m not sure how to produce it, but the error may be over two lines.
This line is here to prevent the underline to overflow. *)
let stop_pos = min error.end_pos (String.length sub_text) in
let error_length = stop_pos - error.start_pos in
String.concat ~sep:""
[
sub_text;
"\n";
String.make error.start_pos ' ';
String.make error_length '^';
]
let get_parse_error default_position env : error =
match MI.stack env with
| (lazy Nil) ->
range_message default_position.Lexing.lex_start_p
default_position.Lexing.lex_curr_p "Invalid syntax\n"
| (lazy (Cons (MI.Element (state, _, start_pos, end_pos), _))) ->
let |