-
Notifications
You must be signed in to change notification settings - Fork 0
/
parse.sml
115 lines (102 loc) · 2.65 KB
/
parse.sml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
val example =
"1" ^ "\n" ^
"4" ^ "\n" ^
"0,0" ^ "\n" ^
"1,0" ^ "\n" ^
"1/2,1/2" ^ "\n" ^
"0,1/2" ^ "\n" ^
"5" ^ "\n" ^
"0,0 1,0" ^ "\n" ^
"1,0 1/2,1/2" ^ "\n" ^
"1/2,1/2 0,1/2" ^ "\n" ^
"0,1/2 0,0" ^ "\n" ^
"0,0 1/2,1/2"
structure Int = IntInf
open IntInf
type rat = int * int
type point = rat * rat
type polygon = point list
type edge = point * point
type skelly = edge list
type silly = polygon list
type problem = silly * skelly
fun assert p = if p then () else raise Fail "extra lines"
fun parse_rat (s:string): rat =
case String.tokens (fn c => c = #"/") s of
[s] => (valOf (Int.fromString s), 1)
| [s1,s2] => (valOf (Int.fromString s1), valOf(Int.fromString s2))
fun parse_vert (ss: string list): point * string list =
let
val (vert:: rest) = ss
val [r1, r2] = String.tokens (fn c => c = #",") vert
in
((parse_rat r1, parse_rat r2), rest)
end
fun parse_verts (nVerts:int, rest: string list): polygon * string list =
case nVerts of
0 => ([], rest)
| _ =>
let
val (vert, rest) = parse_vert rest
val (verts, rest) = parse_verts (nVerts - 1, rest)
in
(vert::verts, rest)
end
fun parse_poly (rest:string list): polygon * string list =
let
val (nVerts :: rest) = rest
val nVerts = valOf(Int.fromString nVerts)
in
parse_verts (nVerts, rest)
end
fun parse_polys (n:int, rest:string list):(polygon list)*(string list) =
case n of
0 => ([], rest)
| _ =>
let
val (poly, rest) = parse_poly rest
val (polys, rest) = parse_polys (n-1, rest)
in
(poly::polys, rest)
end
fun parse_silly (lines:string list):silly*(string list) =
let
val (nPoly:: rest) = lines
val nPoly = valOf (Int.fromString nPoly)
in
parse_polys (nPoly, rest)
end
fun parse_seg (rest:string list):edge * string list =
let
val (seg::rest) = rest
val [p1,p2] = String.tokens (fn c => c = #" ") seg
val ((p1,[]),(p2,[])) = (parse_vert [p1], parse_vert [p2])
in
((p1,p2),rest)
end
fun parse_segs (nSegs:int, rest:string list): skelly * string list =
case nSegs of
0 => ([], rest)
| _ =>
let
val (seg, rest) = parse_seg rest
val (segs, rest) = parse_segs (nSegs - 1, rest)
in
(seg::segs, rest)
end
fun parse_skelly (lines:string list): skelly * string list =
let
val (nSegs::rest) = lines
val nSegs = valOf (Int.fromString nSegs)
in
parse_segs (nSegs, rest)
end
fun parse (str:string):problem =
let
val (silly, rest) = parse_silly (String.tokens (fn c => c = #"\n") str)
val (skelly, rest) = parse_skelly rest
val () = assert (rest = [])
in
(silly, skelly)
end
val load = parse o TextIO.inputAll o TextIO.openIn