16 |
16 |
17 and pgipdtype = Pgipdtype of string option * pgiptype (* type with opt. description *) |
17 and pgipdtype = Pgipdtype of string option * pgiptype (* type with opt. description *) |
18 |
18 |
19 exception PGIP of string |
19 exception PGIP of string |
20 |
20 |
21 (* Values as XML strings *) |
|
22 val read_pgipint : (int option * int option) -> string -> int (* raises PGIP *) |
|
23 val read_pgipnat : string -> int (* raises PGIP *) |
|
24 val read_pgipbool : string -> bool (* raises PGIP *) |
|
25 val read_pgipreal : string -> real (* raises PGIP *) |
|
26 val read_pgipstring : string -> string (* raises PGIP *) |
|
27 val real_to_pgstring : real -> string |
|
28 val int_to_pgstring : int -> string |
|
29 val bool_to_pgstring : bool -> string |
|
30 val string_to_pgstring : string -> string |
|
31 |
|
32 (* PGIP datatypes *) |
|
33 val pgiptype_to_xml : pgiptype -> XML.tree |
21 val pgiptype_to_xml : pgiptype -> XML.tree |
34 end |
22 end |
35 |
23 |
36 structure PgipTypes : PGIPTYPES = |
24 structure PgipTypes : PGIPTYPES = |
37 struct |
25 struct |
47 |
35 |
48 fun attr x y = [(x,y)] : XML.attributes |
36 fun attr x y = [(x,y)] : XML.attributes |
49 |
37 |
50 fun opt_attr _ NONE = [] |
38 fun opt_attr _ NONE = [] |
51 | opt_attr name (SOME value) = attr name value; |
39 | opt_attr name (SOME value) = attr name value; |
52 |
|
53 |
|
54 (** Types and values **) |
|
55 |
|
56 fun read_pgipbool s = |
|
57 (case s of |
|
58 "false" => false |
|
59 | "true" => true |
|
60 | _ => raise PGIP ("Invalid boolean value: " ^ quote s)) |
|
61 |
|
62 local |
|
63 fun int_in_range (NONE,NONE) (_: int) = true |
|
64 | int_in_range (SOME min,NONE) i = min<= i |
|
65 | int_in_range (NONE,SOME max) i = i<=max |
|
66 | int_in_range (SOME min,SOME max) i = min<= i andalso i<=max |
|
67 in |
|
68 fun read_pgipint range s = |
|
69 (case Int.fromString s of |
|
70 SOME i => if int_in_range range i then i |
|
71 else raise PGIP ("Out of range integer value: " ^ quote s) |
|
72 | NONE => raise PGIP ("Invalid integer value: " ^ quote s)) |
|
73 end; |
|
74 |
|
75 fun read_pgipnat s = |
|
76 (case Int.fromString s of |
|
77 SOME i => if i >= 0 then i |
|
78 else raise PGIP ("Invalid natural number: " ^ quote s) |
|
79 | NONE => raise PGIP ("Invalid natural number: " ^ quote s)) |
|
80 |
|
81 fun read_pgipreal s = |
|
82 (case Real.fromString s of |
|
83 SOME x => x |
|
84 | NONE => raise PGIP ("Invalid floating-point number: " ^ quote s)) |
|
85 |
|
86 (* NB: we can maybe do without xml decode/encode here. *) |
|
87 fun read_pgipstring s = (* non-empty strings, XML escapes decoded *) |
|
88 (case XML.parse_string s of |
|
89 SOME s => s |
|
90 | NONE => raise PGIP ("Expected a non-empty string: " ^ quote s)) |
|
91 handle _ => raise PGIP ("Invalid XML string syntax: " ^ quote s) (* FIXME avoid handle _ *) |
|
92 |
|
93 val int_to_pgstring = signed_string_of_int |
|
94 |
|
95 val real_to_pgstring = Markup.print_real; |
|
96 |
|
97 |
|
98 fun string_to_pgstring s = XML.text s |
|
99 |
|
100 fun bool_to_pgstring b = if b then "true" else "false" |
|
101 |
40 |
102 |
41 |
103 (* PGIP datatypes. |
42 (* PGIP datatypes. |
104 |
43 |
105 This is a reflection of the type structure of PGIP configuration, |
44 This is a reflection of the type structure of PGIP configuration, |
148 | Pgipreal => "pgipint" (*sic!*) (*required for PG 4.0 and 3.7.x*) |
87 | Pgipreal => "pgipint" (*sic!*) (*required for PG 4.0 and 3.7.x*) |
149 | Pgipstring => "pgipstring" |
88 | Pgipstring => "pgipstring" |
150 | Pgipconst _ => "pgipconst" |
89 | Pgipconst _ => "pgipconst" |
151 | Pgipchoice _ => "pgipchoice" |
90 | Pgipchoice _ => "pgipchoice" |
152 |
91 |
153 fun range_attr r v = attr r (int_to_pgstring v) |
92 fun range_attr r v = attr r (Markup.print_int v) |
154 |
93 |
155 val attrs = case ty of |
94 val attrs = case ty of |
156 Pgipint (SOME min,SOME max) => (range_attr "min" min)@(range_attr "max" max) |
95 Pgipint (SOME min,SOME max) => (range_attr "min" min)@(range_attr "max" max) |
157 | Pgipint (SOME min,NONE) => (range_attr "min" min) |
96 | Pgipint (SOME min,NONE) => (range_attr "min" min) |
158 | Pgipint (NONE,SOME max) => (range_attr "max" max) |
97 | Pgipint (NONE,SOME max) => (range_attr "max" max) |