parser.ml 53 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625
  1. (*
  2. * Copyright (C)2005-2013 Haxe Foundation
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a
  5. * copy of this software and associated documentation files (the "Software"),
  6. * to deal in the Software without restriction, including without limitation
  7. * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  8. * and/or sell copies of the Software, and to permit persons to whom the
  9. * Software is furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
  19. * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  20. * DEALINGS IN THE SOFTWARE.
  21. *)
  22. open Ast
  23. type error_msg =
  24. | Unexpected of token
  25. | Duplicate_default
  26. | Missing_semicolon
  27. | Unclosed_macro
  28. | Unimplemented
  29. | Missing_type
  30. | Custom of string
  31. exception Error of error_msg * pos
  32. exception TypePath of string list * (string * bool) option * bool (* in import *)
  33. exception Display of expr
  34. let error_msg = function
  35. | Unexpected t -> "Unexpected "^(s_token t)
  36. | Duplicate_default -> "Duplicate default"
  37. | Missing_semicolon -> "Missing ;"
  38. | Unclosed_macro -> "Unclosed macro"
  39. | Unimplemented -> "Not implemented for current platform"
  40. | Missing_type -> "Missing type declaration"
  41. | Custom s -> s
  42. let error m p = raise (Error (m,p))
  43. let display_error : (error_msg -> pos -> unit) ref = ref (fun _ _ -> assert false)
  44. let quoted_ident_prefix = "@$__hx__"
  45. let quote_ident s =
  46. quoted_ident_prefix ^ s
  47. let unquote_ident f =
  48. let pf = quoted_ident_prefix in
  49. let pflen = String.length pf in
  50. let is_quoted = String.length f >= pflen && String.sub f 0 pflen = pf in
  51. let s = if is_quoted then String.sub f pflen (String.length f - pflen) else f in
  52. let is_valid = not is_quoted || try
  53. for i = 0 to String.length s - 1 do
  54. match String.unsafe_get s i with
  55. | 'a'..'z' | 'A'..'Z' | '_' -> ()
  56. | '0'..'9' when i > 0 -> ()
  57. | _ -> raise Exit
  58. done;
  59. if Hashtbl.mem Lexer.keywords s then raise Exit;
  60. true
  61. with Exit ->
  62. false
  63. in
  64. s,is_quoted,is_valid
  65. let cache = ref (DynArray.create())
  66. let last_doc = ref None
  67. let use_doc = ref false
  68. let use_parser_resume = ref true
  69. let resume_display = ref null_pos
  70. let in_macro = ref false
  71. let last_token s =
  72. let n = Stream.count s in
  73. DynArray.get (!cache) (if n = 0 then 0 else n - 1)
  74. let serror() = raise (Stream.Error "")
  75. let do_resume() = !resume_display <> null_pos
  76. let display e = raise (Display e)
  77. let type_path sl in_import = match sl with
  78. | n :: l when n.[0] >= 'A' && n.[0] <= 'Z' -> raise (TypePath (List.rev l,Some (n,false),in_import));
  79. | _ -> raise (TypePath (List.rev sl,None,in_import))
  80. let is_resuming p =
  81. let p2 = !resume_display in
  82. p.pmax = p2.pmin && !use_parser_resume && Common.unique_full_path p.pfile = p2.pfile
  83. let set_resume p =
  84. resume_display := { p with pfile = Common.unique_full_path p.pfile }
  85. let is_dollar_ident e = match fst e with
  86. | EConst (Ident n) when n.[0] = '$' ->
  87. true
  88. | _ ->
  89. false
  90. let precedence op =
  91. let left = true and right = false in
  92. match op with
  93. | OpMod -> 0, left
  94. | OpMult | OpDiv -> 1, left
  95. | OpAdd | OpSub -> 2, left
  96. | OpShl | OpShr | OpUShr -> 3, left
  97. | OpOr | OpAnd | OpXor -> 4, left
  98. | OpEq | OpNotEq | OpGt | OpLt | OpGte | OpLte -> 5, left
  99. | OpInterval -> 6, left
  100. | OpBoolAnd -> 7, left
  101. | OpBoolOr -> 8, left
  102. | OpArrow -> 9, right
  103. | OpAssign | OpAssignOp _ -> 10, right
  104. let is_not_assign = function
  105. | OpAssign | OpAssignOp _ -> false
  106. | _ -> true
  107. let swap op1 op2 =
  108. let p1, left1 = precedence op1 in
  109. let p2, _ = precedence op2 in
  110. left1 && p1 <= p2
  111. let rec make_binop op e ((v,p2) as e2) =
  112. match v with
  113. | EBinop (_op,_e,_e2) when swap op _op ->
  114. let _e = make_binop op e _e in
  115. EBinop (_op,_e,_e2) , punion (pos _e) (pos _e2)
  116. | ETernary (e1,e2,e3) when is_not_assign op ->
  117. let e = make_binop op e e1 in
  118. ETernary (e,e2,e3) , punion (pos e) (pos e3)
  119. | _ ->
  120. EBinop (op,e,e2) , punion (pos e) (pos e2)
  121. let rec make_unop op ((v,p2) as e) p1 =
  122. match v with
  123. | EBinop (bop,e,e2) -> EBinop (bop, make_unop op e p1 , e2) , (punion p1 p2)
  124. | ETernary (e1,e2,e3) -> ETernary (make_unop op e1 p1 , e2, e3), punion p1 p2
  125. | _ ->
  126. EUnop (op,Prefix,e), punion p1 p2
  127. let rec make_meta name params ((v,p2) as e) p1 =
  128. match v with
  129. | EBinop (bop,e,e2) -> EBinop (bop, make_meta name params e p1 , e2) , (punion p1 p2)
  130. | ETernary (e1,e2,e3) -> ETernary (make_meta name params e1 p1 , e2, e3), punion p1 p2
  131. | _ ->
  132. EMeta((name,params,p1),e),punion p1 p2
  133. let make_is e t p =
  134. let e_is = EField((EConst(Ident "Std"),p),"is"),p in
  135. let e2 = expr_of_type_path (t.tpackage,t.tname) p in
  136. ECall(e_is,[e;e2]),p
  137. let reify in_macro =
  138. let cur_pos = ref None in
  139. let mk_enum ename n vl p =
  140. let constr = (EConst (Ident n),p) in
  141. match vl with
  142. | [] -> constr
  143. | _ -> (ECall (constr,vl),p)
  144. in
  145. let to_const c p =
  146. let cst n v = mk_enum "Constant" n [EConst (String v),p] p in
  147. match c with
  148. | Int i -> cst "CInt" i
  149. | String s -> cst "CString" s
  150. | Float s -> cst "CFloat" s
  151. | Ident s -> cst "CIdent" s
  152. | Regexp (r,o) -> mk_enum "Constant" "CRegexp" [(EConst (String r),p);(EConst (String o),p)] p
  153. in
  154. let rec to_binop o p =
  155. let op n = mk_enum "Binop" n [] p in
  156. match o with
  157. | OpAdd -> op "OpAdd"
  158. | OpMult -> op "OpMult"
  159. | OpDiv -> op "OpDiv"
  160. | OpSub -> op "OpSub"
  161. | OpAssign -> op "OpAssign"
  162. | OpEq -> op "OpEq"
  163. | OpNotEq -> op "OpNotEq"
  164. | OpGt -> op "OpGt"
  165. | OpGte -> op "OpGte"
  166. | OpLt -> op "OpLt"
  167. | OpLte -> op "OpLte"
  168. | OpAnd -> op "OpAnd"
  169. | OpOr -> op "OpOr"
  170. | OpXor -> op "OpXor"
  171. | OpBoolAnd -> op "OpBoolAnd"
  172. | OpBoolOr -> op "OpBoolOr"
  173. | OpShl -> op "OpShl"
  174. | OpShr -> op "OpShr"
  175. | OpUShr -> op "OpUShr"
  176. | OpMod -> op "OpMod"
  177. | OpAssignOp o -> mk_enum "Binop" "OpAssignOp" [to_binop o p] p
  178. | OpInterval -> op "OpInterval"
  179. | OpArrow -> op "OpArrow"
  180. in
  181. let to_string s p =
  182. let len = String.length s in
  183. if len > 1 && s.[0] = '$' then
  184. (EConst (Ident (String.sub s 1 (len - 1))),p)
  185. else
  186. (EConst (String s),p)
  187. in
  188. let to_array f a p =
  189. (EArrayDecl (List.map (fun s -> f s p) a),p)
  190. in
  191. let to_null p =
  192. (EConst (Ident "null"),p)
  193. in
  194. let to_opt f v p =
  195. match v with
  196. | None -> to_null p
  197. | Some v -> f v p
  198. in
  199. let to_bool o p =
  200. (EConst (Ident (if o then "true" else "false")),p)
  201. in
  202. let to_obj fields p =
  203. (EObjectDecl fields,p)
  204. in
  205. let rec to_tparam t p =
  206. let n, v = (match t with
  207. | TPType t -> "TPType", to_ctype t p
  208. | TPExpr e -> "TPExpr", to_expr e p
  209. ) in
  210. mk_enum "TypeParam" n [v] p
  211. and to_tpath t p =
  212. let len = String.length t.tname in
  213. if t.tpackage = [] && len > 1 && t.tname.[0] = '$' then
  214. (EConst (Ident (String.sub t.tname 1 (len - 1))),p)
  215. else begin
  216. let fields = [
  217. ("pack", to_array to_string t.tpackage p);
  218. ("name", to_string t.tname p);
  219. ("params", to_array to_tparam t.tparams p);
  220. ] in
  221. to_obj (match t.tsub with None -> fields | Some s -> fields @ ["sub",to_string s p]) p
  222. end
  223. and to_ctype t p =
  224. let ct n vl = mk_enum "ComplexType" n vl p in
  225. match t with
  226. | CTPath { tpackage = []; tparams = []; tsub = None; tname = n } when n.[0] = '$' ->
  227. to_string n p
  228. | CTPath t -> ct "TPath" [to_tpath t p]
  229. | CTFunction (args,ret) -> ct "TFunction" [to_array to_ctype args p; to_ctype ret p]
  230. | CTAnonymous fields -> ct "TAnonymous" [to_array to_cfield fields p]
  231. | CTParent t -> ct "TParent" [to_ctype t p]
  232. | CTExtend (tl,fields) -> ct "TExtend" [to_array to_tpath tl p; to_array to_cfield fields p]
  233. | CTOptional t -> ct "TOptional" [to_ctype t p]
  234. and to_fun f p =
  235. let farg (n,o,t,e) p =
  236. let fields = [
  237. "name", to_string n p;
  238. "opt", to_bool o p;
  239. "type", to_opt to_ctype t p;
  240. ] in
  241. to_obj (match e with None -> fields | Some e -> fields @ ["value",to_expr e p]) p
  242. in
  243. let rec fparam t p =
  244. let fields = [
  245. "name", to_string t.tp_name p;
  246. "constraints", to_array to_ctype t.tp_constraints p;
  247. "params", to_array fparam t.tp_params p;
  248. ] in
  249. to_obj fields p
  250. in
  251. let fields = [
  252. ("args",to_array farg f.f_args p);
  253. ("ret",to_opt to_ctype f.f_type p);
  254. ("expr",to_opt to_expr f.f_expr p);
  255. ("params",to_array fparam f.f_params p);
  256. ] in
  257. to_obj fields p
  258. and to_cfield f p =
  259. let p = f.cff_pos in
  260. let to_access a p =
  261. let n = (match a with
  262. | APublic -> "APublic"
  263. | APrivate -> "APrivate"
  264. | AStatic -> "AStatic"
  265. | AOverride -> "AOverride"
  266. | ADynamic -> "ADynamic"
  267. | AInline -> "AInline"
  268. | AMacro -> "AMacro"
  269. ) in
  270. mk_enum "Access" n [] p
  271. in
  272. let to_kind k =
  273. let n, vl = (match k with
  274. | FVar (ct,e) -> "FVar", [to_opt to_ctype ct p;to_opt to_expr e p]
  275. | FFun f -> "FFun", [to_fun f p]
  276. | FProp (get,set,t,e) -> "FProp", [to_string get p; to_string set p; to_opt to_ctype t p; to_opt to_expr e p]
  277. ) in
  278. mk_enum "FieldType" n vl p
  279. in
  280. let fields = [
  281. Some ("name", to_string f.cff_name p);
  282. (match f.cff_doc with None -> None | Some s -> Some ("doc", to_string s p));
  283. (match f.cff_access with [] -> None | l -> Some ("access", to_array to_access l p));
  284. Some ("kind", to_kind f.cff_kind);
  285. Some ("pos", to_pos f.cff_pos);
  286. (match f.cff_meta with [] -> None | l -> Some ("meta", to_meta f.cff_meta p));
  287. ] in
  288. let fields = List.rev (List.fold_left (fun acc v -> match v with None -> acc | Some e -> e :: acc) [] fields) in
  289. to_obj fields p
  290. and to_meta m p =
  291. to_array (fun (m,el,p) _ ->
  292. let fields = [
  293. "name", to_string (fst (Common.MetaInfo.to_string m)) p;
  294. "params", to_expr_array el p;
  295. "pos", to_pos p;
  296. ] in
  297. to_obj fields p
  298. ) m p
  299. and to_pos p =
  300. match !cur_pos with
  301. | Some p ->
  302. p
  303. | None ->
  304. let file = (EConst (String p.pfile),p) in
  305. let pmin = (EConst (Int (string_of_int p.pmin)),p) in
  306. let pmax = (EConst (Int (string_of_int p.pmax)),p) in
  307. if in_macro then
  308. (EUntyped (ECall ((EConst (Ident "__dollar__mk_pos"),p),[file;pmin;pmax]),p),p)
  309. else
  310. to_obj [("file",file);("min",pmin);("max",pmax)] p
  311. and to_expr_array a p = match a with
  312. | [EMeta ((Meta.Dollar "a",[],_),e1),_] -> (match fst e1 with EArrayDecl el -> to_expr_array el p | _ -> e1)
  313. | _ -> to_array to_expr a p
  314. and to_expr e _ =
  315. let p = snd e in
  316. let expr n vl =
  317. let e = mk_enum "ExprDef" n vl p in
  318. to_obj [("expr",e);("pos",to_pos p)] p
  319. in
  320. let loop e = to_expr e (snd e) in
  321. match fst e with
  322. | EConst (Ident n) when n.[0] = '$' && String.length n > 1 ->
  323. to_string n p
  324. | EConst c ->
  325. expr "EConst" [to_const c p]
  326. | EArray (e1,e2) ->
  327. expr "EArray" [loop e1;loop e2]
  328. | EBinop (op,e1,e2) ->
  329. expr "EBinop" [to_binop op p; loop e1; loop e2]
  330. | EField (e,s) ->
  331. expr "EField" [loop e; to_string s p]
  332. | EParenthesis e ->
  333. expr "EParenthesis" [loop e]
  334. | EObjectDecl fl ->
  335. expr "EObjectDecl" [to_array (fun (f,e) -> to_obj [("field",to_string f p);("expr",loop e)]) fl p]
  336. | EArrayDecl el ->
  337. expr "EArrayDecl" [to_expr_array el p]
  338. | ECall (e,el) ->
  339. expr "ECall" [loop e;to_expr_array el p]
  340. | ENew (t,el) ->
  341. expr "ENew" [to_tpath t p;to_expr_array el p]
  342. | EUnop (op,flag,e) ->
  343. let op = mk_enum "Unop" (match op with
  344. | Increment -> "OpIncrement"
  345. | Decrement -> "OpDecrement"
  346. | Not -> "OpNot"
  347. | Neg -> "OpNeg"
  348. | NegBits -> "OpNegBits"
  349. ) [] p in
  350. expr "EUnop" [op;to_bool (flag = Postfix) p;loop e]
  351. | EVars vl ->
  352. expr "EVars" [to_array (fun (v,t,e) p ->
  353. let fields = [
  354. "name", to_string v p;
  355. "type", to_opt to_ctype t p;
  356. "expr", to_opt to_expr e p;
  357. ] in
  358. to_obj fields p
  359. ) vl p]
  360. | EFunction (name,f) ->
  361. let name = match name with
  362. | None ->
  363. to_null p
  364. | Some name ->
  365. if ExtString.String.starts_with name "inline_$" then begin
  366. let real_name = (String.sub name 7 (String.length name - 7)) in
  367. let e_name = to_string real_name p in
  368. let e_inline = to_string "inline_" p in
  369. let e_add = (EBinop(OpAdd,e_inline,e_name),p) in
  370. e_add
  371. end else
  372. to_string name p
  373. in
  374. expr "EFunction" [name; to_fun f p]
  375. | EBlock el ->
  376. expr "EBlock" [to_expr_array el p]
  377. | EFor (e1,e2) ->
  378. expr "EFor" [loop e1;loop e2]
  379. | EIn (e1,e2) ->
  380. expr "EIn" [loop e1;loop e2]
  381. | EIf (e1,e2,eelse) ->
  382. expr "EIf" [loop e1;loop e2;to_opt to_expr eelse p]
  383. | EWhile (e1,e2,flag) ->
  384. expr "EWhile" [loop e1;loop e2;to_bool (flag = NormalWhile) p]
  385. | ESwitch (e1,cases,def) ->
  386. let scase (el,eg,e) p =
  387. to_obj [("values",to_expr_array el p);"guard",to_opt to_expr eg p;"expr",to_opt to_expr e p] p
  388. in
  389. expr "ESwitch" [loop e1;to_array scase cases p;to_opt (to_opt to_expr) def p]
  390. | ETry (e1,catches) ->
  391. let scatch (n,t,e) p =
  392. to_obj [("name",to_string n p);("type",to_ctype t p);("expr",loop e)] p
  393. in
  394. expr "ETry" [loop e1;to_array scatch catches p]
  395. | EReturn eo ->
  396. expr "EReturn" [to_opt to_expr eo p]
  397. | EBreak ->
  398. expr "EBreak" []
  399. | EContinue ->
  400. expr "EContinue" []
  401. | EUntyped e ->
  402. expr "EUntyped" [loop e]
  403. | EThrow e ->
  404. expr "EThrow" [loop e]
  405. | ECast (e,ct) ->
  406. expr "ECast" [loop e; to_opt to_ctype ct p]
  407. | EDisplay (e,flag) ->
  408. expr "EDisplay" [loop e; to_bool flag p]
  409. | EDisplayNew t ->
  410. expr "EDisplayNew" [to_tpath t p]
  411. | ETernary (e1,e2,e3) ->
  412. expr "ETernary" [loop e1;loop e2;loop e3]
  413. | ECheckType (e1,ct) ->
  414. expr "ECheckType" [loop e1; to_ctype ct p]
  415. | EMeta ((m,ml,p),e1) ->
  416. match m, ml with
  417. | Meta.Dollar ("" | "e"), _ ->
  418. e1
  419. | Meta.Dollar "a", _ ->
  420. expr "EArrayDecl" (match fst e1 with EArrayDecl el -> [to_expr_array el p] | _ -> [e1])
  421. | Meta.Dollar "b", _ ->
  422. expr "EBlock" [e1]
  423. (* TODO: can $v and $i be implemented better? *)
  424. | Meta.Dollar "v", _ ->
  425. begin match fst e1 with
  426. | EParenthesis (ECheckType (e2, CTPath{tname="String";tpackage=[]}),_) -> expr "EConst" [mk_enum "Constant" "CString" [e2] (pos e2)]
  427. | EParenthesis (ECheckType (e2, CTPath{tname="Int";tpackage=[]}),_) -> expr "EConst" [mk_enum "Constant" "CInt" [e2] (pos e2)]
  428. | EParenthesis (ECheckType (e2, CTPath{tname="Float";tpackage=[]}),_) -> expr "EConst" [mk_enum "Constant" "CFloat" [e2] (pos e2)]
  429. | _ -> (ECall ((EField ((EField ((EField ((EConst (Ident "haxe"),p),"macro"),p),"Context"),p),"makeExpr"),p),[e; to_pos (pos e)]),p)
  430. end
  431. | Meta.Dollar "i", _ ->
  432. expr "EConst" [mk_enum "Constant" "CIdent" [e1] (pos e1)]
  433. | Meta.Dollar "p", _ ->
  434. (ECall ((EField ((EField ((EField ((EConst (Ident "haxe"),p),"macro"),p),"MacroStringTools"),p),"toFieldExpr"),p),[e]),p)
  435. | Meta.Custom ":pos", [pexpr] ->
  436. let old = !cur_pos in
  437. cur_pos := Some pexpr;
  438. let e = loop e1 in
  439. cur_pos := old;
  440. e
  441. | _ ->
  442. expr "EMeta" [to_obj [("name",to_string (fst (Common.MetaInfo.to_string m)) p);("params",to_expr_array ml p);("pos",to_pos p)] p;loop e1]
  443. and to_tparam_decl p t =
  444. to_obj [
  445. "name", to_string t.tp_name p;
  446. "params", (EArrayDecl (List.map (to_tparam_decl p) t.tp_params),p);
  447. "constraints", (EArrayDecl (List.map (fun t -> to_ctype t p) t.tp_constraints),p)
  448. ] p
  449. and to_type_def (t,p) =
  450. match t with
  451. | EClass d ->
  452. let ext = ref None and impl = ref [] and interf = ref false in
  453. List.iter (function
  454. | HExtern | HPrivate -> ()
  455. | HInterface -> interf := true;
  456. | HExtends t -> ext := Some (to_tpath t p)
  457. | HImplements i -> impl := (to_tpath i p) :: !impl
  458. ) d.d_flags;
  459. to_obj [
  460. "pack", (EArrayDecl [],p);
  461. "name", to_string d.d_name p;
  462. "pos", to_pos p;
  463. "meta", to_meta d.d_meta p;
  464. "params", (EArrayDecl (List.map (to_tparam_decl p) d.d_params),p);
  465. "isExtern", to_bool (List.mem HExtern d.d_flags) p;
  466. "kind", mk_enum "TypeDefKind" "TDClass" [(match !ext with None -> (EConst (Ident "null"),p) | Some t -> t);(EArrayDecl (List.rev !impl),p);to_bool !interf p] p;
  467. "fields", (EArrayDecl (List.map (fun f -> to_cfield f p) d.d_data),p)
  468. ] p
  469. | _ -> assert false
  470. in
  471. (fun e -> to_expr e (snd e)), to_ctype, to_type_def
  472. let popt f = parser
  473. | [< v = f >] -> Some v
  474. | [< >] -> None
  475. let rec plist f = parser
  476. | [< v = f; l = plist f >] -> v :: l
  477. | [< >] -> []
  478. let rec psep sep f = parser
  479. | [< v = f; s >] ->
  480. let rec loop = parser
  481. | [< '(sep2,_) when sep2 = sep; v = f; l = loop >] -> v :: l
  482. | [< >] -> []
  483. in
  484. v :: loop s
  485. | [< >] -> []
  486. let ident = parser
  487. | [< '(Const (Ident i),p) >] -> i,p
  488. let dollar_ident = parser
  489. | [< '(Const (Ident i),p) >] -> i,p
  490. | [< '(Dollar i,p) >] -> ("$" ^ i),p
  491. let dollar_ident_macro pack = parser
  492. | [< '(Const (Ident i),p) >] -> i,p
  493. | [< '(Dollar i,p) >] -> ("$" ^ i),p
  494. | [< '(Kwd Macro,p) when pack <> [] >] -> "macro", p
  495. | [< '(Kwd Extern,p) when pack <> [] >] -> "extern", p
  496. let lower_ident_or_macro = parser
  497. | [< '(Const (Ident i),p) when is_lower_ident i >] -> i
  498. | [< '(Kwd Macro,_) >] -> "macro"
  499. | [< '(Kwd Extern,_) >] -> "extern"
  500. let property_ident = parser
  501. | [< i, _ = ident >] -> i
  502. | [< '(Kwd Dynamic,_) >] -> "dynamic"
  503. | [< '(Kwd Default,_) >] -> "default"
  504. | [< '(Kwd Null,_) >] -> "null"
  505. let get_doc s =
  506. (* do the peek first to make sure we fetch the doc *)
  507. match Stream.peek s with
  508. | None -> None
  509. | Some (tk,p) ->
  510. match !last_doc with
  511. | None -> None
  512. | Some (d,pos) ->
  513. last_doc := None;
  514. if pos = p.pmin then Some d else None
  515. let comma = parser
  516. | [< '(Comma,_) >] -> ()
  517. let semicolon s =
  518. if fst (last_token s) = BrClose then
  519. match s with parser
  520. | [< '(Semicolon,p) >] -> p
  521. | [< >] -> snd (last_token s)
  522. else
  523. match s with parser
  524. | [< '(Semicolon,p) >] -> p
  525. | [< s >] ->
  526. let pos = snd (last_token s) in
  527. if do_resume() then pos else error Missing_semicolon pos
  528. let rec parse_file s =
  529. last_doc := None;
  530. match s with parser
  531. | [< '(Kwd Package,_); pack = parse_package; s >] ->
  532. begin match s with parser
  533. | [< '(Const(Ident _),p) when pack = [] >] -> error (Custom "Package name must start with a lowercase character") p
  534. | [< _ = semicolon; l = parse_type_decls pack []; '(Eof,_) >] -> pack , l
  535. end
  536. | [< l = parse_type_decls [] []; '(Eof,_) >] -> [] , l
  537. and parse_type_decls pack acc s =
  538. try
  539. match s with parser
  540. | [< v = parse_type_decl; l = parse_type_decls pack (v :: acc) >] -> l
  541. | [< >] -> List.rev acc
  542. with TypePath ([],Some (name,false),b) ->
  543. (* resolve imports *)
  544. List.iter (fun d ->
  545. match fst d with
  546. | EImport (t,_) ->
  547. (match List.rev t with
  548. | (n,_) :: path when n = name && List.for_all (fun (i,_) -> is_lower_ident i) path -> raise (TypePath (List.map fst (List.rev path),Some (name,false),b))
  549. | _ -> ())
  550. | _ -> ()
  551. ) acc;
  552. raise (TypePath (pack,Some(name,true),b))
  553. and parse_type_decl s =
  554. match s with parser
  555. | [< '(Kwd Import,p1) >] -> parse_import s p1
  556. | [< '(Kwd Using,p1); t = parse_type_path; p2 = semicolon >] -> EUsing t, punion p1 p2
  557. | [< doc = get_doc; meta = parse_meta; c = parse_common_flags; s >] ->
  558. match s with parser
  559. | [< n , p1 = parse_enum_flags; name = type_name; tl = parse_constraint_params; '(BrOpen,_); l = plist parse_enum; '(BrClose,p2) >] ->
  560. (EEnum {
  561. d_name = name;
  562. d_doc = doc;
  563. d_meta = meta;
  564. d_params = tl;
  565. d_flags = List.map snd c @ n;
  566. d_data = l
  567. }, punion p1 p2)
  568. | [< n , p1 = parse_class_flags; name = type_name; tl = parse_constraint_params; hl = plist parse_class_herit; '(BrOpen,_); fl, p2 = parse_class_fields false p1 >] ->
  569. (EClass {
  570. d_name = name;
  571. d_doc = doc;
  572. d_meta = meta;
  573. d_params = tl;
  574. d_flags = List.map fst c @ n @ hl;
  575. d_data = fl;
  576. }, punion p1 p2)
  577. | [< '(Kwd Typedef,p1); name = type_name; tl = parse_constraint_params; '(Binop OpAssign,p2); t = parse_complex_type; s >] ->
  578. (match s with parser
  579. | [< '(Semicolon,_) >] -> ()
  580. | [< >] -> ());
  581. (ETypedef {
  582. d_name = name;
  583. d_doc = doc;
  584. d_meta = meta;
  585. d_params = tl;
  586. d_flags = List.map snd c;
  587. d_data = t;
  588. }, punion p1 p2)
  589. | [< '(Kwd Abstract,p1); name = type_name; tl = parse_constraint_params; st = parse_abstract_subtype; sl = plist parse_abstract_relations; '(BrOpen,_); fl, p2 = parse_class_fields false p1 >] ->
  590. let flags = List.map (fun (_,c) -> match c with EPrivate -> APrivAbstract | EExtern -> error (Custom "extern abstract not allowed") p1) c in
  591. let flags = (match st with None -> flags | Some t -> AIsType t :: flags) in
  592. (EAbstract {
  593. d_name = name;
  594. d_doc = doc;
  595. d_meta = meta;
  596. d_params = tl;
  597. d_flags = flags @ sl;
  598. d_data = fl;
  599. },punion p1 p2)
  600. and parse_class doc meta cflags need_name s =
  601. let opt_name = if need_name then type_name else (fun s -> match popt type_name s with None -> "" | Some n -> n) in
  602. match s with parser
  603. | [< n , p1 = parse_class_flags; name = opt_name; tl = parse_constraint_params; hl = psep Comma parse_class_herit; '(BrOpen,_); fl, p2 = parse_class_fields (not need_name) p1 >] ->
  604. (EClass {
  605. d_name = name;
  606. d_doc = doc;
  607. d_meta = meta;
  608. d_params = tl;
  609. d_flags = List.map fst cflags @ n @ hl;
  610. d_data = fl;
  611. }, punion p1 p2)
  612. and parse_import s p1 =
  613. let rec loop acc =
  614. match s with parser
  615. | [< '(Dot,p) >] ->
  616. let resume() =
  617. type_path (List.map fst acc) true
  618. in
  619. if is_resuming p then resume();
  620. (match s with parser
  621. | [< '(Const (Ident k),p) >] ->
  622. loop ((k,p) :: acc)
  623. | [< '(Kwd Macro,p) >] ->
  624. loop (("macro",p) :: acc)
  625. | [< '(Kwd Extern,p) >] ->
  626. loop (("extern",p) :: acc)
  627. | [< '(Binop OpMult,_); '(Semicolon,p2) >] ->
  628. p2, List.rev acc, IAll
  629. | [< '(Binop OpOr,_) when do_resume() >] ->
  630. set_resume p;
  631. resume()
  632. | [< >] ->
  633. serror());
  634. | [< '(Semicolon,p2) >] ->
  635. p2, List.rev acc, INormal
  636. | [< '(Kwd In,_); '(Const (Ident name),_); '(Semicolon,p2) >] ->
  637. p2, List.rev acc, IAsName name
  638. | [< '(Const (Ident "as"),_); '(Const (Ident name),_); '(Semicolon,p2) >] ->
  639. p2, List.rev acc, IAsName name
  640. | [< >] ->
  641. serror()
  642. in
  643. let p2, path, mode = (match s with parser
  644. | [< '(Const (Ident name),p) >] -> loop [name,p]
  645. | [< >] -> serror()
  646. ) in
  647. (EImport (path,mode),punion p1 p2)
  648. and parse_abstract_relations s =
  649. match s with parser
  650. | [< '(Const (Ident "to"),_); t = parse_complex_type >] -> AToType t
  651. | [< '(Const (Ident "from"),_); t = parse_complex_type >] -> AFromType t
  652. and parse_abstract_subtype s =
  653. match s with parser
  654. | [< '(POpen, _); t = parse_complex_type; '(PClose,_) >] -> Some t
  655. | [< >] -> None
  656. and parse_package s = psep Dot lower_ident_or_macro s
  657. and parse_class_fields tdecl p1 s =
  658. let l = parse_class_field_resume tdecl s in
  659. let p2 = (match s with parser
  660. | [< '(BrClose,p2) >] -> p2
  661. | [< >] -> if do_resume() then p1 else serror()
  662. ) in
  663. l, p2
  664. and parse_class_field_resume tdecl s =
  665. if not (do_resume()) then
  666. plist parse_class_field s
  667. else try
  668. let c = parse_class_field s in
  669. c :: parse_class_field_resume tdecl s
  670. with Stream.Error _ | Stream.Failure ->
  671. (* look for next variable/function or next type declaration *)
  672. let rec junk k =
  673. if k <= 0 then () else begin
  674. Stream.junk s;
  675. junk (k - 1);
  676. end
  677. in
  678. (*
  679. walk back tokens which are prefixing a type/field declaration
  680. *)
  681. let rec junk_tokens k =
  682. if k = 0 then
  683. ()
  684. else match List.rev_map fst (Stream.npeek k s) with
  685. | Kwd Private :: _ -> junk_tokens (k - 1)
  686. | (Const (Ident _) | Kwd _) :: DblDot :: At :: l
  687. | (Const (Ident _) | Kwd _) :: At :: l ->
  688. junk_tokens (List.length l)
  689. | PClose :: l ->
  690. (* count matching parenthesises for metadata call *)
  691. let rec loop n = function
  692. | [] -> []
  693. | POpen :: l -> if n = 0 then l else loop (n - 1) l
  694. | PClose :: l -> loop (n + 1) l
  695. | _ :: l -> loop n l
  696. in
  697. (match loop 0 l with
  698. | (Const (Ident _) | Kwd _) :: At :: l
  699. | (Const (Ident _) | Kwd _) :: DblDot :: At :: l -> junk_tokens (List.length l)
  700. | _ ->
  701. junk k)
  702. | _ ->
  703. junk k
  704. in
  705. let rec loop k =
  706. match List.rev_map fst (Stream.npeek k s) with
  707. (* metadata *)
  708. | Kwd _ :: At :: _ | Kwd _ :: DblDot :: At :: _ ->
  709. loop (k + 1)
  710. (* field declaration *)
  711. | Const _ :: Kwd Function :: _
  712. | Kwd New :: Kwd Function :: _ ->
  713. junk_tokens (k - 2);
  714. parse_class_field_resume tdecl s
  715. | Kwd Macro :: _ | Kwd Public :: _ | Kwd Static :: _ | Kwd Var :: _ | Kwd Override :: _ | Kwd Dynamic :: _ | Kwd Inline :: _ ->
  716. junk_tokens (k - 1);
  717. parse_class_field_resume tdecl s
  718. | BrClose :: _ when tdecl ->
  719. junk_tokens (k - 1);
  720. []
  721. (* type declaration *)
  722. | Eof :: _ | Kwd Import :: _ | Kwd Using :: _ | Kwd Extern :: _ | Kwd Class :: _ | Kwd Interface :: _ | Kwd Enum :: _ | Kwd Typedef :: _ | Kwd Abstract :: _->
  723. junk_tokens (k - 1);
  724. []
  725. | [] ->
  726. []
  727. | _ ->
  728. loop (k + 1)
  729. in
  730. loop 1
  731. and parse_common_flags = parser
  732. | [< '(Kwd Private,_); l = parse_common_flags >] -> (HPrivate, EPrivate) :: l
  733. | [< '(Kwd Extern,_); l = parse_common_flags >] -> (HExtern, EExtern) :: l
  734. | [< >] -> []
  735. and parse_meta_argument_expr s =
  736. try
  737. expr s
  738. with Display e -> match fst e with
  739. | EDisplay(e,_) ->
  740. begin try
  741. type_path (string_list_of_expr_path_raise e) false
  742. with Exit ->
  743. e
  744. end
  745. | _ ->
  746. e
  747. and parse_meta_params pname s = match s with parser
  748. | [< '(POpen,p) when p.pmin = pname.pmax; params = psep Comma parse_meta_argument_expr; '(PClose,_); >] -> params
  749. | [< >] -> []
  750. and parse_meta_entry = parser
  751. [< '(At,_); name,p = meta_name; params = parse_meta_params p; s >] -> (name,params,p)
  752. and parse_meta = parser
  753. | [< entry = parse_meta_entry; s >] ->
  754. entry :: parse_meta s
  755. | [< >] -> []
  756. and meta_name = parser
  757. | [< '(Const (Ident i),p) >] -> (Meta.Custom i), p
  758. | [< '(Kwd k,p) >] -> (Meta.Custom (s_keyword k)),p
  759. | [< '(DblDot,_); s >] -> match s with parser
  760. | [< '(Const (Ident i),p) >] -> (Common.MetaInfo.parse i), p
  761. | [< '(Kwd k,p) >] -> (Common.MetaInfo.parse (s_keyword k)),p
  762. and parse_enum_flags = parser
  763. | [< '(Kwd Enum,p) >] -> [] , p
  764. and parse_class_flags = parser
  765. | [< '(Kwd Class,p) >] -> [] , p
  766. | [< '(Kwd Interface,p) >] -> [HInterface] , p
  767. and parse_type_hint = parser
  768. | [< '(DblDot,_); t = parse_complex_type >] -> t
  769. and parse_type_opt = parser
  770. | [< t = parse_type_hint >] -> Some t
  771. | [< >] -> None
  772. and parse_complex_type s =
  773. let t = parse_complex_type_inner s in
  774. parse_complex_type_next t s
  775. and parse_structural_extension = parser
  776. | [< '(Binop OpGt,_); t = parse_type_path; '(Comma,_); s >] ->
  777. t
  778. and parse_complex_type_inner = parser
  779. | [< '(POpen,_); t = parse_complex_type; '(PClose,_) >] -> CTParent t
  780. | [< '(BrOpen,p1); s >] ->
  781. (match s with parser
  782. | [< l = parse_type_anonymous false >] -> CTAnonymous l
  783. | [< t = parse_structural_extension; s>] ->
  784. let tl = t :: plist parse_structural_extension s in
  785. (match s with parser
  786. | [< l = parse_type_anonymous false >] -> CTExtend (tl,l)
  787. | [< l, _ = parse_class_fields true p1 >] -> CTExtend (tl,l))
  788. | [< l, _ = parse_class_fields true p1 >] -> CTAnonymous l
  789. | [< >] -> serror())
  790. | [< '(Question,_); t = parse_complex_type_inner >] ->
  791. CTOptional t
  792. | [< t = parse_type_path >] ->
  793. CTPath t
  794. and parse_type_path s = parse_type_path1 [] s
  795. and parse_type_path1 pack = parser
  796. | [< name, p = dollar_ident_macro pack; s >] ->
  797. if is_lower_ident name then
  798. (match s with parser
  799. | [< '(Dot,p) >] ->
  800. if is_resuming p then
  801. raise (TypePath (List.rev (name :: pack),None,false))
  802. else
  803. parse_type_path1 (name :: pack) s
  804. | [< '(Semicolon,_) >] ->
  805. error (Custom "Type name should start with an uppercase letter") p
  806. | [< >] -> serror())
  807. else
  808. let sub = (match s with parser
  809. | [< '(Dot,p); s >] ->
  810. (if is_resuming p then
  811. raise (TypePath (List.rev pack,Some (name,false),false))
  812. else match s with parser
  813. | [< '(Const (Ident name),_) when not (is_lower_ident name) >] -> Some name
  814. | [< '(Binop OpOr,_) when do_resume() >] ->
  815. set_resume p;
  816. raise (TypePath (List.rev pack,Some (name,false),false))
  817. | [< >] -> serror())
  818. | [< >] -> None
  819. ) in
  820. let params = (match s with parser
  821. | [< '(Binop OpLt,_); l = psep Comma parse_type_path_or_const; '(Binop OpGt,_) >] -> l
  822. | [< >] -> []
  823. ) in
  824. {
  825. tpackage = List.rev pack;
  826. tname = name;
  827. tparams = params;
  828. tsub = sub;
  829. }
  830. | [< '(Binop OpOr,_) when do_resume() >] ->
  831. raise (TypePath (List.rev pack,None,false))
  832. and type_name = parser
  833. | [< '(Const (Ident name),p) >] ->
  834. if is_lower_ident name then
  835. error (Custom "Type name should start with an uppercase letter") p
  836. else
  837. name
  838. | [< '(Dollar name,_) >] -> "$" ^ name
  839. and parse_type_path_or_const = parser
  840. (* we can't allow (expr) here *)
  841. | [< '(BkOpen,p1); l = parse_array_decl; '(BkClose,p2); s >] -> TPExpr (EArrayDecl l, punion p1 p2)
  842. | [< t = parse_complex_type >] -> TPType t
  843. | [< '(Const c,p) >] -> TPExpr (EConst c,p)
  844. | [< e = expr >] -> TPExpr e
  845. | [< >] -> serror()
  846. and parse_complex_type_next t = parser
  847. | [< '(Arrow,_); t2 = parse_complex_type >] ->
  848. (match t2 with
  849. | CTFunction (args,r) ->
  850. CTFunction (t :: args,r)
  851. | _ ->
  852. CTFunction ([t] , t2))
  853. | [< >] -> t
  854. and parse_type_anonymous opt = parser
  855. | [< '(Question,_) when not opt; s >] -> parse_type_anonymous true s
  856. | [< name, p1 = ident; t = parse_type_hint; s >] ->
  857. let next p2 acc =
  858. {
  859. cff_name = name;
  860. cff_meta = if opt then [Meta.Optional,[],p1] else [];
  861. cff_access = [];
  862. cff_doc = None;
  863. cff_kind = FVar (Some t,None);
  864. cff_pos = punion p1 p2;
  865. } :: acc
  866. in
  867. match s with parser
  868. | [< '(BrClose,p2) >] -> next p2 []
  869. | [< '(Comma,p2) >] ->
  870. (match s with parser
  871. | [< '(BrClose,_) >] -> next p2 []
  872. | [< l = parse_type_anonymous false >] -> next p2 l
  873. | [< >] -> serror());
  874. | [< >] -> serror()
  875. and parse_enum s =
  876. let doc = get_doc s in
  877. let meta = parse_meta s in
  878. match s with parser
  879. | [< name, p1 = ident; params = parse_constraint_params; s >] ->
  880. let args = (match s with parser
  881. | [< '(POpen,_); l = psep Comma parse_enum_param; '(PClose,_) >] -> l
  882. | [< >] -> []
  883. ) in
  884. let t = parse_type_opt s in
  885. let p2 = (match s with parser
  886. | [< p = semicolon >] -> p
  887. | [< >] -> serror()
  888. ) in
  889. {
  890. ec_name = name;
  891. ec_doc = doc;
  892. ec_meta = meta;
  893. ec_args = args;
  894. ec_params = params;
  895. ec_type = t;
  896. ec_pos = punion p1 p2;
  897. }
  898. and parse_enum_param = parser
  899. | [< '(Question,_); name, _ = ident; t = parse_type_hint >] -> (name,true,t)
  900. | [< name, _ = ident; t = parse_type_hint >] -> (name,false,t)
  901. and parse_class_field s =
  902. let doc = get_doc s in
  903. match s with parser
  904. | [< meta = parse_meta; al = parse_cf_rights true []; s >] ->
  905. let name, pos, k = (match s with parser
  906. | [< '(Kwd Var,p1); name, _ = dollar_ident; s >] ->
  907. (match s with parser
  908. | [< '(POpen,_); i1 = property_ident; '(Comma,_); i2 = property_ident; '(PClose,_) >] ->
  909. let t = parse_type_opt s in
  910. let e , p2 = (match s with parser
  911. | [< '(Binop OpAssign,_); e = toplevel_expr; p2 = semicolon >] -> Some e , p2
  912. | [< '(Semicolon,p2) >] -> None , p2
  913. | [< >] -> serror()
  914. ) in
  915. name, punion p1 p2, FProp (i1,i2,t, e)
  916. | [< t = parse_type_opt; s >] ->
  917. let e , p2 = (match s with parser
  918. | [< '(Binop OpAssign,_); e = toplevel_expr; p2 = semicolon >] -> Some e , p2
  919. | [< '(Semicolon,p2) >] -> None , p2
  920. | [< >] -> serror()
  921. ) in
  922. name, punion p1 p2, FVar (t,e))
  923. | [< '(Kwd Function,p1); name = parse_fun_name; pl = parse_constraint_params; '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = parse_type_opt; s >] ->
  924. let e, p2 = (match s with parser
  925. | [< e = toplevel_expr; s >] ->
  926. (try ignore(semicolon s) with Error (Missing_semicolon,p) -> !display_error Missing_semicolon p);
  927. Some e, pos e
  928. | [< '(Semicolon,p) >] -> None, p
  929. | [< >] -> serror()
  930. ) in
  931. let f = {
  932. f_params = pl;
  933. f_args = al;
  934. f_type = t;
  935. f_expr = e;
  936. } in
  937. name, punion p1 p2, FFun f
  938. | [< >] ->
  939. if al = [] then raise Stream.Failure else serror()
  940. ) in
  941. {
  942. cff_name = name;
  943. cff_doc = doc;
  944. cff_meta = meta;
  945. cff_access = al;
  946. cff_pos = pos;
  947. cff_kind = k;
  948. }
  949. and parse_cf_rights allow_static l = parser
  950. | [< '(Kwd Static,_) when allow_static; l = parse_cf_rights false (AStatic :: l) >] -> l
  951. | [< '(Kwd Macro,_) when not(List.mem AMacro l); l = parse_cf_rights allow_static (AMacro :: l) >] -> l
  952. | [< '(Kwd Public,_) when not(List.mem APublic l || List.mem APrivate l); l = parse_cf_rights allow_static (APublic :: l) >] -> l
  953. | [< '(Kwd Private,_) when not(List.mem APublic l || List.mem APrivate l); l = parse_cf_rights allow_static (APrivate :: l) >] -> l
  954. | [< '(Kwd Override,_) when not (List.mem AOverride l); l = parse_cf_rights false (AOverride :: l) >] -> l
  955. | [< '(Kwd Dynamic,_) when not (List.mem ADynamic l); l = parse_cf_rights allow_static (ADynamic :: l) >] -> l
  956. | [< '(Kwd Inline,_); l = parse_cf_rights allow_static (AInline :: l) >] -> l
  957. | [< >] -> l
  958. and parse_fun_name = parser
  959. | [< name,_ = dollar_ident >] -> name
  960. | [< '(Kwd New,_) >] -> "new"
  961. and parse_fun_param = parser
  962. | [< '(Question,_); name, _ = dollar_ident; t = parse_type_opt; c = parse_fun_param_value >] -> (name,true,t,c)
  963. | [< name, _ = dollar_ident; t = parse_type_opt; c = parse_fun_param_value >] -> (name,false,t,c)
  964. and parse_fun_param_value = parser
  965. | [< '(Binop OpAssign,_); e = toplevel_expr >] -> Some e
  966. | [< >] -> None
  967. and parse_fun_param_type = parser
  968. | [< '(Question,_); name = ident; t = parse_type_hint >] -> (name,true,t)
  969. | [< name = ident; t = parse_type_hint >] -> (name,false,t)
  970. and parse_constraint_params = parser
  971. | [< '(Binop OpLt,_); l = psep Comma parse_constraint_param; '(Binop OpGt,_) >] -> l
  972. | [< >] -> []
  973. and parse_constraint_param = parser
  974. | [< meta = parse_meta; name = type_name; s >] ->
  975. let params = (match s with parser
  976. | [< >] -> []
  977. ) in
  978. let ctl = (match s with parser
  979. | [< '(DblDot,_); s >] ->
  980. (match s with parser
  981. | [< '(POpen,_); l = psep Comma parse_complex_type; '(PClose,_) >] -> l
  982. | [< t = parse_complex_type >] -> [t]
  983. | [< >] -> serror())
  984. | [< >] -> []
  985. ) in
  986. {
  987. tp_name = name;
  988. tp_params = params;
  989. tp_constraints = ctl;
  990. tp_meta = meta;
  991. }
  992. and parse_class_herit = parser
  993. | [< '(Kwd Extends,_); t = parse_type_path >] -> HExtends t
  994. | [< '(Kwd Implements,_); t = parse_type_path >] -> HImplements t
  995. and block1 = parser
  996. | [< name,p = dollar_ident; s >] -> block2 name (Ident name) p s
  997. | [< '(Const (String name),p); s >] -> block2 (quote_ident name) (String name) p s
  998. | [< b = block [] >] -> EBlock b
  999. and block2 name ident p s =
  1000. match s with parser
  1001. | [< '(DblDot,_); e = expr; l = parse_obj_decl >] -> EObjectDecl ((name,e) :: l)
  1002. | [< >] ->
  1003. let e = expr_next (EConst ident,p) s in
  1004. try
  1005. let _ = semicolon s in
  1006. let b = block [e] s in
  1007. EBlock b
  1008. with
  1009. | Error (err,p) ->
  1010. (!display_error) err p;
  1011. EBlock (block [e] s)
  1012. and block acc s =
  1013. try
  1014. (* because of inner recursion, we can't put Display handling in errors below *)
  1015. let e = try parse_block_elt s with Display e -> display (EBlock (List.rev (e :: acc)),snd e) in
  1016. block (e :: acc) s
  1017. with
  1018. | Stream.Failure ->
  1019. List.rev acc
  1020. | Stream.Error _ ->
  1021. let tk , pos = (match Stream.peek s with None -> last_token s | Some t -> t) in
  1022. (!display_error) (Unexpected tk) pos;
  1023. block acc s
  1024. | Error (e,p) ->
  1025. (!display_error) e p;
  1026. block acc s
  1027. and parse_block_elt = parser
  1028. | [< '(Kwd Var,p1); vl = parse_var_decls p1; p2 = semicolon >] ->
  1029. (EVars vl,punion p1 p2)
  1030. | [< '(Kwd Inline,p1); '(Kwd Function,_); e = parse_function p1 true; _ = semicolon >] -> e
  1031. | [< e = expr; _ = semicolon >] -> e
  1032. and parse_obj_decl = parser
  1033. | [< '(Comma,_); s >] ->
  1034. (match s with parser
  1035. | [< name, _ = ident; '(DblDot,_); e = expr; l = parse_obj_decl >] -> (name,e) :: l
  1036. | [< '(Const (String name),_); '(DblDot,_); e = expr; l = parse_obj_decl >] -> (quote_ident name,e) :: l
  1037. | [< >] -> [])
  1038. | [< >] -> []
  1039. and parse_array_decl = parser
  1040. | [< e = expr; s >] ->
  1041. (match s with parser
  1042. | [< '(Comma,_); l = parse_array_decl >] -> e :: l
  1043. | [< >] -> [e])
  1044. | [< >] ->
  1045. []
  1046. and parse_var_decl_head = parser
  1047. | [< name, _ = dollar_ident; t = parse_type_opt >] -> (name,t)
  1048. and parse_var_assignment = parser
  1049. | [< '(Binop OpAssign,p1); s >] ->
  1050. begin match s with parser
  1051. | [< e = expr >] -> Some e
  1052. | [< >] -> error (Custom "expression expected after =") p1
  1053. end
  1054. | [< >] -> None
  1055. and parse_var_decls_next vl = parser
  1056. | [< '(Comma,p1); name,t = parse_var_decl_head; s >] ->
  1057. begin try
  1058. let eo = parse_var_assignment s in
  1059. parse_var_decls_next ((name,t,eo) :: vl) s
  1060. with Display e ->
  1061. let v = (name,t,Some e) in
  1062. let e = (EVars(List.rev (v :: vl)),punion p1 (pos e)) in
  1063. display e
  1064. end
  1065. | [< >] ->
  1066. vl
  1067. and parse_var_decls p1 = parser
  1068. | [< name,t = parse_var_decl_head; s >] ->
  1069. let eo = parse_var_assignment s in
  1070. List.rev (parse_var_decls_next [name,t,eo] s)
  1071. | [< s >] -> error (Custom "Missing variable identifier") p1
  1072. and parse_var_decl = parser
  1073. | [< name,t = parse_var_decl_head; eo = parse_var_assignment >] -> (name,t,eo)
  1074. and inline_function = parser
  1075. | [< '(Kwd Inline,_); '(Kwd Function,p1) >] -> true, p1
  1076. | [< '(Kwd Function,p1) >] -> false, p1
  1077. and reify_expr e =
  1078. let to_expr,_,_ = reify !in_macro in
  1079. let e = to_expr e in
  1080. (ECheckType (e,(CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = None; tparams = [] })),pos e)
  1081. and parse_macro_expr p = parser
  1082. | [< '(DblDot,_); t = parse_complex_type >] ->
  1083. let _, to_type, _ = reify !in_macro in
  1084. let t = to_type t p in
  1085. (ECheckType (t,(CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some "ComplexType"; tparams = [] })),p)
  1086. | [< '(Kwd Var,p1); vl = psep Comma parse_var_decl >] ->
  1087. reify_expr (EVars vl,p1)
  1088. | [< d = parse_class None [] [] false >] ->
  1089. let _,_,to_type = reify !in_macro in
  1090. (ECheckType (to_type d,(CTPath { tpackage = ["haxe";"macro"]; tname = "Expr"; tsub = Some "TypeDefinition"; tparams = [] })),p)
  1091. | [< e = secure_expr >] ->
  1092. reify_expr e
  1093. and parse_function p1 inl = parser
  1094. | [< name = popt dollar_ident; pl = parse_constraint_params; '(POpen,_); al = psep Comma parse_fun_param; '(PClose,_); t = parse_type_opt; s >] ->
  1095. let make e =
  1096. let f = {
  1097. f_params = pl;
  1098. f_type = t;
  1099. f_args = al;
  1100. f_expr = Some e;
  1101. } in
  1102. EFunction ((match name with None -> None | Some (name,_) -> Some (if inl then "inline_" ^ name else name)),f), punion p1 (pos e)
  1103. in
  1104. (try
  1105. expr_next (make (secure_expr s)) s
  1106. with
  1107. Display e -> display (make e))
  1108. and expr = parser
  1109. | [< (name,params,p) = parse_meta_entry; s >] ->
  1110. (try
  1111. make_meta name params (secure_expr s) p
  1112. with Display e ->
  1113. display (make_meta name params e p))
  1114. | [< '(BrOpen,p1); s >] ->
  1115. if is_resuming p1 then display (EDisplay ((EObjectDecl [],p1),false),p1);
  1116. (match s with parser
  1117. | [< '(Binop OpOr,p2) when do_resume() >] ->
  1118. set_resume p1;
  1119. display (EDisplay ((EObjectDecl [],p1),false),p1);
  1120. | [< b = block1; '(BrClose,p2); s >] ->
  1121. let e = (b,punion p1 p2) in
  1122. (match b with
  1123. | EObjectDecl _ -> expr_next e s
  1124. | _ -> e))
  1125. | [< '(Kwd Macro,p); s >] ->
  1126. parse_macro_expr p s
  1127. | [< '(Kwd Var,p1); v = parse_var_decl >] -> (EVars [v],p1)
  1128. | [< '(Const c,p); s >] -> expr_next (EConst c,p) s
  1129. | [< '(Kwd This,p); s >] -> expr_next (EConst (Ident "this"),p) s
  1130. | [< '(Kwd True,p); s >] -> expr_next (EConst (Ident "true"),p) s
  1131. | [< '(Kwd False,p); s >] -> expr_next (EConst (Ident "false"),p) s
  1132. | [< '(Kwd Null,p); s >] -> expr_next (EConst (Ident "null"),p) s
  1133. | [< '(Kwd Cast,p1); s >] ->
  1134. (match s with parser
  1135. | [< '(POpen,pp); e = expr; s >] ->
  1136. (match s with parser
  1137. | [< '(Comma,_); t = parse_complex_type; '(PClose,p2); s >] -> expr_next (ECast (e,Some t),punion p1 p2) s
  1138. | [< t = parse_type_hint; '(PClose,p2); s >] ->
  1139. let ep = EParenthesis (ECheckType(e,t),punion p1 p2), punion p1 p2 in
  1140. expr_next (ECast (ep,None),punion p1 (pos ep)) s
  1141. | [< '(Const (Ident "is"),_); t = parse_type_path; '(PClose,p2); >] ->
  1142. let e_is = make_is e t (punion p1 p2) in
  1143. expr_next (ECast (e_is,None),punion p1 (pos e_is)) s
  1144. | [< '(PClose,p2); s >] ->
  1145. let ep = expr_next (EParenthesis(e),punion pp p2) s in
  1146. expr_next (ECast (ep,None),punion p1 (pos ep)) s
  1147. | [< >] -> serror())
  1148. | [< e = secure_expr >] -> expr_next (ECast (e,None),punion p1 (pos e)) s)
  1149. | [< '(Kwd Throw,p); e = expr >] -> (EThrow e,p)
  1150. | [< '(Kwd New,p1); t = parse_type_path; '(POpen,p); s >] ->
  1151. if is_resuming p then display (EDisplayNew t,punion p1 p);
  1152. (match s with parser
  1153. | [< al = psep Comma expr; '(PClose,p2); s >] -> expr_next (ENew (t,al),punion p1 p2) s
  1154. | [< >] -> serror())
  1155. | [< '(POpen,p1); e = expr; s >] -> (match s with parser
  1156. | [< '(PClose,p2); s >] -> expr_next (EParenthesis e, punion p1 p2) s
  1157. | [< t = parse_type_hint; '(PClose,p2); s >] -> expr_next (EParenthesis (ECheckType(e,t),punion p1 p2), punion p1 p2) s
  1158. | [< '(Const (Ident "is"),_); t = parse_type_path; '(PClose,p2); >] -> expr_next (make_is e t (punion p1 p2)) s
  1159. | [< >] -> serror())
  1160. | [< '(BkOpen,p1); l = parse_array_decl; '(BkClose,p2); s >] -> expr_next (EArrayDecl l, punion p1 p2) s
  1161. | [< '(Kwd Function,p1); e = parse_function p1 false; >] -> e
  1162. | [< '(Unop op,p1) when is_prefix op; e = expr >] -> make_unop op e p1
  1163. | [< '(Binop OpSub,p1); e = expr >] ->
  1164. let neg s =
  1165. if s.[0] = '-' then String.sub s 1 (String.length s - 1) else "-" ^ s
  1166. in
  1167. (match make_unop Neg e p1 with
  1168. | EUnop (Neg,Prefix,(EConst (Int i),pc)),p -> EConst (Int (neg i)),p
  1169. | EUnop (Neg,Prefix,(EConst (Float j),pc)),p -> EConst (Float (neg j)),p
  1170. | e -> e)
  1171. (*/* removed unary + : this cause too much syntax errors go unnoticed, such as "a + + 1" (missing 'b')
  1172. without adding anything to the language
  1173. | [< '(Binop OpAdd,p1); s >] ->
  1174. (match s with parser
  1175. | [< '(Const (Int i),p); e = expr_next (EConst (Int i),p) >] -> e
  1176. | [< '(Const (Float f),p); e = expr_next (EConst (Float f),p) >] -> e
  1177. | [< >] -> serror()) */*)
  1178. | [< '(Kwd For,p); '(POpen,_); it = expr; '(PClose,_); s >] ->
  1179. (try
  1180. let e = secure_expr s in
  1181. (EFor (it,e),punion p (pos e))
  1182. with
  1183. Display e -> display (EFor (it,e),punion p (pos e)))
  1184. | [< '(Kwd If,p); '(POpen,_); cond = expr; '(PClose,_); e1 = expr; s >] ->
  1185. let e2 = (match s with parser
  1186. | [< '(Kwd Else,_); e2 = expr; s >] -> Some e2
  1187. | [< >] ->
  1188. match Stream.npeek 2 s with
  1189. | [(Semicolon,_); (Kwd Else,_)] ->
  1190. Stream.junk s;
  1191. Stream.junk s;
  1192. Some (secure_expr s)
  1193. | _ ->
  1194. None
  1195. ) in
  1196. (EIf (cond,e1,e2), punion p (match e2 with None -> pos e1 | Some e -> pos e))
  1197. | [< '(Kwd Return,p); e = popt expr >] -> (EReturn e, match e with None -> p | Some e -> punion p (pos e))
  1198. | [< '(Kwd Break,p) >] -> (EBreak,p)
  1199. | [< '(Kwd Continue,p) >] -> (EContinue,p)
  1200. | [< '(Kwd While,p1); '(POpen,_); cond = expr; '(PClose,_); s >] ->
  1201. (try
  1202. let e = secure_expr s in
  1203. (EWhile (cond,e,NormalWhile),punion p1 (pos e))
  1204. with
  1205. Display e -> display (EWhile (cond,e,NormalWhile),punion p1 (pos e)))
  1206. | [< '(Kwd Do,p1); e = expr; '(Kwd While,_); '(POpen,_); cond = expr; '(PClose,_); s >] -> (EWhile (cond,e,DoWhile),punion p1 (pos e))
  1207. | [< '(Kwd Switch,p1); e = expr; '(BrOpen,_); cases , def = parse_switch_cases e []; '(BrClose,p2); s >] -> (ESwitch (e,cases,def),punion p1 p2)
  1208. | [< '(Kwd Try,p1); e = expr; cl = plist (parse_catch e); >] -> (ETry (e,cl),p1)
  1209. | [< '(IntInterval i,p1); e2 = expr >] -> make_binop OpInterval (EConst (Int i),p1) e2
  1210. | [< '(Kwd Untyped,p1); e = expr >] -> (EUntyped e,punion p1 (pos e))
  1211. | [< '(Dollar v,p); s >] -> expr_next (EConst (Ident ("$"^v)),p) s
  1212. and expr_next e1 = parser
  1213. | [< '(BrOpen,p1) when is_dollar_ident e1; eparam = expr; '(BrClose,p2); s >] ->
  1214. (match fst e1 with
  1215. | EConst(Ident n) -> expr_next (EMeta((Common.MetaInfo.from_string n,[],snd e1),eparam), punion p1 p2) s
  1216. | _ -> assert false)
  1217. | [< '(Dot,p); s >] ->
  1218. if is_resuming p then display (EDisplay (e1,false),p);
  1219. (match s with parser
  1220. | [< '(Kwd Macro,p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,"macro") , punion (pos e1) p2) s
  1221. | [< '(Kwd New,p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,"new") , punion (pos e1) p2) s
  1222. | [< '(Const (Ident f),p2) when p.pmax = p2.pmin; s >] -> expr_next (EField (e1,f) , punion (pos e1) p2) s
  1223. | [< '(Dollar v,p2); s >] -> expr_next (EField (e1,"$"^v) , punion (pos e1) p2) s
  1224. | [< '(Binop OpOr,p2) when do_resume() >] ->
  1225. set_resume p;
  1226. display (EDisplay (e1,false),p) (* help for debug display mode *)
  1227. | [< >] ->
  1228. (* turn an integer followed by a dot into a float *)
  1229. match e1 with
  1230. | (EConst (Int v),p2) when p2.pmax = p.pmin -> expr_next (EConst (Float (v ^ ".")),punion p p2) s
  1231. | _ -> serror())
  1232. | [< '(POpen,p1); s >] ->
  1233. if is_resuming p1 then display (EDisplay (e1,true),p1);
  1234. (match s with parser
  1235. | [< '(Binop OpOr,p2) when do_resume() >] ->
  1236. set_resume p1;
  1237. display (EDisplay (e1,true),p1) (* help for debug display mode *)
  1238. | [< params = parse_call_params e1; '(PClose,p2); s >] -> expr_next (ECall (e1,params) , punion (pos e1) p2) s
  1239. | [< >] -> serror())
  1240. | [< '(BkOpen,_); e2 = expr; '(BkClose,p2); s >] ->
  1241. expr_next (EArray (e1,e2), punion (pos e1) p2) s
  1242. | [< '(Binop OpGt,p1); s >] ->
  1243. (match s with parser
  1244. | [< '(Binop OpGt,p2) when p1.pmax = p2.pmin; s >] ->
  1245. (match s with parser
  1246. | [< '(Binop OpGt,p3) when p2.pmax = p3.pmin >] ->
  1247. (match s with parser
  1248. | [< '(Binop OpAssign,p4) when p3.pmax = p4.pmin; e2 = expr >] -> make_binop (OpAssignOp OpUShr) e1 e2
  1249. | [< e2 = secure_expr >] -> make_binop OpUShr e1 e2)
  1250. | [< '(Binop OpAssign,p3) when p2.pmax = p3.pmin; e2 = expr >] -> make_binop (OpAssignOp OpShr) e1 e2
  1251. | [< e2 = secure_expr >] -> make_binop OpShr e1 e2)
  1252. | [< '(Binop OpAssign,p2) when p1.pmax = p2.pmin; s >] ->
  1253. make_binop OpGte e1 (secure_expr s)
  1254. | [< e2 = secure_expr >] ->
  1255. make_binop OpGt e1 e2)
  1256. | [< '(Binop op,_); s >] ->
  1257. (try
  1258. (match s with parser
  1259. | [< e2 = expr >] -> make_binop op e1 e2
  1260. | [< >] -> serror())
  1261. with Display e2 ->
  1262. raise (Display (make_binop op e1 e2)))
  1263. | [< '(Unop op,p) when is_postfix e1 op; s >] ->
  1264. expr_next (EUnop (op,Postfix,e1), punion (pos e1) p) s
  1265. | [< '(Question,_); e2 = expr; '(DblDot,_); e3 = expr >] ->
  1266. (ETernary (e1,e2,e3),punion (pos e1) (pos e3))
  1267. | [< '(Kwd In,_); e2 = expr >] ->
  1268. (EIn (e1,e2), punion (pos e1) (pos e2))
  1269. | [< >] -> e1
  1270. and parse_guard = parser
  1271. | [< '(Kwd If,p1); '(POpen,_); e = expr; '(PClose,_); >] ->
  1272. e
  1273. and parse_switch_cases eswitch cases = parser
  1274. | [< '(Kwd Default,p1); '(DblDot,_); s >] ->
  1275. let b = (try block [] s with Display e -> display (ESwitch (eswitch,cases,Some (Some e)),punion (pos eswitch) (pos e))) in
  1276. let b = match b with
  1277. | [] -> None
  1278. | _ -> Some ((EBlock b,p1))
  1279. in
  1280. let l , def = parse_switch_cases eswitch cases s in
  1281. (match def with None -> () | Some _ -> error Duplicate_default p1);
  1282. l , Some b
  1283. | [< '(Kwd Case,p1); el = psep Comma expr; eg = popt parse_guard; '(DblDot,_); s >] ->
  1284. (match el with
  1285. | [] -> error (Custom "case without a pattern is not allowed") p1
  1286. | _ ->
  1287. let b = (try block [] s with Display e -> display (ESwitch (eswitch,List.rev ((el,eg,Some e) :: cases),None),punion (pos eswitch) (pos e))) in
  1288. let b = match b with
  1289. | [] -> None
  1290. | _ -> Some ((EBlock b,p1))
  1291. in
  1292. parse_switch_cases eswitch ((el,eg,b) :: cases) s
  1293. )
  1294. | [< >] ->
  1295. List.rev cases , None
  1296. and parse_catch etry = parser
  1297. | [< '(Kwd Catch,p); '(POpen,_); name, _ = dollar_ident; s >] ->
  1298. match s with parser
  1299. | [< t = parse_type_hint; '(PClose,_); s >] ->
  1300. (try
  1301. (name,t,secure_expr s)
  1302. with
  1303. Display e -> display (ETry (etry,[name,t,e]),punion (pos etry) (pos e)))
  1304. | [< '(_,p) >] -> error Missing_type p
  1305. and parse_call_params ec s =
  1306. let e = (try
  1307. match s with parser
  1308. | [< e = expr >] -> Some e
  1309. | [< >] -> None
  1310. with Display e ->
  1311. display (ECall (ec,[e]),punion (pos ec) (pos e))
  1312. ) in
  1313. let rec loop acc =
  1314. try
  1315. match s with parser
  1316. | [< '(Comma,_); e = expr >] -> loop (e::acc)
  1317. | [< >] -> List.rev acc
  1318. with Display e ->
  1319. display (ECall (ec,List.rev (e::acc)),punion (pos ec) (pos e))
  1320. in
  1321. match e with
  1322. | None -> []
  1323. | Some e -> loop [e]
  1324. and parse_macro_cond allow_op s =
  1325. match s with parser
  1326. | [< '(Const (Ident t),p) >] ->
  1327. parse_macro_ident allow_op t p s
  1328. | [< '(Const (String s),p) >] ->
  1329. None, (EConst (String s),p)
  1330. | [< '(Const (Int i),p) >] ->
  1331. None, (EConst (Int i),p)
  1332. | [< '(Const (Float f),p) >] ->
  1333. None, (EConst (Float f),p)
  1334. | [< '(Kwd k,p) >] ->
  1335. parse_macro_ident allow_op (s_keyword k) p s
  1336. | [< '(POpen, p1); _,e = parse_macro_cond true; '(PClose, p2) >] ->
  1337. let e = (EParenthesis e,punion p1 p2) in
  1338. if allow_op then parse_macro_op e s else None, e
  1339. | [< '(Unop op,p); tk, e = parse_macro_cond allow_op >] ->
  1340. tk, make_unop op e p
  1341. and parse_macro_ident allow_op t p s =
  1342. let e = (EConst (Ident t),p) in
  1343. if not allow_op then
  1344. None, e
  1345. else
  1346. parse_macro_op e s
  1347. and parse_macro_op e s =
  1348. match Stream.peek s with
  1349. | Some (Binop op,_) ->
  1350. Stream.junk s;
  1351. let op = match Stream.peek s with
  1352. | Some (Binop OpAssign,_) when op = OpGt ->
  1353. Stream.junk s;
  1354. OpGte
  1355. | _ -> op
  1356. in
  1357. let tk, e2 = (try parse_macro_cond true s with Stream.Failure -> serror()) in
  1358. tk, make_binop op e e2
  1359. | tk ->
  1360. tk, e
  1361. and toplevel_expr s =
  1362. try
  1363. expr s
  1364. with
  1365. Display e -> e
  1366. and secure_expr s =
  1367. match s with parser
  1368. | [< e = expr >] -> e
  1369. | [< >] -> serror()
  1370. (* eval *)
  1371. type small_type =
  1372. | TNull
  1373. | TBool of bool
  1374. | TFloat of float
  1375. | TString of string
  1376. let is_true = function
  1377. | TBool false | TNull | TFloat 0. | TString "" -> false
  1378. | _ -> true
  1379. let cmp v1 v2 =
  1380. match v1, v2 with
  1381. | TNull, TNull -> 0
  1382. | TFloat a, TFloat b -> compare a b
  1383. | TString a, TString b -> compare a b
  1384. | TBool a, TBool b -> compare a b
  1385. | TString a, TFloat b -> compare (float_of_string a) b
  1386. | TFloat a, TString b -> compare a (float_of_string b)
  1387. | _ -> raise Exit (* always false *)
  1388. let rec eval ctx (e,p) =
  1389. match e with
  1390. | EConst (Ident i) ->
  1391. (try TString (Common.raw_defined_value ctx i) with Not_found -> TNull)
  1392. | EConst (String s) -> TString s
  1393. | EConst (Int i) -> TFloat (float_of_string i)
  1394. | EConst (Float f) -> TFloat (float_of_string f)
  1395. | EBinop (OpBoolAnd, e1, e2) -> TBool (is_true (eval ctx e1) && is_true (eval ctx e2))
  1396. | EBinop (OpBoolOr, e1, e2) -> TBool (is_true (eval ctx e1) || is_true(eval ctx e2))
  1397. | EUnop (Not, _, e) -> TBool (not (is_true (eval ctx e)))
  1398. | EParenthesis e -> eval ctx e
  1399. | EBinop (op, e1, e2) ->
  1400. let v1 = eval ctx e1 in
  1401. let v2 = eval ctx e2 in
  1402. let compare op =
  1403. TBool (try op (cmp v1 v2) 0 with _ -> false)
  1404. in
  1405. (match op with
  1406. | OpEq -> compare (=)
  1407. | OpNotEq -> compare (<>)
  1408. | OpGt -> compare (>)
  1409. | OpGte -> compare (>=)
  1410. | OpLt -> compare (<)
  1411. | OpLte -> compare (<=)
  1412. | _ -> error (Custom "Unsupported operation") p)
  1413. | _ ->
  1414. error (Custom "Invalid condition expression") p
  1415. (* parse main *)
  1416. let parse ctx code =
  1417. let old = Lexer.save() in
  1418. let old_cache = !cache in
  1419. let mstack = ref [] in
  1420. cache := DynArray.create();
  1421. last_doc := None;
  1422. in_macro := Common.defined ctx Common.Define.Macro;
  1423. Lexer.skip_header code;
  1424. let sraw = Stream.from (fun _ -> Some (Lexer.token code)) in
  1425. let rec next_token() = process_token (Lexer.token code)
  1426. and process_token tk =
  1427. match fst tk with
  1428. | Comment s ->
  1429. let tk = next_token() in
  1430. if !use_doc then begin
  1431. let l = String.length s in
  1432. if l > 0 && s.[0] = '*' then last_doc := Some (String.sub s 1 (l - (if l > 1 && s.[l-1] = '*' then 2 else 1)), (snd tk).pmin);
  1433. end;
  1434. tk
  1435. | CommentLine s ->
  1436. next_token()
  1437. | Sharp "end" ->
  1438. (match !mstack with
  1439. | [] -> tk
  1440. | _ :: l ->
  1441. mstack := l;
  1442. next_token())
  1443. | Sharp "else" | Sharp "elseif" ->
  1444. (match !mstack with
  1445. | [] -> tk
  1446. | _ :: l ->
  1447. mstack := l;
  1448. process_token (skip_tokens (snd tk) false))
  1449. | Sharp "if" ->
  1450. process_token (enter_macro (snd tk))
  1451. | Sharp "error" ->
  1452. (match Lexer.token code with
  1453. | (Const (String s),p) -> error (Custom s) p
  1454. | _ -> error Unimplemented (snd tk))
  1455. | Sharp "line" ->
  1456. let line = (match next_token() with
  1457. | (Const (Int s),_) -> int_of_string s
  1458. | (t,p) -> error (Unexpected t) p
  1459. ) in
  1460. !(Lexer.cur).Lexer.lline <- line - 1;
  1461. next_token();
  1462. | _ ->
  1463. tk
  1464. and enter_macro p =
  1465. let tk, e = parse_macro_cond false sraw in
  1466. let tk = (match tk with None -> Lexer.token code | Some tk -> tk) in
  1467. if is_true (eval ctx e) || (match fst e with EConst (Ident "macro") when Common.unique_full_path p.pfile = (!resume_display).pfile -> true | _ -> false) then begin
  1468. mstack := p :: !mstack;
  1469. tk
  1470. end else
  1471. skip_tokens_loop p true tk
  1472. and skip_tokens_loop p test tk =
  1473. match fst tk with
  1474. | Sharp "end" ->
  1475. Lexer.token code
  1476. | Sharp "elseif" | Sharp "else" when not test ->
  1477. skip_tokens p test
  1478. | Sharp "else" ->
  1479. mstack := snd tk :: !mstack;
  1480. Lexer.token code
  1481. | Sharp "elseif" ->
  1482. enter_macro (snd tk)
  1483. | Sharp "if" ->
  1484. skip_tokens_loop p test (skip_tokens p false)
  1485. | Eof ->
  1486. if do_resume() then tk else error Unclosed_macro p
  1487. | _ ->
  1488. skip_tokens p test
  1489. and skip_tokens p test = skip_tokens_loop p test (Lexer.token code)
  1490. in
  1491. let s = Stream.from (fun _ ->
  1492. let t = next_token() in
  1493. DynArray.add (!cache) t;
  1494. Some t
  1495. ) in
  1496. try
  1497. let l = parse_file s in
  1498. (match !mstack with p :: _ when not (do_resume()) -> error Unclosed_macro p | _ -> ());
  1499. cache := old_cache;
  1500. Lexer.restore old;
  1501. l
  1502. with
  1503. | Stream.Error _
  1504. | Stream.Failure ->
  1505. let last = (match Stream.peek s with None -> last_token s | Some t -> t) in
  1506. Lexer.restore old;
  1507. cache := old_cache;
  1508. error (Unexpected (fst last)) (pos last)
  1509. | e ->
  1510. Lexer.restore old;
  1511. cache := old_cache;
  1512. raise e