Alternate if syntax support
[hiphop-php.git] / hphp / hack / src / parser / hack_grammar_descriptor_helper.ml
blob9c78869d459c0bee6e191f842bca338ddba2e6a3
1 (**
2 * Copyright (c) 2016, Facebook, Inc.
3 * All rights reserved.
5 * This source code is licensed under the BSD-style license found in the
6 * LICENSE file in the "hack" directory of this source tree. An additional grant
7 * of patent rights can be found in the PATENTS file in the same directory.
9 *)
11 module type Grammar = sig
12 type term
14 type nonterm
16 type symbol =
17 | Term of term
18 | NonTerm of nonterm
20 val start : nonterm
22 val grammar : nonterm -> symbol list list
24 val to_string : term -> string
26 val nonterm_to_string : nonterm -> string
28 end
30 module HackGrammarTypeDef = struct
31 module TokenKind = Full_fidelity_token_kind
33 type term = TokenKind.t
34 and nonterm = string * (unit -> symbol list list)
35 and symbol =
36 | Term of term
37 | NonTerm of nonterm
38 end
40 module HackGrammarHelper = struct
42 let is_keyword text =
43 let text = String.lowercase_ascii text in
44 match Full_fidelity_token_kind.from_string text with
45 | Some _ -> true
46 | _ -> false
48 (* generate a random name *)
49 let rec gen_name () =
50 let var_length_max = 8 in
51 let alpha_size = 26 in (* 26 English alphabet *)
52 let postfix_size = Random.int var_length_max in
53 let first_symbol = int_of_char 'a' + Random.int alpha_size in
54 let second_symbol = int_of_char 'A' + Random.int alpha_size in
55 let generate () =
56 match Random.int (2 * alpha_size) with
57 | n when n < 26 -> int_of_char 'a' + n
58 | n -> int_of_char 'A' + n - 26
60 let init_fun i =
61 char_of_int (if i = 0 then first_symbol
62 else if i = 1 then second_symbol
63 else generate ()) in
64 let result = String.init (postfix_size + 2) init_fun in
65 if is_keyword result then gen_name() else result
67 (* create the powerset of the given set in lists. For our use case, the
68 * original and the resultant sets are ordered and the function should
69 * preserve the order *)
70 let power_set lst =
71 let folder acc el = [] :: List.map (fun lst -> el :: lst) acc in
72 List.fold_left folder [[]] (List.rev lst)
74 (* return the combinations of all pairs from each of list1 and list2
75 * The pair is ordered so that the element in list 1 is the first argument to
76 * the combinor *)
77 let cross lst1 lst2 combinor =
78 List.flatten
79 (List.map (fun x -> List.map (fun y -> combinor x y) lst2 ) lst1)
80 end
82 module HackGrammarTermSpec = struct
83 include HackGrammarTypeDef
84 include HackGrammarHelper
86 open TokenKind
88 (************************ Definition of terms ****************************)
89 let term_array = Term Array
90 let term_list = Term List
91 let name = Term Name
92 let equal = Term Equal
93 let backslash = Term Backslash
94 let equal_equal = Term EqualEqual
95 let equal_equal_equal = Term EqualEqualEqual
96 let equal_greater_than = Term EqualGreaterThan
97 let equal_equal_greater_than = Term EqualEqualGreaterThan
98 let dollar = Term Dollar
99 let dollar_dollar = Term DollarDollar
100 let star_star_equal = Term StarStarEqual
101 let star_equal = Term StarEqual
102 let slash_equal = Term SlashEqual
103 let percent_equal = Term PercentEqual
104 let plus_equal = Term PlusEqual
105 let plus_plus = Term PlusPlus
106 let minus_minus = Term MinusMinus
107 let at = Term At
108 let plus = Term Plus
109 let minus = Term Minus
110 let star = Term Star
111 let slash = Term Slash
112 let percent = Term Percent
113 let dot = Term Dot
114 let ampersand = Term Ampersand
115 let ampersand_ampersand = Term AmpersandAmpersand
116 let carat = Term Carat
117 let bar = Term Bar
118 let bar_bar = Term BarBar
119 let exclamation = Term Exclamation
120 let exclamation_equal = Term ExclamationEqual
121 let exclamation_equal_equal = Term ExclamationEqualEqual
122 let tilde = Term Tilde
123 let minus_equal = Term MinusEqual
124 let dot_equal = Term DotEqual
125 let dot_dot_dot = Term DotDotDot
126 let less_than = Term LessThan
127 let less_than_equal = Term LessThanEqual
128 let less_than_less_than = Term LessThanLessThan
129 let less_less_equal = Term LessThanLessThanEqual
130 let greater_than = Term GreaterThan
131 let greater_than_equal = Term GreaterThanEqual
132 let greater_than_greater_than = Term GreaterThanGreaterThan
133 let greater_greater_equal = Term GreaterThanGreaterThanEqual
134 let ampersand_equal = Term AmpersandEqual
135 let carat_equal = Term CaratEqual
136 let bar_equal = Term BarEqual
137 let bar_greater_than = Term BarGreaterThan
138 let minus_greater_than = Term MinusGreaterThan
139 let colon_colon = Term ColonColon
140 let star_star = Term StarStar
141 let question = Term Question
142 let question_question = Term QuestionQuestion
143 let question_minus_greater_than = Term QuestionMinusGreaterThan
144 let clone = Term Clone
145 let require = Term Require
146 let require_once = Term Require_once
147 let term_function = Term Function
148 let abstract = Term Abstract
149 let final = Term Final
150 let enum = Term Enum
151 let interface = Term Interface
152 let trait = Term Trait
153 let term_class = Term Class
154 let namespace = Term Namespace
155 let implements = Term Implements
156 let extends = Term Extends
157 let use = Term Use
158 let const = Term Const
159 let destruct = Term Destruct
160 let construct = Term Construct
161 let term_public = Term Public
162 let term_private = Term Private
163 let term_protected = Term Protected
164 let term_new = Term New
165 let instanceof = Term Instanceof
166 let async = Term Async
167 let case = Term Case
168 let default = Term Default
169 let colon = Term Colon
170 let comma = Term Comma
171 let left_paren = Term LeftParen
172 let right_paren = Term RightParen
173 let left_brace = Term LeftBrace
174 let right_brace = Term RightBrace
175 let left_bracket = Term LeftBracket
176 let right_bracket = Term RightBracket
177 let static = Term Static
178 let semicolon = Term Semicolon
179 let continue = Term Continue
180 let break = Term Break
181 let return = Term Return
182 let throw = Term Throw
183 let term_try = Term Try
184 let finally = Term Finally
185 let yield = Term Yield
186 let switch = Term Switch
187 let term_if = Term If
188 let term_else = Term Else
189 let elseif = Term Elseif
190 let term_do = Term Do
191 let term_while = Term While
192 let term_for = Term For
193 let foreach = Term Foreach
194 let await = Term Await
195 let term_as = Term As
196 let catch = Term Catch
197 let this = Term This
198 let self = Term Self
199 let parent = Term Parent
200 let term_type = Term Type
201 let newtype = Term Newtype
202 let void = Term Void
203 let term_bool = Term Bool
204 let term_int = Term Int
205 let term_float = Term Float
206 let term_string = Term String
207 let noreturn = Term Noreturn
208 let arraykey = Term Arraykey
209 let num = Term Num
210 let resource = Term Resource
211 let classname = Term Classname
212 let mixed = Term Mixed
213 let boolean_literal = Term BooleanLiteral
214 let floating_literal = Term FloatingLiteral
215 let null_literal = Term NullLiteral
216 let decimal_literal = Term DecimalLiteral
217 let octal_literal = Term OctalLiteral
218 let hexadecimal_literal = Term HexadecimalLiteral
219 let binary_literal = Term BinaryLiteral
220 let single_quoted_string_literal = Term SingleQuotedStringLiteral
221 let double_quoted_string_literal = Term DoubleQuotedStringLiteral
222 let heredoc_string_literal = Term HeredocStringLiteral
223 let nowdoc_string_literal = Term NowdocStringLiteral
224 let echo = Term Echo
225 (* TODO should be exit but doesnt exits, use echo for now *)
226 let term_exit = Term Echo
227 let tuple = Term Tuple
228 let shape = Term Shape
229 let xhp_element_name = Term XHPElementName
230 let xhp_string_literal = Term XHPStringLiteral
231 let xhp_body_text = Term XHPBody
232 let xhp_comment = Term XHPComment
233 let slash_greater_than = Term SlashGreaterThan
234 let less_than_slash = Term LessThanSlash
235 let inout = Term Inout
237 let rec qualified_name = NonTerm ("QualifiedName", fun () -> [
238 [name; backslash; name];
239 [qualified_name; backslash; name]])
241 (* For keywords, use TokenKind to_string. For names, use gen_name to generate
242 * name *)
243 let to_string = function
244 | Dollar -> "$" ^ (gen_name ())
245 | Name -> gen_name()
246 (* TODO more general approach *)
247 (* | QualifiedName -> (gen_name ()) ^ "/" ^ (gen_name ()) *)
248 | BooleanLiteral -> "true"
249 | FloatingLiteral -> "42.42"
250 | NullLiteral -> "null"
251 | HexadecimalLiteral -> "0x16"
252 | DecimalLiteral -> "12"
253 | OctalLiteral -> "0123"
254 | BinaryLiteral -> "0b101010"
255 (* TODO *)
256 (* | HeredocStringLiteral -> Printf.sprintf "<<<HSL\nsome string\nHSL;"
257 | NowdocStringLiteral -> Printf.sprintf "<<<'NSL'\nsome string\nNSL;" *)
258 | HeredocStringLiteral -> "\"heredoc\""
259 | NowdocStringLiteral -> "\"nowdoc\""
260 | DoubleQuotedStringLiteral -> "\"double string\""
261 | SingleQuotedStringLiteral -> "'single string'"
262 | XHPElementName -> "<" ^ (gen_name())
263 | XHPStringLiteral -> "\"xhp string literal\""
264 | XHPBody -> "just some body text" (*TODO better test coverage *)
265 | XHPComment -> "<!-- some comments -->"
266 | x -> TokenKind.to_string x