/fparsec/main/FParsec/Primitives.fs

http://github.com/sandersn/fing · F# · 884 lines · 752 code · 92 blank · 40 comment · 215 complexity · 1b85325a5836812f67c88819f56a6e82 MD5 · raw file

  1. // Copyright (c) Stephan Tolksdorf 2007-2009
  2. // License: Simplified BSD License. See accompanying documentation.
  3. module FParsec.Primitives
  4. open FParsec.Internals
  5. open FParsec.Error
  6. type ReplyStatus = Ok = 1
  7. | Error = 0
  8. | FatalError = -1
  9. [<Literal>]
  10. let Ok = ReplyStatus.Ok
  11. [<Literal>]
  12. let Error = ReplyStatus.Error
  13. [<Literal>]
  14. let FatalError = ReplyStatus.FatalError
  15. [<System.Diagnostics.DebuggerDisplay("{GetDebuggerDisplay(),nq}")>]
  16. [<CustomEquality; NoComparison>]
  17. type Reply<'Result,'UserState> = struct
  18. new (result, state) = {State = state; Error = NoErrorMessages; Result = result; Status = Ok}
  19. new (status, error, state) = {State = state; Error = error; Result = Unchecked.defaultof<_>; Status = status}
  20. new (status, result, error, state) = {State = state; Error = error; Result = result; Status = status}
  21. // The order of the following fields was chosen to optimize the object layout.
  22. // We don't use LayoutKind.Auto because it inhibits JIT optimizations:
  23. // http://blogs.msdn.com/clrcodegeneration/archive/2007/11/02/how-are-value-types-implemented-in-the-32-bit-clr-what-has-been-done-to-improve-their-performance.aspx
  24. val mutable State: State<'UserState>
  25. [<System.Diagnostics.DebuggerDisplay("{FParsec.Error.ErrorMessageList.GetDebuggerDisplay(Error),nq}")>]
  26. val mutable Error: ErrorMessageList
  27. /// If Status <> Ok then the value of the Result field is undefined and may be equal to Unchecked.defaultof<'Result>.
  28. val mutable Result: 'Result
  29. val mutable Status: ReplyStatus
  30. override t.Equals(value: obj) =
  31. match value with
  32. | :? Reply<'Result,'UserState> as r ->
  33. t.Status = r.Status
  34. && (t.Status <> Ok || LanguagePrimitives.GenericEqualityERComparer.Equals(t.Result, r.Result))
  35. && t.State = r.State
  36. && t.Error = r.Error
  37. | _ -> false
  38. override t.GetHashCode() =
  39. // GetHashCode() is not required to return different hash codes for unequal instances
  40. int t.Status ^^^ t.State.GetHashCode()
  41. member private t.GetDebuggerDisplay() =
  42. let pos = if isNull t.State then "null" else t.State.Position.ToString()
  43. if t.Status = Ok && isNull t.Error then
  44. if typeof<'Result> = typeof<unit> then "Reply((), " + pos + ")"
  45. else sprintf "Reply(%0.5A, %s)" t.Result pos
  46. else
  47. let e = FParsec.Error.ErrorMessageList.GetDebuggerDisplay(t.Error)
  48. if t.Status = Ok then
  49. if typeof<'Result> = typeof<unit> then "Reply(Ok, (), " + e + ", " + pos + ")"
  50. else sprintf "Reply(Ok, %0.5A, %s, %s)" t.Result e pos
  51. else sprintf "Reply(Error, %s, %s)" e pos
  52. end
  53. type Parser<'a, 'u> = State<'u> -> Reply<'a,'u>
  54. // =================================
  55. // Parser primitives and combinators
  56. // =================================
  57. // The `PrimitiveTests.Reference` module contains simple (but sometimes naive)
  58. // reference implementations of most of the functions below.
  59. let preturn x = fun state -> Reply(x, state)
  60. let pzero : Parser<'a,'u> = fun state -> Reply(Error, NoErrorMessages, state)
  61. // ---------------------------
  62. // Chaining and piping parsers
  63. // ---------------------------
  64. let (>>=) (p: Parser<'a,'u>) (f: 'a -> Parser<'b,'u>) =
  65. match box f with
  66. // optimization for uncurried functions
  67. | :? OptimizedClosures.FSharpFunc<'a, State<'u>, Reply<'b,'u>> as optF ->
  68. fun state ->
  69. let reply1 = p state
  70. if reply1.Status = Ok then
  71. let mutable reply2 = optF.Invoke(reply1.Result, reply1.State)
  72. if isNotNull reply1.Error && reply2.State == reply1.State then
  73. reply2.Error <- concatErrorMessages reply1.Error reply2.Error
  74. reply2
  75. else
  76. Reply(reply1.Status, reply1.Error, reply1.State)
  77. | _ ->
  78. fun state ->
  79. let reply1 = p state
  80. if reply1.Status = Ok then
  81. let p2 = f reply1.Result
  82. let mutable reply2 = p2 reply1.State
  83. if isNotNull reply1.Error && reply2.State == reply1.State then
  84. reply2.Error <- concatErrorMessages reply1.Error reply2.Error
  85. reply2
  86. else
  87. Reply(reply1.Status, reply1.Error, reply1.State)
  88. let (>>%) (p: Parser<'a,'u>) x =
  89. fun state ->
  90. let reply = p state
  91. Reply(reply.Status, x, reply.Error, reply.State)
  92. let (>>.) (p: Parser<'a,'u>) (q: Parser<'b,'u>) =
  93. fun state ->
  94. let reply1 = p state
  95. if reply1.Status = Ok then
  96. let mutable reply2 = q reply1.State
  97. if isNotNull reply1.Error && reply2.State == reply1.State then
  98. reply2.Error <- concatErrorMessages reply1.Error reply2.Error
  99. reply2
  100. else
  101. Reply(reply1.Status, reply1.Error, reply1.State)
  102. let (.>>) (p: Parser<'a,'u>) (q: Parser<'b,'u>) =
  103. fun state ->
  104. let mutable reply1 = p state
  105. if reply1.Status = Ok then
  106. let reply2 = q reply1.State
  107. reply1.Error <- mergeErrorsIfNeeded reply1.State reply1.Error reply2.State reply2.Error
  108. reply1.State <- reply2.State
  109. reply1.Status <- reply2.Status
  110. reply1
  111. let between (popen: Parser<_,'u>) (pclose: Parser<_,'u>) (p: Parser<_,'u>) =
  112. fun state ->
  113. let reply1 = popen state
  114. if reply1.Status = Ok then
  115. let mutable reply2 = p reply1.State
  116. let error = mergeErrorsIfNeeded reply1.State reply1.Error reply2.State reply2.Error
  117. if reply2.Status = Ok then
  118. let reply3 = pclose reply2.State
  119. reply2.Error <- mergeErrorsIfNeeded reply2.State error reply3.State reply3.Error
  120. reply2.State <- reply3.State
  121. reply2.Status <- reply3.Status
  122. else
  123. reply2.Error <- error
  124. reply2
  125. else
  126. Reply(reply1.Status, reply1.Error, reply1.State)
  127. let (|>>) (p: Parser<'a,'u>) f =
  128. fun state ->
  129. let reply = p state
  130. Reply(reply.Status,
  131. (if reply.Status = Ok then f reply.Result else Unchecked.defaultof<_>),
  132. reply.Error,
  133. reply.State)
  134. let pipe2 (p1: Parser<'a,'u>) (p2: Parser<'b,'u>) f =
  135. let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  136. fun state ->
  137. let reply1 = p1 state
  138. let mutable error = reply1.Error
  139. if reply1.Status = Ok then
  140. let reply2 = p2 reply1.State
  141. error <- mergeErrorsIfNeeded reply1.State error reply2.State reply2.Error
  142. if reply2.Status = Ok then
  143. Reply(Ok, optF.Invoke(reply1.Result, reply2.Result), error, reply2.State)
  144. else Reply(reply2.Status, error, reply2.State)
  145. else Reply(reply1.Status, reply1.Error, reply1.State)
  146. let pipe3 (p1: Parser<'a,'u>) (p2: Parser<'b,'u>) (p3: Parser<'c,'u>) f =
  147. let optF = OptimizedClosures.FSharpFunc<_,_,_,_>.Adapt(f)
  148. fun state ->
  149. let reply1 = p1 state
  150. let mutable error = reply1.Error
  151. if reply1.Status = Ok then
  152. let reply2 = p2 reply1.State
  153. error <- mergeErrorsIfNeeded reply1.State error reply2.State reply2.Error
  154. if reply2.Status = Ok then
  155. let reply3 = p3 reply2.State
  156. error <- mergeErrorsIfNeeded reply2.State error reply3.State reply3.Error
  157. if reply3.Status = Ok then
  158. Reply(Ok, optF.Invoke(reply1.Result, reply2.Result, reply3.Result), error, reply3.State)
  159. else Reply(reply3.Status, error, reply3.State)
  160. else Reply(reply2.Status, error, reply2.State)
  161. else Reply(reply1.Status, error, reply1.State)
  162. let pipe4 (p1: Parser<'a,'u>) (p2: Parser<'b,'u>) (p3: Parser<'c,'u>) (p4: Parser<'d,'u>) f =
  163. let optF = OptimizedClosures.FSharpFunc<_,_,_,_,_>.Adapt(f)
  164. fun state ->
  165. let reply1 = p1 state
  166. let mutable error = reply1.Error
  167. if reply1.Status = Ok then
  168. let reply2 = p2 reply1.State
  169. error <- mergeErrorsIfNeeded reply1.State error reply2.State reply2.Error
  170. if reply2.Status = Ok then
  171. let reply3 = p3 reply2.State
  172. error <- mergeErrorsIfNeeded reply2.State error reply3.State reply3.Error
  173. if reply3.Status = Ok then
  174. let reply4 = p4 reply3.State
  175. error <- mergeErrorsIfNeeded reply3.State error reply4.State reply4.Error
  176. if reply4.Status = Ok then
  177. Reply(Ok, optF.Invoke(reply1.Result, reply2.Result, reply3.Result, reply4.Result), error, reply4.State)
  178. else Reply(reply4.Status, error, reply4.State)
  179. else Reply(reply3.Status, error, reply3.State)
  180. else Reply(reply2.Status, error, reply2.State)
  181. else Reply(reply1.Status, error, reply1.State)
  182. let pipe5 (p1: Parser<'a,'u>) (p2: Parser<'b,'u>) (p3: Parser<'c,'u>) (p4: Parser<'d,'u>) (p5: Parser<'e,'u>) f =
  183. let optF = OptimizedClosures.FSharpFunc<_,_,_,_,_,_>.Adapt(f)
  184. fun state ->
  185. let reply1 = p1 state
  186. let mutable error = reply1.Error
  187. if reply1.Status = Ok then
  188. let reply2 = p2 reply1.State
  189. error <- mergeErrorsIfNeeded reply1.State error reply2.State reply2.Error
  190. if reply2.Status = Ok then
  191. let reply3 = p3 reply2.State
  192. error <- mergeErrorsIfNeeded reply2.State error reply3.State reply3.Error
  193. if reply3.Status = Ok then
  194. let reply4 = p4 reply3.State
  195. error <- mergeErrorsIfNeeded reply3.State error reply4.State reply4.Error
  196. if reply4.Status = Ok then
  197. let reply5 = p5 reply4.State
  198. error <- mergeErrorsIfNeeded reply4.State error reply5.State reply5.Error
  199. if reply5.Status = Ok then
  200. Reply(Ok, optF.Invoke(reply1.Result, reply2.Result, reply3.Result, reply4.Result, reply5.Result), error, reply5.State)
  201. else Reply(reply5.Status, error, reply5.State)
  202. else Reply(reply4.Status, error, reply4.State)
  203. else Reply(reply3.Status, error, reply3.State)
  204. else Reply(reply2.Status, error, reply2.State)
  205. else Reply(reply1.Status, error, reply1.State)
  206. // -----------------------------------------------
  207. // Parsing alternatives and recovering from errors
  208. // -----------------------------------------------
  209. let (<|>) (p1: Parser<'a,'u>) (p2: Parser<'a,'u>) : Parser<'a,'u> =
  210. fun state ->
  211. let reply1 = p1 state
  212. if reply1.Status = Error && reply1.State == state then
  213. let mutable reply2 = p2 state
  214. if reply2.State == reply1.State then
  215. reply2.Error <- mergeErrors reply1.Error reply2.Error
  216. reply2
  217. else reply1
  218. let choice (ps: seq<Parser<'a,'u>>) =
  219. match ps with
  220. | :? (Parser<'a,'u>[]) as ps ->
  221. if ps.Length = 0 then pzero
  222. else
  223. fun state ->
  224. let mutable error = NoErrorMessages
  225. let mutable reply = ps.[0] state
  226. let mutable i = 1
  227. while reply.Status = Error && reply.State == state && i < ps.Length do
  228. error <- mergeErrors error reply.Error
  229. reply <- ps.[i] state
  230. i <- i + 1
  231. if reply.State == state then
  232. reply.Error <- mergeErrors error reply.Error
  233. reply
  234. | :? (Parser<'a,'u> list) as ps ->
  235. match ps with
  236. | [] -> pzero
  237. | hd::tl ->
  238. fun state ->
  239. let mutable error = NoErrorMessages
  240. let mutable hd, tl = hd, tl
  241. let mutable reply = hd state
  242. while reply.Status = Error && reply.State == state
  243. && (match tl with
  244. | h::t -> hd <- h; tl <- t; true
  245. | _ -> false)
  246. do
  247. error <- mergeErrors error reply.Error
  248. reply <- hd state
  249. if reply.State == state then
  250. reply.Error <- mergeErrors error reply.Error
  251. reply
  252. | _ -> fun state ->
  253. use iter = ps.GetEnumerator()
  254. if iter.MoveNext() then
  255. let mutable error = NoErrorMessages
  256. let mutable reply = iter.Current state
  257. while reply.Status = Error && reply.State == state && iter.MoveNext() do
  258. error <- mergeErrors error reply.Error
  259. reply <- iter.Current state
  260. if reply.State == state then
  261. reply.Error <- mergeErrors error reply.Error
  262. reply
  263. else
  264. Reply(Error, NoErrorMessages, state)
  265. let choiceL (ps: seq<Parser<'a,'u>>) label =
  266. let error = expectedError label
  267. match ps with
  268. | :? (Parser<'a,'u>[]) as ps ->
  269. if ps.Length = 0 then pzero
  270. else
  271. fun state ->
  272. let mutable reply = ps.[0] state
  273. let mutable i = 1
  274. while reply.Status = Error && reply.State == state && i < ps.Length do
  275. reply <- ps.[i] state
  276. i <- i + 1
  277. if reply.State == state then
  278. reply.Error <- error
  279. reply
  280. | :? (Parser<'a,'u> list) as ps ->
  281. match ps with
  282. | [] -> pzero
  283. | hd::tl ->
  284. fun state ->
  285. let mutable hd, tl = hd, tl
  286. let mutable reply = hd state
  287. while reply.Status = Error && reply.State == state
  288. && (match tl with
  289. | h::t -> hd <- h; tl <- t; true
  290. | _ -> false)
  291. do
  292. reply <- hd state
  293. if reply.State == state then
  294. reply.Error <- error
  295. reply
  296. | _ -> fun state ->
  297. use iter = ps.GetEnumerator()
  298. if iter.MoveNext() then
  299. let mutable reply = iter.Current state
  300. while reply.Status = Error && reply.State == state && iter.MoveNext() do
  301. reply <- iter.Current state
  302. if reply.State == state then
  303. reply.Error <- error
  304. reply
  305. else
  306. Reply(Error, NoErrorMessages, state)
  307. let (<|>%) (p: Parser<'a,'u>) x =
  308. fun state ->
  309. let mutable reply = p state
  310. if reply.Status = Error && reply.State == state then
  311. reply.Result <- x
  312. reply.Status <- Ok
  313. reply
  314. let opt (p: Parser<'a,'u>) : Parser<'a option,'u> =
  315. fun state ->
  316. let reply = p state
  317. if reply.Status = Ok then
  318. Reply(Ok, Some reply.Result, reply.Error, reply.State)
  319. else
  320. // None is represented as null
  321. let status = if reply.Status = Error && reply.State == state then Ok else reply.Status
  322. Reply(status, reply.Error, reply.State)
  323. let optional (p: Parser<'a,'u>) : Parser<unit,'u> =
  324. fun state ->
  325. let reply = p state
  326. let status = if reply.Status = Error && reply.State == state then Ok else reply.Status
  327. // () is represented as null
  328. Reply<unit,_>(status, reply.Error, reply.State)
  329. let attempt (p: Parser<'a,'u>) =
  330. fun state ->
  331. let mutable reply = p state
  332. if reply.Status <> Ok then
  333. if reply.State != state then
  334. reply.Error <- backtrackError reply.State reply.Error
  335. reply.State <- state
  336. reply.Status <- Error // turns FatalErrors into Errors
  337. elif reply.Status = FatalError then
  338. reply.Status <- Error
  339. reply
  340. let (>>=?) (p: Parser<'a,'u>) (f: 'a -> Parser<'b,'u>) =
  341. let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  342. fun state ->
  343. let reply1 = p state
  344. if reply1.Status = Ok then
  345. let mutable reply2 = optF.Invoke(reply1.Result, reply1.State)
  346. if reply2.State == reply1.State then
  347. let error = mergeErrors reply1.Error reply2.Error
  348. if reply2.Status = Ok then reply2.Error <- error
  349. else
  350. if reply1.State == state then reply2.Error <- error
  351. else
  352. reply2.Error <- backtrackError reply2.State error
  353. reply2.State <- state
  354. reply2.Status <- Error // turns FatalErrors into Error
  355. reply2
  356. else
  357. Reply(reply1.Status, reply1.Error, reply1.State)
  358. let (>>?) (p: Parser<'a,'u>) (q: Parser<'b,'u>) =
  359. fun state ->
  360. let reply1 = p state
  361. if reply1.Status = Ok then
  362. let mutable reply2 = q reply1.State
  363. if reply2.State == reply1.State then
  364. let error = mergeErrors reply1.Error reply2.Error
  365. if reply2.Status = Ok then reply2.Error <- error
  366. else
  367. if reply1.State == state then reply2.Error <- error
  368. else
  369. reply2.Error <- backtrackError reply2.State error
  370. reply2.State <- state
  371. reply2.Status <- Error // turns FatalErrors into Errors
  372. reply2
  373. else
  374. Reply(reply1.Status, reply1.Error, reply1.State)
  375. let (.>>?) (p: Parser<'a,'u>) (q: Parser<'b,'u>) =
  376. fun state ->
  377. let mutable reply1 = p state
  378. if reply1.Status = Ok then
  379. let reply2 = q reply1.State
  380. if reply2.State == reply1.State then
  381. let error = mergeErrors reply1.Error reply2.Error
  382. if reply2.Status = Ok then reply1.Error <- error
  383. else
  384. if reply1.State == state then reply1.Error <- error
  385. else
  386. reply1.Error <- backtrackError reply1.State error
  387. reply1.State <- state
  388. reply1.Status <- Error // turns FatalErrors into Errors
  389. else
  390. reply1.State <- reply2.State
  391. reply1.Error <- reply2.Error
  392. reply1.Status <- reply2.Status
  393. reply1
  394. // -------------------------------------
  395. // Conditional parsing and looking ahead
  396. // -------------------------------------
  397. /// REVIEW: should `followedBy` use the error messages generated by `p`?
  398. let internal followedByE (p: Parser<'a,'u>) error =
  399. fun state ->
  400. let reply = p state
  401. if reply.Status = Ok then Reply((), state)
  402. else Reply(Error, error, state)
  403. let followedBy p = followedByE p NoErrorMessages
  404. let followedByL p label = followedByE p (expectedError label)
  405. let internal notFollowedByE (p: Parser<'a,'u>) error =
  406. fun state ->
  407. let reply = p state
  408. if reply.Status <> Ok then Reply((), state)
  409. else Reply(Error, error, state)
  410. let notFollowedBy p = notFollowedByE p NoErrorMessages
  411. let notFollowedByL p label = notFollowedByE p (unexpectedError label)
  412. let lookAhead (p: Parser<'a,'u>) =
  413. fun state ->
  414. let mutable reply = p state
  415. if reply.Status = Ok then
  416. reply.State <- state
  417. reply.Error <- NoErrorMessages
  418. else
  419. if reply.State != state then
  420. reply.Error <- backtrackError reply.State reply.Error
  421. reply.State <- state
  422. reply.Status <- Error // turn FatalErrors into normal Errors
  423. reply
  424. // --------------------------
  425. // Customizing error messages
  426. // --------------------------
  427. let (<?>) (p: Parser<'a,'u>) label =
  428. let error = expectedError label
  429. fun state ->
  430. let mutable reply = p state
  431. if reply.State == state then
  432. reply.Error <- error
  433. reply
  434. let (<??>) (p: Parser<'a,'u>) label =
  435. let expErr = expectedError label
  436. fun state ->
  437. let mutable reply = p state
  438. if reply.Status = Ok then
  439. if reply.State == state then
  440. reply.Error <- expErr
  441. else
  442. if reply.State == state then
  443. reply.Error <- match reply.Error with
  444. | AddErrorMessage(BacktrackPoint(pos, msgs), NoErrorMessages)
  445. -> AddErrorMessage(CompoundError(label, pos, msgs), NoErrorMessages)
  446. | _ -> expErr
  447. else
  448. reply.Error <- compoundError label reply.State reply.Error
  449. reply.State <- state // we backtrack ...
  450. reply.Status <- FatalError // ... so we need to make sure normal parsing doesn't continue
  451. reply
  452. let fail msg : Parser<'a,'u> =
  453. let error = messageError msg
  454. fun state ->
  455. Reply(Error, error, state)
  456. let failFatally msg : Parser<'a,'u> =
  457. let error = messageError msg
  458. fun state -> Reply(FatalError, error, state)
  459. // -----------------
  460. // Parsing sequences
  461. // -----------------
  462. let tuple2 p1 p2 = pipe2 p1 p2 (fun a b -> (a, b))
  463. let tuple3 p1 p2 p3 = pipe3 p1 p2 p3 (fun a b c -> (a, b, c))
  464. let tuple4 p1 p2 p3 p4 = pipe4 p1 p2 p3 p4 (fun a b c d -> (a, b, c, d))
  465. let tuple5 p1 p2 p3 p4 p5 = pipe5 p1 p2 p3 p4 p5 (fun a b c d e -> (a, b, c, d, e))
  466. let parray n (p: Parser<'a,'u>) =
  467. if n = 0 then preturn [||]
  468. else
  469. fun state ->
  470. let mutable reply = p state
  471. let mutable error = reply.Error
  472. let mutable newReply = Unchecked.defaultof<Reply<_,_>>
  473. if reply.Status = Ok then
  474. let mutable xs = Array.zeroCreate n
  475. xs.[0] <- reply.Result
  476. let mutable i = 1
  477. while i < n do
  478. let prevState = reply.State
  479. reply <- p prevState
  480. error <- mergeErrorsIfNeeded prevState error reply.State reply.Error
  481. if reply.Status = Ok then
  482. xs.[i] <- reply.Result
  483. i <- i + 1
  484. else
  485. i <- n // break
  486. newReply.Result <- xs // we set the result even if there was an error
  487. newReply.State <- reply.State
  488. newReply.Error <- error
  489. newReply.Status <- reply.Status
  490. newReply
  491. let skipArray n (p: Parser<'a,'u>) =
  492. if n = 0 then preturn ()
  493. else
  494. fun state ->
  495. let mutable reply = p state
  496. let mutable error = reply.Error
  497. let mutable newReply = Unchecked.defaultof<Reply<_,_>>
  498. if reply.Status = Ok then
  499. let mutable i = 1
  500. while i < n do
  501. let prevState = reply.State
  502. reply <- p prevState
  503. error <- mergeErrorsIfNeeded prevState error reply.State reply.Error
  504. if reply.Status = Ok then
  505. i <- i + 1
  506. else
  507. i <- n // break
  508. // () is represented as null
  509. newReply.State <- reply.State
  510. newReply.Error <- error
  511. newReply.Status <- reply.Status
  512. newReply
  513. let
  514. #if NOINLINE
  515. #else
  516. inline
  517. #endif
  518. private manyFoldApplyImpl require1 fold1 fold applyF getEmpty (p: Parser<'a,'u>) =
  519. fun state ->
  520. let mutable reply = p state
  521. if reply.Status = Ok then
  522. let mutable xs = fold1 reply.Result
  523. let mutable error = reply.Error
  524. let mutable state = reply.State
  525. reply <- p state
  526. while reply.Status = Ok do
  527. if referenceEquals reply.State state then
  528. _raiseInfiniteLoopException "many" state
  529. xs <- fold xs reply.Result
  530. error <- reply.Error
  531. state <- reply.State
  532. reply <- p state
  533. if reply.Status = Error && reply.State == state then
  534. Reply(Ok, applyF xs, mergeErrors error reply.Error, state)
  535. else
  536. let error = mergeErrorsIfNeeded state error reply.State reply.Error
  537. Reply(reply.Status, error, reply.State)
  538. elif not require1 && reply.Status = Error && reply.State == state then
  539. Reply(Ok, getEmpty(), reply.Error, state)
  540. else
  541. Reply(reply.Status, reply.Error, reply.State)
  542. let
  543. #if NOINLINE
  544. #else
  545. inline
  546. #endif
  547. private manyFoldApply2Impl require1 fold1 fold applyF getEmpty (p1: Parser<'a,'u>) (p: Parser<'b,'u>) =
  548. fun state ->
  549. let reply1 = p1 state
  550. if reply1.Status = Ok then
  551. let mutable xs = fold1 reply1.Result
  552. let mutable error = reply1.Error
  553. let mutable state = reply1.State
  554. let mutable reply = p state
  555. while reply.Status = Ok do
  556. if referenceEquals reply.State state then
  557. _raiseInfiniteLoopException "many" state
  558. xs <- fold xs reply.Result
  559. error <- reply.Error
  560. state <- reply.State
  561. reply <- p state
  562. if reply.Status = Error && reply.State == state then
  563. Reply(Ok, applyF xs, mergeErrors error reply.Error, state)
  564. else
  565. let error = mergeErrorsIfNeeded state error reply.State reply.Error
  566. Reply(reply.Status, error, reply.State)
  567. elif not require1 && reply1.Status = Error && reply1.State == state then
  568. Reply(Ok, getEmpty(), reply1.Error, state)
  569. else
  570. Reply(reply1.Status, reply1.Error, reply1.State)
  571. let
  572. #if NOINLINE
  573. #else
  574. inline
  575. #endif
  576. manyFoldApply fold1 fold applyF getEmpty p =
  577. manyFoldApplyImpl false fold1 fold applyF getEmpty p
  578. let
  579. #if NOINLINE
  580. #else
  581. inline
  582. #endif
  583. many1FoldApply fold1 fold applyF p =
  584. manyFoldApplyImpl true fold1 fold applyF (fun () -> Unchecked.defaultof<_>) p
  585. let
  586. #if NOINLINE
  587. #else
  588. inline
  589. #endif
  590. manyFoldApply2 fold1 fold applyF getEmpty p1 p =
  591. manyFoldApply2Impl false fold1 fold applyF getEmpty p1 p
  592. let
  593. #if NOINLINE
  594. #else
  595. inline
  596. #endif
  597. many1FoldApply2 fold1 fold applyF p1 p =
  598. manyFoldApply2Impl true fold1 fold applyF (fun () -> Unchecked.defaultof<_>) p1 p
  599. // it's the sepMayEnd case that's difficult to implement (efficiently) without a specialized parser
  600. let
  601. #if NOINLINE
  602. #else
  603. inline
  604. #endif
  605. sepEndByFoldApplyImpl require1 sepMayEnd fold1 fold applyF getEmpty (p: Parser<'a,'u>) (sep: Parser<'b,'u>) =
  606. fun state ->
  607. let mutable reply1 = p state
  608. if reply1.Status = Ok then
  609. let mutable xs = fold1 reply1.Result
  610. let mutable error = reply1.Error
  611. let mutable state = reply1.State
  612. let mutable reply2 = sep state
  613. while reply2.Status = Ok && (reply1 <- p reply2.State; reply1.Status = Ok) do
  614. xs <- fold xs reply1.Result
  615. if not (referenceEquals reply1.State reply2.State) then
  616. error <- reply1.Error
  617. elif not (referenceEquals reply1.State state) then
  618. error <- mergeErrors reply2.Error reply1.Error
  619. else
  620. _raiseInfiniteLoopException "sep(EndBy)" state
  621. state <- reply1.State
  622. reply2 <- sep state
  623. if reply2.Status = Error && reply2.State == state then
  624. Reply(Ok, applyF xs, mergeErrors error reply2.Error, state)
  625. elif sepMayEnd && reply1.Status = Error && reply1.State == reply2.State then
  626. let error = mergeErrors (mergeErrorsIfNeeded state error reply2.State reply2.Error) reply1.Error
  627. Reply(Ok, applyF xs, error, reply1.State)
  628. elif reply1.Status <> Ok then
  629. let error = mergeErrorsIfNeeded3 state error reply2.State reply2.Error reply1.State reply1.Error
  630. Reply(reply1.Status, error, reply1.State)
  631. else
  632. let error = mergeErrorsIfNeeded state error reply2.State reply2.Error
  633. Reply(reply2.Status, error, reply2.State)
  634. elif not require1 && reply1.Status = Error && reply1.State == state then
  635. Reply(Ok, getEmpty(), reply1.Error, state)
  636. else
  637. Reply(reply1.Status, reply1.Error, reply1.State)
  638. let
  639. #if NOINLINE
  640. #else
  641. inline
  642. #endif
  643. sepByFoldApply fold1 fold applyF getEmpty p sep =
  644. sepEndByFoldApplyImpl false false fold1 fold applyF getEmpty p sep
  645. let
  646. #if NOINLINE
  647. #else
  648. inline
  649. #endif
  650. sepBy1FoldApply fold1 fold applyF p sep =
  651. sepEndByFoldApplyImpl true false fold1 fold applyF (fun () -> Unchecked.defaultof<_>) p sep
  652. let
  653. #if NOINLINE
  654. #else
  655. inline
  656. #endif
  657. sepEndByFoldApply fold1 fold applyF getEmpty p sep =
  658. sepEndByFoldApplyImpl false true fold1 fold applyF getEmpty p sep
  659. let
  660. #if NOINLINE
  661. #else
  662. inline
  663. #endif
  664. sepEndBy1FoldApply fold1 fold applyF p sep =
  665. sepEndByFoldApplyImpl true true fold1 fold applyF (fun () -> Unchecked.defaultof<_>) p sep
  666. let
  667. #if NOINLINE
  668. #else
  669. inline
  670. #endif
  671. manyTillFoldApply fold1 fold applyF getEmpty (p: Parser<'a,'u>) (endp: Parser<'c,'u>) =
  672. fun state ->
  673. let mutable reply2 = endp state
  674. if reply2.Status <> Ok then
  675. let mutable reply1 = p state
  676. if reply1.Status = Ok then
  677. let mutable xs = fold1 reply1.Result
  678. let mutable error = reply1.Error
  679. let mutable state = reply1.State
  680. reply2 <- endp state
  681. while reply2.Status <> Ok && (reply1 <- p state; reply1.Status = Ok) do
  682. if referenceEquals reply1.State state then
  683. _raiseInfiniteLoopException "manyTill" state
  684. xs <- fold xs reply1.Result
  685. error <- reply1.Error
  686. state <- reply1.State
  687. reply2 <- endp state
  688. if reply2.Status = Ok then
  689. let error = mergeErrorsIfNeeded state error reply2.State reply2.Error
  690. Reply(Ok, applyF xs reply2.Result, error, reply2.State)
  691. elif reply1.Status = Error && reply1.State == state then
  692. let error = if reply2.State != state then reply2.Error
  693. else mergeErrors (mergeErrors error reply1.Error) reply2.Error
  694. Reply(reply2.Status, error, reply2.State)
  695. else
  696. let error = mergeErrorsIfNeeded state error reply1.State reply1.Error
  697. Reply(reply1.Status, error, reply1.State)
  698. elif reply1.Status = Error && reply1.State == state then
  699. let error = if reply2.State != state then reply2.Error
  700. else mergeErrors reply1.Error reply2.Error
  701. Reply(reply2.Status, error, reply2.State)
  702. else
  703. Reply(reply1.Status, reply1.Error, reply1.State)
  704. else
  705. Reply(Ok, getEmpty reply2.Result, reply2.Error, reply2.State)
  706. let many p = manyFoldApply (fun x -> [x]) (fun xs x -> x::xs) List.rev (fun () -> []) p
  707. let manyRev p = manyFoldApply (fun x -> [x]) (fun xs x -> x::xs) (fun xs -> xs) (fun () -> []) p
  708. let skipMany p = manyFoldApply (fun _ -> ()) (fun _ _ -> ()) (fun xs -> xs) (fun () -> ()) p
  709. let manyFold acc0 f p = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  710. manyFoldApply (fun x -> optF.Invoke(acc0, x)) (fun acc x -> optF.Invoke(acc, x)) (fun acc -> acc) (fun () -> acc0) p
  711. let manyReduce f altX p = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  712. manyFoldApply (fun x0 -> x0) (fun x0 x -> optF.Invoke(x0, x)) (fun x0 -> x0) (fun () -> altX) p
  713. let many1 p = many1FoldApply (fun x -> [x]) (fun xs x -> x::xs) List.rev p
  714. let many1Rev p = many1FoldApply (fun x -> [x]) (fun xs x -> x::xs) (fun xs -> xs) p
  715. let skipMany1 p = many1FoldApply (fun _ -> ()) (fun _ _ -> ()) (fun xs -> xs) p
  716. let many1Fold acc0 f p = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  717. many1FoldApply (fun x -> optF.Invoke(acc0, x)) (fun acc x -> optF.Invoke(acc, x)) (fun x -> x) p
  718. let many1Reduce f p = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  719. many1FoldApply (fun x0 -> x0) (fun x0 x -> optF.Invoke(x0, x)) (fun x0 -> x0) p
  720. let sepBy p sep = sepByFoldApply (fun x -> [x]) (fun xs x -> x::xs) List.rev (fun () -> []) p sep
  721. let sepByRev p sep = sepByFoldApply (fun x -> [x]) (fun xs x -> x::xs) (fun xs -> xs) (fun () -> []) p sep
  722. let skipSepBy p sep = sepByFoldApply (fun _ -> ()) (fun _ _ -> ()) (fun xs -> xs) (fun _ -> ()) p sep
  723. let sepByFold acc0 f p sep = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  724. sepByFoldApply (fun x -> optF.Invoke(acc0, x)) (fun acc x -> optF.Invoke(acc, x)) (fun acc -> acc) (fun () -> acc0) p sep
  725. let sepByReduce f altX p sep = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  726. sepByFoldApply (fun x0 -> x0) (fun x0 x -> optF.Invoke(x0, x)) (fun x0 -> x0) (fun () -> altX) p sep
  727. let sepBy1 p sep = sepBy1FoldApply (fun x -> [x]) (fun xs x -> x::xs) List.rev p sep
  728. let sepBy1Rev p sep = sepBy1FoldApply (fun x -> [x]) (fun xs x -> x::xs) (fun xs -> xs) p sep
  729. let skipSepBy1 p sep = sepBy1FoldApply (fun _ -> ()) (fun _ _ -> ()) (fun xs -> xs) p sep
  730. let sepBy1Fold acc0 f p sep = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  731. sepBy1FoldApply (fun x -> optF.Invoke(acc0, x)) (fun acc x -> optF.Invoke(acc, x)) (fun acc -> acc) p sep
  732. let sepBy1Reduce f p sep = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  733. sepBy1FoldApply (fun x0 -> x0) (fun x0 x -> optF.Invoke(x0, x)) (fun x0 -> x0) p sep
  734. let sepEndBy p sep = sepEndByFoldApply(fun x -> [x]) (fun xs x -> x::xs) List.rev (fun () -> []) p sep
  735. let sepEndByRev p sep = sepEndByFoldApply(fun x -> [x]) (fun xs x -> x::xs) (fun xs -> xs) (fun () -> []) p sep
  736. let skipSepEndBy p sep = sepEndByFoldApply(fun _ -> ()) (fun _ _ -> ()) (fun xs -> xs) (fun _ -> ()) p sep
  737. let sepEndByFold acc0 f p sep = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  738. sepEndByFoldApply (fun x -> optF.Invoke(acc0, x)) (fun acc x -> optF.Invoke(acc, x)) (fun acc -> acc) (fun () -> acc0) p sep
  739. let sepEndByReduce f altX p sep = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  740. sepEndByFoldApply (fun x0 -> x0) (fun x0 x -> optF.Invoke(x0, x)) (fun x0 -> x0) (fun () -> altX) p sep
  741. let sepEndBy1 p sep = sepEndBy1FoldApply (fun x -> [x]) (fun xs x -> x::xs) List.rev p sep
  742. let sepEndBy1Rev p sep = sepEndBy1FoldApply (fun x -> [x]) (fun xs x -> x::xs) (fun xs -> xs) p sep
  743. let skipSepEndBy1 p sep = sepEndBy1FoldApply (fun _ -> ()) (fun _ _ -> ()) (fun xs -> xs) p sep
  744. let sepEndBy1Fold acc0 f p sep = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  745. sepEndBy1FoldApply (fun x -> optF.Invoke(acc0, x)) (fun acc x -> optF.Invoke(acc, x)) (fun acc -> acc) p sep
  746. let sepEndBy1Reduce f p sep = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  747. sepEndBy1FoldApply (fun x0 -> x0) (fun x0 x -> optF.Invoke(x0, x)) (fun x0 -> x0) p sep
  748. let manyTill p endp = manyTillFoldApply (fun x -> [x]) (fun xs x -> x::xs) (fun xs _ -> List.rev xs) (fun _ -> []) p endp
  749. let manyTillRev p endp = manyTillFoldApply (fun x -> [x]) (fun xs x -> x::xs) (fun xs _ -> xs) (fun _ -> []) p endp
  750. let skipManyTill p endp = manyTillFoldApply (fun _ -> ()) (fun _ _ -> ()) (fun _ _ -> ()) (fun _ -> ()) p endp
  751. let manyTillFold acc0 f p endp = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  752. manyTillFoldApply (fun x -> optF.Invoke(acc0, x)) (fun acc x -> optF.Invoke(acc, x)) (fun acc _ -> acc) (fun _ -> acc0) p endp
  753. let manyTillReduce f altX p endp = let optF = OptimizedClosures.FSharpFunc<_,_,_>.Adapt(f)
  754. manyTillFoldApply (fun x0 -> x0) (fun x0 x -> optF.Invoke(x0, x)) (fun x0 _ -> x0) (fun _ -> altX) p endp
  755. let chainl1 p op =
  756. many1FoldApply2 (fun x0 -> x0) (fun x (f, y) -> f x y) (fun x -> x) p (tuple2 op p)
  757. let chainl p op altX =
  758. manyFoldApply2 (fun x0 -> x0) (fun x (f, y) -> f x y) (fun x -> x) (fun () -> altX) p (tuple2 op p)
  759. let chainr1 p op =
  760. pipe2 p (manyRev (tuple2 op p)) (fun x0 opYs -> match opYs with
  761. | [] -> x0
  762. | (op, y)::tl ->
  763. let rec calc op1 y lst =
  764. match lst with
  765. | (op2, x)::tl -> calc op2 (op1 x y) tl
  766. | [] -> op1 x0 y
  767. calc op y tl)
  768. let chainr p op x = chainr1 p op <|>% x
  769. // ------------------------------
  770. // Computation expression syntax
  771. // ------------------------------
  772. [<Sealed>]
  773. type ParserCombinator() =
  774. member t.Delay(f:(unit -> Parser<'a,'u>)) = fun state -> (f ()) state
  775. member t.Return(x) = preturn x
  776. member t.Bind(p, f) = p >>= f
  777. member t.Zero() : Parser<'a,'u> = pzero
  778. // no Combine member by purpose
  779. member t.TryWith(p:Parser<'a,'u>, cf:(exn -> Parser<'a,'u>)) =
  780. fun state ->
  781. (try p state with e -> (cf e) state)
  782. member t.TryFinally(p:Parser<'a,'u>, ff:(unit -> unit)) =
  783. fun state ->
  784. try p state finally ff ()
  785. let parse = ParserCombinator()
  786. // ----------------------
  787. // Other helper functions
  788. // ----------------------
  789. let createParserForwardedToRef() =
  790. let dummyParser = fun state -> failwith "a parser was not initialized"
  791. let r = ref dummyParser
  792. (fun state -> !r state), r : Parser<_,'u> * Parser<_,'u> ref