let p_string delim =
parser
- [<_ = node delim; xs = many in_string; _ = node delim>] ->
- string @@ implode xs
+ [<n = node delim; xs = many in_string; _ = node delim>] ->
+ {n with
+ Node.value = Genlex.String (ExtString.String.implode @@ List.map Node.value xs)}
| [<>] ->
fail ()
}
val scheme' : laungage
-val lexer : laungage -> char Node.t Stream.t -> token Node.t Stream.t
+val lexer : laungage -> char Node.t Stream.t -> t Stream.t
{node with
value = f x}
-
let concat f =
function
(x::_) as xs ->
| [] ->
empty (f [])
+let to_string show {value=value;filename=filename; lineno=lineno} =
+ Printf.sprintf "{value=%s; filename=%s; lineno=%d}\n"
+ (show value) filename lineno
val lift : ('a -> 'b) -> 'a t -> 'b t
val concat : ('a list -> 'b) -> 'a t list -> 'b t
+val to_string : ('a -> string) -> 'a t -> string
+
(* lisp parser *)
open Base
type lisp =
- Int of int
- | String of string
+ Int of int
+ | String of string
| Float of float
| Bool of bool
| Symbol of string
| List of lisp list
+type t =
+ Int_ of int Node.t
+ | String_ of string Node.t
+ | Float_ of float Node.t
+ | Bool_ of bool Node.t
+ | Symbol_ of string Node.t
+ | List_ of t list Node.t
+
+
let rec to_string =
function
- Int n ->
- string_of_int n
- | String s ->
- Printf.sprintf "\"%s\"" s
- | Float d ->
- string_of_float d
- | Symbol s ->
- s
- | Bool b ->
- if b then "#t" else "#f"
- | List xs ->
- let s =
- String.concat " " @@ List.map to_string xs in
- Printf.sprintf "(%s)" s
+ Int_ node ->
+ Node.to_string string_of_int node
+ | String_ node ->
+ Node.to_string (Printf.sprintf "\"%s\"") node
+ | Float_ node ->
+ Node.to_string string_of_float node
+ | Symbol_ node ->
+ Node.to_string id node
+ | Bool_ node ->
+ Node.to_string (fun b -> if b then "#t" else "#f") node
+ | List_ node ->
+ let f xs =
+ let s = String.concat " " @@ List.map to_string xs in
+ Printf.sprintf "(%s)" s in
+ Node.to_string f node
let rec read =
parser
let parse_string string =
parse @@ Stream.of_string string
+
+let rec read_node =
+ parser
+ [<'{Node.value = Genlex.String s} as node>] ->
+ String_ {node with Node.value = s}
+ | [<'{Node.value = Genlex.Ident name} as node>] ->
+ Symbol_ {node with Node.value = name}
+ | [<'{Node.value = Genlex.Int n} as node >] ->
+ Int_ {node with Node.value = n}
+ | [<'{Node.value = Genlex.Float x} as node>] ->
+ Float_ {node with Node.value = x}
+ | [<'{Node.value = Genlex.Kwd "true"} as node>] ->
+ Bool_ {node with Node.value = true}
+ | [<'{Node.value=Genlex.Kwd "false"} as node >] ->
+ Bool_ {node with Node.value = false}
+ | [<'{Node.value=Genlex.Kwd "("} as node;
+ c = Parsec.many read_node;
+ '{Node.value = Genlex.Kwd ")"} >] ->
+ List_ {node with Node.value = c}
+ | [<'{Node.value=Genlex.Kwd "["} as node;
+ c = Parsec.many read_node;
+ '{Node.value=Genlex.Kwd "]"} >] ->
+ List_ {node with Node.value = c}
+ | [<'{Node.value=Genlex.Kwd "'"} as node; c = Parsec.many read_node >] ->
+ let quote =
+ Symbol_ {node with Node.value= "quote"} in
+ List_ {node with Node.value = quote::c}
+
+let of_stream stream =
+ let lexer =
+ Lexer.lexer Lexer.scheme' in
+ Parsec.many read_node @@ lexer stream
+
+let of_string string =
+ of_stream @@ Node.of_string string
type lisp = Int of int | String of string | Float of float | Bool of bool | Symbol of string | List of lisp list
-val to_string : lisp -> string
+
val parse : char Stream.t -> lisp list
val parse_string : string -> lisp list
+
+type t =
+ Int_ of int Node.t
+ | String_ of string Node.t
+ | Float_ of float Node.t
+ | Bool_ of bool Node.t
+ | Symbol_ of string Node.t
+ | List_ of t list Node.t
+
+val of_stream : char Node.t Stream.t -> t list
+val of_string : string -> t list
+val to_string : t -> string
let _ =
("lex module test" >::: [
+ "multiline" >::
+ (fun () ->
+ let s =
+ lexer "x\ny" in
+ ok (node (Ident "x")) @@ Stream.next s;
+ ok {(node (Ident "y")) with Node.lineno=1} @@ Stream.next s);
"symbol" >::
(fun () ->
ok (node (Ident "+")) @@ Stream.next (lexer "+");
"dot" >::
(fun () ->
ok (node (Ident ".")) @@ Stream.next (lexer "."));
+ "string" >::
+ (fun () ->
+ ok (node (String "")) @@ Stream.next (lexer "\"\"");
+ ok (node (String "xyz")) @@ Stream.next (lexer "\"xyz\""));
"bool" >::
(fun () ->
ok (node (Kwd "true")) @@ Stream.next (lexer "#t");
let ok sexp str =
let sexp' =
- parse_string str in
+ of_string str in
OUnit.assert_equal
~printer:(String.concat ";\n" $ List.map Sexp.to_string)
sexp
sexp'
+let node x =
+ {Node.value = x; filename = "<string>"; lineno = 0}
+
let _ =
("S expression module test" >::: [
+ "multi line" >::
+ (fun () ->
+ ok [Int_ (node 42);
+ Int_ {(node 10) with Node.lineno=1}] "42\n10");
"empty" >::
(fun () ->
ok [] "";
ok [] "; foo bar");
"int" >::
(fun () ->
- ok [(Int 42)] "42";
- ok [(Int ~-42)] "-42");
+ ok [Int_ (node 42)] "42";
+ ok [Int_ (node ~-42)] "-42");
"bool" >::
(fun () ->
- ok [(Bool true)] "#t";
- ok [(Bool false)] "#f");
+ ok [Bool_ (node true)] "#t";
+ ok [Bool_ (node false)] "#f");
"float" >::
(fun () ->
- ok [(Float 42.)] "42.";
- ok [(Float 42.5)] "42.5");
+ ok [Float_ (node 42.)] "42.";
+ ok [Float_ (node 42.5)] "42.5");
"string" >::
(fun () ->
- ok [(String "")] "\"\"";
- ok [(String "foo")] "\"foo\"";
- ok [(String "foo\"x")] "\"foo\\\"x\"";
- ok [(String "foo\"")] "\"foo\\\"\"");
+ ok [String_ (node "")] "\"\"";
+ ok [String_ (node "foo")] "\"foo\"";
+ ok [String_ (node "foo\"x")] "\"foo\\\"x\"";
+ ok [String_ (node "foo\"")] "\"foo\\\"\"");
"symbol" >::
(fun () ->
- ok [(String "foo")] "\"foo\"";
- ok [(String "+")] "\"+\"";
- ok [(Symbol ".")] ".");
+ ok [String_ (node "foo")] "\"foo\"";
+ ok [String_ (node "+")] "\"+\"";
+ ok [Symbol_ (node ".")] ".");
"+" >::
(fun () ->
- ok [List [Symbol "+";Int 1; Int 2]] "(+ 1 2)");
+ ok [List_ (node [Symbol_ (node "+");
+ Int_ (node 1);
+ Int_ (node 2)])] "(+ 1 2)");
"call" >::
(fun () ->
- ok [List [Symbol "print";String "hello"]] "(print \"hello\")");
+ ok [List_ (node [Symbol_ (node "print");
+ String_ (node "hello")])] "(print \"hello\")");
"bracket" >::
(fun () ->
- ok [List [Symbol "print";String "hello"]] "[print \"hello\"]");
+ ok [List_ (node [Symbol_ (node "print");
+ String_ (node "hello")])] "[print \"hello\"]");
"quote" >::
(fun () ->
- ok [List [Symbol "quote";Symbol "hello"]] "(quote hello)";
- ok [List [Symbol "quote";Symbol "hello"]] "'hello")
+ ok [List_ (node [Symbol_ (node "quote");
+ Symbol_ (node "hello")])] "(quote hello)";
+ ok [List_ (node [Symbol_ (node "quote");
+ Symbol_ (node "hello")])] "'hello")
]) +> run_test_tt