7 signature URL = |
7 signature URL = |
8 sig |
8 sig |
9 datatype T = |
9 datatype T = |
10 File of Path.T | |
10 File of Path.T | |
11 Http of string * Path.T | |
11 Http of string * Path.T | |
|
12 Https of string * Path.T | |
12 Ftp of string * Path.T |
13 Ftp of string * Path.T |
13 val append: T -> T -> T |
14 val append: T -> T -> T |
14 val implode: T -> string |
15 val implode: T -> string |
15 val explode: string -> T |
16 val explode: string -> T |
16 val pretty: T -> Pretty.T |
17 val pretty: T -> Pretty.T |
23 (* type url *) |
24 (* type url *) |
24 |
25 |
25 datatype T = |
26 datatype T = |
26 File of Path.T | |
27 File of Path.T | |
27 Http of string * Path.T | |
28 Http of string * Path.T | |
|
29 Https of string * Path.T | |
28 Ftp of string * Path.T; |
30 Ftp of string * Path.T; |
29 |
31 |
30 |
32 |
31 (* append *) |
33 (* append *) |
32 |
34 |
33 fun append (File p) (File p') = File (Path.append p p') |
35 fun append (File p) (File p') = File (Path.append p p') |
34 | append (Http (h, p)) (File p') = Http (h, Path.append p p') |
36 | append (Http (h, p)) (File p') = Http (h, Path.append p p') |
|
37 | append (Https (h, p)) (File p') = Https (h, Path.append p p') |
35 | append (Ftp (h, p)) (File p') = Ftp (h, Path.append p p') |
38 | append (Ftp (h, p)) (File p') = Ftp (h, Path.append p p') |
36 | append _ url = url; |
39 | append _ url = url; |
37 |
40 |
38 |
41 |
39 (* implode *) |
42 (* implode *) |
40 |
43 |
41 fun implode_path p = if Path.is_current p then "" else Path.implode p; |
44 fun implode_path p = if Path.is_current p then "" else Path.implode p; |
42 |
45 |
43 fun implode_url (File p) = implode_path p |
46 fun implode_url (File p) = implode_path p |
44 | implode_url (Http (h, p)) = "http://" ^ h ^ implode_path p |
47 | implode_url (Http (h, p)) = "http://" ^ h ^ implode_path p |
|
48 | implode_url (Https (h, p)) = "https://" ^ h ^ implode_path p |
45 | implode_url (Ftp (h, p)) = "ftp://" ^ h ^ implode_path p; |
49 | implode_url (Ftp (h, p)) = "ftp://" ^ h ^ implode_path p; |
46 |
50 |
47 |
51 |
48 (* explode *) |
52 (* explode *) |
49 |
53 |
55 |
59 |
56 val scan_path = Scan.many Symbol.not_eof >> (Path.explode o implode); |
60 val scan_path = Scan.many Symbol.not_eof >> (Path.explode o implode); |
57 val scan_path_root = Scan.many Symbol.not_eof >> (Path.explode o implode o cons "/"); |
61 val scan_path_root = Scan.many Symbol.not_eof >> (Path.explode o implode o cons "/"); |
58 |
62 |
59 val scan_url = |
63 val scan_url = |
60 Scan.unless (Scan.this_string "file:" || |
64 Scan.unless |
61 Scan.this_string "http:" || Scan.this_string "ftp:") scan_path >> File || |
65 (Scan.this_string "file:" || Scan.this_string "http:" || |
|
66 Scan.this_string "https:" || Scan.this_string "ftp:") scan_path >> File || |
62 Scan.this_string "file:///" |-- scan_path_root >> File || |
67 Scan.this_string "file:///" |-- scan_path_root >> File || |
63 Scan.this_string "file://localhost/" |-- scan_path_root >> File || |
68 Scan.this_string "file://localhost/" |-- scan_path_root >> File || |
64 Scan.this_string "file://" |-- scan_host -- scan_path |
69 Scan.this_string "file://" |-- scan_host -- scan_path |
65 >> (fn (h, p) => File (Path.append (Path.named_root h) p)) || |
70 >> (fn (h, p) => File (Path.append (Path.named_root h) p)) || |
66 Scan.this_string "file:/" |-- scan_path_root >> File || |
71 Scan.this_string "file:/" |-- scan_path_root >> File || |
67 Scan.this_string "http://" |-- scan_host -- scan_path >> Http || |
72 Scan.this_string "http://" |-- scan_host -- scan_path >> Http || |
|
73 Scan.this_string "https://" |-- scan_host -- scan_path >> Https || |
68 Scan.this_string "ftp://" |-- scan_host -- scan_path >> Ftp; |
74 Scan.this_string "ftp://" |-- scan_host -- scan_path >> Ftp; |
69 |
75 |
70 in |
76 in |
71 |
77 |
72 fun explode_url s = Symbol.scanner "Malformed URL" scan_url (Symbol.explode s); |
78 fun explode_url s = Symbol.scanner "Malformed URL" scan_url (Symbol.explode s); |