open Base
open Parsec
+let kwd =
+ Node.lift (fun x -> Genlex.Kwd x)
+
+let ident =
+ Node.lift (fun x -> Genlex.Ident x)
+
let parse_keyword keywords stream =
let parse =
HList.fold_left1 (<|>) @@ List.map string keywords in
Genlex.Kwd (ExtString.String.implode @@ parse stream)
+let keyword keywords stream =
+ let parse =
+ HList.fold_left1 (<|>) @@ List.map NodeS.string keywords in
+ kwd (Node.lift ExtString.String.implode @@ parse stream)
+
let parse_comment start stream =
ignore @@ string start stream;
ignore @@ until '\n' stream;
Stream.junk stream
+let comment start stream =
+ ignore @@ NodeS.string start stream;
+ ignore @@ untilBy (fun {Node.value=c} -> c = '\n') stream;
+ Stream.junk stream
+
let parse_space =
ignore $ one_of " \t\n\r"
+let space =
+ ignore $ NodeS.one_of " \t\n\r"
+
let parse_ident head tail =
let head =
alpha <|> one_of head in
[< x = head; xs = many tail>] ->
Genlex.Ident (ExtString.String.implode @@ x::xs)
+let p_ident head tail =
+ let head =
+ NodeS.alpha <|> NodeS.one_of head in
+ let tail =
+ head <|> NodeS.digit <|> NodeS.one_of tail in
+ parser
+ [< x = head; xs = many tail>] ->
+ ident @@ Node.concat ExtString.String.implode @@ x::xs
+
+let p_char =
+ let escaped =
+ List.map (fun c -> ((Char.escaped c).[1],c)) ['\n'; '\t'] in
+ parser [<'c; stream >] ->
+ if c.Node.value = '\\' then
+ let {Node.value = x} as node =
+ Stream.next stream in
+ try
+ {node with
+ Node.value = List.assoc x escaped}
+ with Not_found ->
+ node
+ else
+ c
+
let parse_char =
let escaped =
List.map (fun c -> ((Char.escaped c).[1],c)) ['\n'; '\t'] in
else
c
+
let string_content stream =
match Stream.peek stream with
Some '"' ->
let test f s =
let stream =
- Stream.of_string s in
+ Node.of_string s in
let result =
try
Some (f stream)
with _ ->
None in
- Stream.dump (print_char) stream;
+ Stream.iter (fun {Node.value=v} -> print_char v) stream;
result
| _ ->
[]
+let rec untilBy f stream =
+ match Stream.peek stream with
+ Some x when not (f x) ->
+ Stream.junk stream;
+ x::(untilBy f stream)
+ | _ ->
+ []
+
let option f stream =
try
Some (f stream)
fail ()
end
-module Char = Parser(
+module CharS = Parser(
struct
type t = char
type s = char list
let shrink = id
end)
-module N = Node
-module Node = Parser(
+module NodeS = Parser(
struct
- type t = char N.t
- type s = char list N.t
+ type t = char Node.t
+ type s = char list Node.t
let npeek n stream =
- List.map N.value @@ Stream.npeek n stream
+ List.map Node.value @@ Stream.npeek n stream
let peek stream =
- sure N.value @@ Stream.peek stream
+ sure Node.value @@ Stream.peek stream
let junk =
Stream.junk
let next =
let shrink =
function
(x::_) as xs ->
- {x with N.value = List.map N.value xs}
+ {x with Node.value = List.map Node.value xs}
| [] ->
fail ()
end)
(* obsolute *)
let string =
- Char.string
+ CharS.string
let one_of =
- Char.one_of
+ CharS.one_of
let alpha =
- Char.alpha
+ CharS.alpha
let digit =
- Char.digit
+ CharS.digit
val many : ('a Stream.t -> 'b) -> 'a Stream.t -> 'b list
val many1 : ('a Stream.t -> 'b) -> 'a Stream.t -> 'b list
val until : 'a -> 'a Stream.t -> 'a list
+val untilBy : ('a -> bool) -> 'a Stream.t -> 'a list
val char : 'a -> 'a Stream.t -> 'a
val string : string -> char Stream.t -> char list
val alpha : char Stream.t -> char
val digit : char Stream.t -> char
+module CharS :
+ sig
+ val string : string -> char Stream.t -> char list
+ val one_of : string -> char Stream.t -> char
+ val alpha : char Stream.t -> char
+ val digit : char Stream.t -> char
+ end
+
+module NodeS :
+ sig
+ val string : string -> char Node.t Stream.t -> char list Node.t
+ val one_of : string -> char Node.t Stream.t -> char Node.t
+ val alpha : char Node.t Stream.t -> char Node.t
+ val digit : char Node.t Stream.t -> char Node.t
+ end