Skip to content

Commit d934974

Browse files
committed
[ util ] tidy up pp_sexp
1 parent e4fae8b commit d934974

File tree

3 files changed

+58
-115
lines changed

3 files changed

+58
-115
lines changed

util/pp_sexp/pp_sexp.ml

+21-115
Original file line numberDiff line numberDiff line change
@@ -1,121 +1,26 @@
1-
module Sexp = struct
2-
3-
let is_unquoted_atom_char = function
4-
| 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '-' | '_' ->
5-
true
6-
| _ ->
7-
false
8-
(*
9-
let fold_sexp atom list input =
10-
let scan_unquoted_atom start =
11-
let rec scan i =
12-
if i = String.length input then
13-
i, String.sub input start (i - start)
14-
else
15-
if is_unquoted_atom_char input.[i] then
16-
scan (i+1)
17-
else
18-
i, String.sub input start (i - start)
19-
in
20-
scan start
21-
in
22-
let scan_quoted_atom start =
23-
let b = Buffer.create 128 in
24-
let rec scan i =
25-
if i = String.length input then
26-
failwith "unexpected end of input during quoted atom"
27-
else
28-
match input.[i] with
29-
| '"' ->
30-
i+1, Buffer.contents b
31-
| '\\' ->
32-
(if i + 1 = String.length input then
33-
failwith "unexpected end of input during quoted atom"
34-
else
35-
match input.[i+1] with
36-
| 'n' -> Buffer.add_char b '\n'; scan (i+2)
37-
| 't' -> Buffer.add_char b '\t'; scan (i+2)
38-
| '\\' -> Buffer.add_char b '\\'; scan (i+2)
39-
| '"' -> Buffer.add_char b '"'; scan (i+2)
40-
| _ -> failwith "invalid escape character")
41-
| c ->
42-
Buffer.add_char b c; scan (i+1)
43-
in
44-
scan start
45-
in
46-
let rec scan i acc =
47-
if i = String.length input then
48-
i, List.rev acc
49-
else
50-
match input.[i] with
51-
| ' ' | '\n' | '\t' ->
52-
scan (i+1) acc
53-
| ')' ->
54-
i, List.rev acc
55-
| '(' ->
56-
(let i, items = scan (i+1) [] in
57-
if i = String.length input then
58-
failwith "unexpected end of input"
59-
else if input.[i] = ')' then
60-
scan (i+1) (list items :: acc)
61-
else
62-
failwith "expecting ')'")
63-
| c when is_unquoted_atom_char c ->
64-
let i, str = scan_unquoted_atom i in
65-
scan i (atom str :: acc)
66-
| '"' ->
67-
let i, str = scan_quoted_atom (i+1) in
68-
scan i (atom str :: acc)
69-
| _ ->
70-
failwith "unexpected character"
71-
in
72-
let i, result = scan 0 [] in
73-
if i = String.length input then
74-
result
75-
else
76-
failwith "Unexpected junk at end of input"
77-
*)
78-
end
79-
801
open Generalities
2+
open Sexp
813

82-
type sexp =
83-
| Atom of string
84-
| List of sexp list
85-
86-
(* FIXME: spans *)
87-
let of_lexbuf lexbuf =
88-
let rec scan acc =
89-
match Sexp_reader.token lexbuf with
90-
| Sexp_reader.EOF ->
91-
List.rev acc, `eof
92-
| RParen ->
93-
List.rev acc, `rparen
94-
| LParen ->
95-
(let list, terminator = scan [] in
96-
match terminator with
97-
| `eof -> failwith "Unfinished '('"
98-
| `rparen -> scan (List list :: acc))
99-
| BareAtom atom | QuotedAtom atom ->
100-
scan (Atom atom :: acc)
101-
in
102-
let sexps, terminator = scan [] in
103-
match terminator with
104-
| `eof -> sexps
105-
| `rparen -> failwith "Non-matching ')'"
4+
let is_unquoted_atom_char = function
5+
| 'A' .. 'Z' | 'a' .. 'z' | '0' .. '9' | '-' | '_' ->
6+
true
7+
| _ ->
8+
false
1069

10710
let is_bare_atom =
108-
String.for_all Sexp.is_unquoted_atom_char
11+
String.for_all is_unquoted_atom_char
10912

11013
let quote str =
11114
let b = Buffer.create 128 in
11215
Buffer.add_string b "\"";
113-
str |> String.iter (function
114-
| '"' -> Buffer.add_string b "\\\""
115-
| '\\' -> Buffer.add_string b "\\\\"
116-
| '\n' -> Buffer.add_string b "\\n"
117-
| '\t' -> Buffer.add_string b "\\t"
118-
| c -> Buffer.add_char b c);
16+
String.iter
17+
(function
18+
| '"' -> Buffer.add_string b "\\\""
19+
| '\\' -> Buffer.add_string b "\\\\"
20+
| '\n' -> Buffer.add_string b "\\n"
21+
| '\t' -> Buffer.add_string b "\\t"
22+
| c -> Buffer.add_char b c)
23+
str;
11924
Buffer.add_string b "\"";
12025
Buffer.contents b
12126

@@ -125,8 +30,9 @@ let atom str =
12530
else
12631
Pretty.text (quote str)
12732

128-
and list = function
129-
| [] -> Pretty.text "()"
33+
let list = function
34+
| [] ->
35+
Pretty.text "()"
13036
| [head] ->
13137
Pretty.(text "(" ^^ head ^^ text ")")
13238
| head :: rest ->
@@ -140,6 +46,6 @@ let rec pretty = function
14046
let () =
14147
stdin
14248
|> Lexing.from_channel
143-
|> of_lexbuf
144-
|> List.map pretty
145-
|> List.iter (fun doc -> Pretty.print doc; print_newline ())
49+
|> Sexp_reader.of_lexbuf
50+
|> Seq.map pretty
51+
|> Seq.iter (fun doc -> Pretty.print doc; print_newline ())

util/pp_sexp/sexp.ml

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
type sexp =
2+
| Atom of string
3+
| List of sexp list

util/pp_sexp/sexp_reader.mll

+34
Original file line numberDiff line numberDiff line change
@@ -29,3 +29,37 @@ and quoted_atom b = parse
2929
| '\\' '\\' { Buffer.add_char b '\\'; quoted_atom b lexbuf }
3030
| [^ '\\' '"' '\n']+ { Buffer.add_string b (Lexing.lexeme lexbuf);
3131
quoted_atom b lexbuf }
32+
33+
{
34+
35+
open Sexp
36+
37+
(* FIXME: spans *)
38+
let of_lexbuf lexbuf =
39+
let rec scan acc =
40+
match token lexbuf with
41+
| EOF ->
42+
failwith "Unexpected EOF" (* FIXME: say where the opening '(' was *)
43+
| RParen ->
44+
List.rev acc
45+
| LParen ->
46+
let list = scan [] in
47+
scan (List list :: acc)
48+
| BareAtom atom | QuotedAtom atom ->
49+
scan (Atom atom :: acc)
50+
in
51+
let rec to_seq () =
52+
match token lexbuf with
53+
| EOF ->
54+
Seq.Nil
55+
| RParen ->
56+
failwith "Unopened ')'" (* FIXME: say where *)
57+
| LParen ->
58+
let list = scan [] in
59+
Seq.Cons (List list, to_seq)
60+
| BareAtom atom | QuotedAtom atom ->
61+
Seq.Cons (Atom atom, to_seq)
62+
in
63+
to_seq
64+
65+
}

0 commit comments

Comments
 (0)