Source file solidity_parser.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
open Solidity_common
open Solidity_ast
let get_imported_files m =
let base = Filename.dirname m.module_file in
List.fold_left (fun fileset unit_node ->
match strip unit_node with
| Import { import_from; _ } ->
let file = make_absolute_path base import_from in
StringSet.add file fileset
| _ -> fileset
) StringSet.empty m.module_units
let parse_module id file =
let c = open_in file in
let lb = Lexing.from_channel c in
let module_units =
Solidity_raw_parser.module_units
Solidity_lexer.token lb
in
close_in c;
{ module_file = file; module_id = Ident.root id; module_units }
let parse file =
let file = make_absolute_path (Sys.getcwd ()) file in
let files = ref (StringSet.singleton file) in
let to_parse = Queue.create () in
StringSet.iter (fun file -> Queue.push file to_parse) !files;
let modules = ref [] in
let id = ref (-1) in
while not (Queue.is_empty to_parse) do
let file = Queue.pop to_parse in
let m = parse_module (id := !id + 1; !id) file in
modules := m :: !modules;
let imported_files = get_imported_files m in
let new_files = StringSet.diff imported_files !files in
files := StringSet.union new_files !files;
StringSet.iter (fun file -> Queue.push file to_parse) new_files
done;
let program_modules, program_modules_by_id, program_modules_by_file =
List.fold_left (fun (mods, mods_by_id, mods_by_file) m ->
m :: mods,
IdentMap.add m.module_id m mods_by_id,
StringMap.add m.module_file m mods_by_file
) ([], IdentMap.empty, StringMap.empty) !modules
in
{ program_modules; program_modules_by_id; program_modules_by_file }