You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

232 lines
5.5 KiB

4 years ago
  1. open import "prelude.ml"
  2. open import "./monads.ml"
  3. private type consumed = C | E
  4. private type error = Unexpected of string * list string
  5. instance show error begin
  6. let show = function
  7. | Unexpected (s, []) -> s
  8. | Unexpected (s, ms) ->
  9. "Unexpected " ^ s ^ "\n"
  10. ^ "Expecting one of " ^ foldl (^) "" ms
  11. end
  12. private type result 'a =
  13. | Ok of consumed * 'a * string
  14. | Err of consumed * error * string
  15. let join_consumed x y =
  16. match x with
  17. | C -> C
  18. | E -> y
  19. type parser_t 'm 'a = private P of string -> 'm (result 'a)
  20. type parser <- parser_t identity
  21. instance functor 'm => functor (parser_t 'm) begin
  22. let f <$> P x = P @@ fun i ->
  23. flip map (x i) @@ fun p ->
  24. match p with
  25. | Ok (c, x, i) -> Ok (c, f x, i)
  26. | Err e -> Err e
  27. end
  28. instance monad 'm => applicative (parser_t 'm) begin
  29. let pure x = P (fun s -> pure (Ok (E, x, s)))
  30. let P f <*> P x = P @@ fun s ->
  31. let! f = f s
  32. match f with
  33. | Ok (c, f, s) ->
  34. let! x = x s
  35. match x with
  36. | Ok (c', x, s) -> pure @@ Ok (join_consumed c c', f x, s)
  37. | Err (c', p) -> pure @@ Err (join_consumed c c', p)
  38. | Err e -> pure @@ Err e
  39. end
  40. let x *> y = (fun _ x -> x) <$> x <*> y
  41. let x <* y = (| const x y |)
  42. instance monad 'm => monad (parser_t 'm) begin
  43. let P x >>= f = P @@ fun s ->
  44. let! x = x s
  45. match x with
  46. | Ok (c, x, s) ->
  47. let P kont = f x
  48. let! x = kont s
  49. match x with
  50. | Ok (c', x, s) -> pure @@ Ok (join_consumed c c', x, s)
  51. | Err (c', p) -> pure @@ Err (join_consumed c c', p)
  52. | Err e -> pure @@ Err e
  53. end
  54. let private fail e = P (fun s -> pure (Err (E, e, s)))
  55. let empty : forall 'm 'a. monad 'm => parser_t 'm 'a =
  56. fail (Unexpected ("empty parse", []))
  57. let unexpected e =
  58. fail (Unexpected (e, []))
  59. let alt_err (Unexpected (u, xs)) (Unexpected (_, ys)) =
  60. Unexpected (u, xs ++ ys)
  61. let P x <|> P y = P @@ fun s ->
  62. let! x = x s
  63. match x with
  64. | Ok x -> pure (Ok x)
  65. | Err (c, m, s) ->
  66. let! y = y s
  67. match y with
  68. | Ok (c', x, s) -> pure (Ok (join_consumed c c', x, s))
  69. | Err (c', m', s) -> pure (Err (join_consumed c c', alt_err m m', s))
  70. let P x <+> y = P @@ fun s ->
  71. let! x = x s
  72. match x with
  73. | Ok x -> pure (Ok x)
  74. | Err (c, m, s) ->
  75. let P y = force y
  76. let! y = y s
  77. match y with
  78. | Ok (c', x, s) -> pure (Ok (join_consumed c c', x, s))
  79. | Err (c', m', s) -> pure (Err (join_consumed c c', alt_err m m', s))
  80. private module S = import "lua/string.ml"
  81. let char : forall 'm. applicative 'm => parser_t 'm string =
  82. P @@ fun s ->
  83. let x = S.substring s 1 1
  84. if x <> "" then
  85. let r = S.substring s 2 (S.length s)
  86. pure @@ Ok (C, x, r)
  87. else
  88. pure @@ Err (E, Unexpected ("end-of-file", ["character"]), s)
  89. let eof : forall 'm. applicative 'm => parser_t 'm () =
  90. P @@ fun s ->
  91. if s == "" then
  92. pure @@ Ok (E, (), s)
  93. else
  94. pure @@ Err (E, Unexpected (S.substring s 1 1, ["end-of-file"]), s)
  95. let satisfy p = P @@ fun s ->
  96. let x = S.substring s 1 1
  97. if x <> "" && p x then
  98. pure @@ Ok (C, x, S.substring s 2 (S.length s))
  99. else
  100. let m =
  101. if x == "" then
  102. "end of file"
  103. else x
  104. pure @@ Err (E, Unexpected (m, ["character"]), s)
  105. let P k <?> m = P @@ fun s ->
  106. let! x = k s
  107. match x with
  108. | Ok e -> pure (Ok e)
  109. | Err (c, Unexpected (u, _), s) -> pure (Err (c, Unexpected (u, [m]), s))
  110. let many_fold k z (P x) =
  111. let rec go consumed kont s =
  112. let! x = x s
  113. match x with
  114. | Err ((c, _, s) as p) ->
  115. match c with
  116. | C -> pure (Err p)
  117. | E -> kont consumed z s
  118. | Ok (c, x, s) ->
  119. match c with
  120. | E -> error @@ "many: got parser that accepts the empty string"
  121. | C -> go C (fun c -> kont c # k x) s
  122. P (go E (fun c z s -> pure (Ok (c, z, s))))
  123. let many p = many_fold (::) [] p
  124. let some p =
  125. let! x = p
  126. (x ::) <$> many p
  127. let sep_by_1 sep p =
  128. let! x = p
  129. let! xs = many (sep *> p)
  130. pure (x :: xs)
  131. let sep_by sep p = sep_by_1 sep p <|> pure []
  132. external private val is_infix_of : string -> string -> bool =
  133. "function(s, s2) return s2:find(s) ~= nil end"
  134. external private val is_prefix_of : string -> string -> bool =
  135. "function(s, s2) return (s2:find(s)) == 1 end"
  136. let one_of chs =
  137. let len = S.length chs
  138. let rec loop ch i =
  139. if i > len then
  140. fail @@ Unexpected (ch, ["one of \"" ^ chs ^ "\""])
  141. else if ch == S.substring chs i i then
  142. pure ch
  143. else
  144. loop ch (i + 1)
  145. let! ch = char
  146. loop ch 1
  147. let symbol str =
  148. let len = S.length str
  149. let rec loop acc i =
  150. if i > len then
  151. pure acc
  152. else
  153. let! c = char <?> S.substring str i i
  154. if c == S.substring str i i then
  155. loop (acc ^ c) (i + 1)
  156. else
  157. fail @@ Unexpected (acc ^ c, [S.substring str 1 i])
  158. loop "" 1
  159. let between o c p =
  160. let! _ = o
  161. let! x = p
  162. let! _ = c
  163. pure x
  164. let try (P x) = P @@ fun s ->
  165. let! x = x s
  166. match x with
  167. | Ok c -> pure (Ok c)
  168. | Err (_, p, _) -> pure (Err (E, p, s))
  169. let optionally p = map Some (try p) <|> pure None
  170. let rec sep_end_by_1 sep p =
  171. let! x = p
  172. ( let! _ = sep
  173. let! xs = sep_end_by sep p
  174. pure (x :: xs)
  175. ) <|> pure [x]
  176. and sep_end_by sep p =
  177. sep_end_by_1 sep p <|> pure []
  178. let parse (P x) s =
  179. let! x = x s
  180. match x with
  181. | Ok (_, x, r) -> pure @@ Right (x, r)
  182. | Err (_, m, _) -> pure @@ Left m
  183. let run_parser p s =
  184. let Id x = parse p s
  185. x
  186. let run_parser' (P x) s =
  187. let Id x = x s
  188. x
  189. let lift m = P @@ fun s ->
  190. let! x = m
  191. pure @@ Ok (E, x, s)
  192. let morph (k : forall 'a. 'm 'a -> 'n 'a) (P x) = P @@ fun s -> k (x s)
  193. let void x = map (const ()) x