forked from ManasJayanth/flow
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathflow_parser_js.ml
121 lines (103 loc) · 4.09 KB
/
flow_parser_js.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
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
(**
* Copyright (c) 2013-present, Facebook, Inc.
*
* This source code is licensed under the MIT license found in the
* LICENSE file in the root directory of this source tree.
*)
module JsTranslator : sig
val translation_errors: (Loc.t * Parse_error.t) list ref
include Translator_intf.S
end = struct
type t = Js.Unsafe.any
let translation_errors = ref []
let string x = Js.Unsafe.inject (Js.string x)
let bool x = Js.Unsafe.inject (Js.bool x)
let obj props = Js.Unsafe.inject (Js.Unsafe.obj (Array.of_list props))
let array arr = Js.Unsafe.inject (Js.array (Array.of_list arr))
let number x = Js.Unsafe.inject (Js.number_of_float x)
let null = Js.Unsafe.inject Js.null
let regexp loc pattern flags =
let regexp = try
Js.Unsafe.new_obj (Js.Unsafe.variable "RegExp") [|
string pattern;
string flags;
|]
with _ ->
translation_errors := (loc, Parse_error.InvalidRegExp)::!translation_errors;
(* Invalid RegExp. We already validated the flags, but we've been
* too lazy to write a JS regexp parser in Ocaml, so we didn't know
* the pattern was invalid. We'll recover with an empty pattern.
*)
Js.Unsafe.new_obj (Js.Unsafe.variable "RegExp") [|
string "";
string flags;
|]
in
Js.Unsafe.inject regexp
end
module Translate = Estree_translator.Translate (JsTranslator) (struct
let include_comments = true
let include_locs = true
end)
module Token_translator = Token_translator.Translate (JsTranslator)
let parse_options jsopts = Parser_env.(
let opts = default_parse_options in
let decorators = Js.Unsafe.get jsopts "esproposal_decorators" in
let opts = if Js.Optdef.test decorators
then { opts with esproposal_decorators = Js.to_bool decorators; }
else opts in
let class_instance_fields = Js.Unsafe.get jsopts "esproposal_class_instance_fields" in
let opts = if Js.Optdef.test class_instance_fields
then { opts with esproposal_class_instance_fields = Js.to_bool class_instance_fields; }
else opts in
let class_static_fields = Js.Unsafe.get jsopts "esproposal_class_static_fields" in
let opts = if Js.Optdef.test class_static_fields
then { opts with esproposal_class_static_fields = Js.to_bool class_static_fields; }
else opts in
let export_star_as = Js.Unsafe.get jsopts "esproposal_export_star_as" in
let opts = if Js.Optdef.test export_star_as
then { opts with esproposal_export_star_as = Js.to_bool export_star_as; }
else opts in
let optional_chaining = Js.Unsafe.get jsopts "esproposal_optional_chaining" in
let opts = if Js.Optdef.test optional_chaining
then { opts with esproposal_optional_chaining = Js.to_bool optional_chaining; }
else opts in
let nullish_coalescing = Js.Unsafe.get jsopts "esproposal_nullish_coalescing" in
let opts = if Js.Optdef.test nullish_coalescing
then { opts with esproposal_nullish_coalescing = Js.to_bool nullish_coalescing; }
else opts in
let types = Js.Unsafe.get jsopts "types" in
let opts = if Js.Optdef.test types
then { opts with types = Js.to_bool types; }
else opts in
opts
)
let translate_tokens tokens =
JsTranslator.array (List.rev_map Token_translator.token tokens)
let parse content options =
let options =
if options = Js.undefined
then Js.Unsafe.obj [||]
else options
in
let content = Js.to_string content in
let parse_options = Some (parse_options options) in
let include_tokens =
let tokens = Js.Unsafe.get options "tokens" in
Js.Optdef.test tokens && Js.to_bool tokens
in
let rev_tokens = ref [] in
let token_sink =
if include_tokens then
Some (fun token_data ->
rev_tokens := token_data::!rev_tokens
)
else None
in
let (ocaml_ast, errors) = Parser_flow.program ~fail:false ~parse_options ~token_sink content in
JsTranslator.translation_errors := [];
let ret = Translate.program ocaml_ast in
let translation_errors = !JsTranslator.translation_errors in
Js.Unsafe.set ret "errors" (Translate.errors (errors @ translation_errors));
if include_tokens then Js.Unsafe.set ret "tokens" (translate_tokens !rev_tokens);
ret