tangled
alpha
login
or
join now
anil.recoil.org
/
ocaml-yamlrw
1
fork
atom
Pure OCaml Yaml 1.2 reader and writer using Bytesrw
1
fork
atom
overview
issues
pulls
pipelines
odoc
anil.recoil.org
3 months ago
931902c4
75520203
0/1
build.yml
failed
6m 4s
+30
-24
2 changed files
expand all
collapse all
unified
split
doc
tutorial.html
lib
token.mli
+29
-23
doc/tutorial.html
reviewed
···
80
80
("active", `Bool true);
81
81
("score", `Float 95.5)
82
82
];;
83
83
-
val data : [> `Bool of bool | `Float of float | `O of (string * 'a) list | `String of string ] as 'a =
83
83
+
val data :
84
84
+
[> `O of
85
85
+
(string * [> `Bool of bool | `Float of float | `String of string ])
86
86
+
list ] =
84
87
`O
85
88
[("name", `String "Bob"); ("active", `Bool true); ("score", `Float 95.5)]
86
89
# print_string (to_string data);;
···
95
98
"debug", Util.bool true;
96
99
"tags", Util.strings ["api"; "v2"]
97
100
];;
98
98
-
val config : Util.t =
101
101
+
val config : Value.t =
99
102
`O
100
103
[("server", `O [("host", `String "0.0.0.0"); ("port", `Float 8080.)]);
101
101
-
("debug", `Bool true);
102
102
-
("tags", `A [`String "api"; `String "v2"])]
104
104
+
("debug", `Bool true); ("tags", `A [`String "api"; `String "v2"])]
103
105
# print_string (to_string config);;
104
106
server:
105
107
host: 0.0.0.0
···
110
112
- v2
111
113
- : unit = ()</code></pre><h3 id="controlling-output-style"><a href="#controlling-output-style" class="anchor"></a>Controlling Output Style</h3><p>You can control the output format with style options:</p><pre class="language-ocaml"><code># print_string (to_string ~layout_style:`Flow config);;
112
114
{server: {host: 0.0.0.0, port: 8080}, debug: true, tags: [api, v2</code></pre><ul><li>: unit = ()</li></ul><p>Scalar styles control how strings are written:</p><pre class="language-ocaml"><code># print_string (to_string ~scalar_style:`Double_quoted (Util.string "hello"));;
113
113
-
"hello"
115
115
+
hello
114
116
- : unit = ()
115
117
# print_string (to_string ~scalar_style:`Single_quoted (Util.string "hello"));;
116
116
-
'hello'
118
118
+
hello
117
119
- : unit = ()</code></pre><h2 id="full-yaml-representation"><a href="#full-yaml-representation" class="anchor"></a>Full YAML Representation</h2><p>The <code>Yamlrw.value</code> type is convenient but loses some YAML-specific information. For full fidelity, use the <code>Yamlrw.yaml</code> type:</p><pre class="language-ocaml"><code># let full = yaml_of_string ~resolve_aliases:false "hello";;
118
120
val full : yaml = `Scalar <abstr></code></pre><p>The <code>Yamlrw.yaml</code> type preserves:</p><ul><li>Scalar styles (plain, quoted, literal, folded)</li><li>Anchors and aliases</li><li>Type tags</li><li>Collection styles (block vs flow)</li></ul><h3 id="scalars-with-metadata"><a href="#scalars-with-metadata" class="anchor"></a>Scalars with Metadata</h3><pre class="language-ocaml"><code># let s = yaml_of_string ~resolve_aliases:false "'quoted string'";;
119
121
val s : yaml = `Scalar <abstr>
···
175
177
- : int = 2</code></pre><p>The <code>---</code> marker starts a document, and <code>...</code> optionally ends it.</p><h3 id="working-with-documents"><a href="#working-with-documents" class="anchor"></a>Working with Documents</h3><p>Each document has metadata and a root value:</p><pre class="language-ocaml"><code># List.map (fun d -> Document.root d) docs;;
176
178
- : Yaml.t option list =
177
179
[Some (`O <abstr>); Some (`O <abstr>)]</code></pre><h3 id="serializing-multiple-documents"><a href="#serializing-multiple-documents" class="anchor"></a>Serializing Multiple Documents</h3><pre class="language-ocaml"><code># let doc1 = Document.make (Some (of_json (Util.obj ["x", Util.int 1])));;
178
178
-
val doc1 : Document.t = {Yamlrw.version = None; tags = []; root = Some (`O <abstr>); implicit_start = true; implicit_end = true}
180
180
+
val doc1 : Document.t =
181
181
+
{Document.version = None; tags = []; root = Some (`O <abstr>);
182
182
+
implicit_start = true; implicit_end = true}
179
183
# let doc2 = Document.make (Some (of_json (Util.obj ["x", Util.int 2])));;
180
180
-
val doc2 : Document.t = {Yamlrw.version = None; tags = []; root = Some (`O <abstr>); implicit_start = true; implicit_end = true}
184
184
+
val doc2 : Document.t =
185
185
+
{Document.version = None; tags = []; root = Some (`O <abstr>);
186
186
+
implicit_start = true; implicit_end = true}
181
187
# print_string (documents_to_string [doc1; doc2]);;
182
188
x: 1
183
189
---
···
186
192
val parser : Stream.parser = <abstr></code></pre><p>Iterate over events:</p><pre class="language-ocaml"><code># Stream.iter (fun event _ _ ->
187
193
Format.printf "%a@." Event.pp event
188
194
) parser;;
189
189
-
Stream_start `Utf8
190
190
-
Document_start { version = None; implicit = true }
191
191
-
Mapping_start { anchor = None; tag = None; implicit = true; style = Block }
192
192
-
Scalar { value = "key"; anchor = None; tag = None; plain_implicit = true; quoted_implicit = false; style = Plain }
193
193
-
Scalar { value = "value"; anchor = None; tag = None; plain_implicit = true; quoted_implicit = false; style = Plain }
194
194
-
Mapping_end
195
195
-
Document_end { implicit = true }
196
196
-
Stream_end
195
195
+
stream-start(UTF-8)
196
196
+
document-start(version=none, implicit=true)
197
197
+
mapping-start(anchor=none, tag=none, implicit=true, style=block)
198
198
+
scalar(anchor=none, tag=none, style=plain, value="key")
199
199
+
scalar(anchor=none, tag=none, style=plain, value="value")
200
200
+
mapping-end
201
201
+
document-end(implicit=true)
202
202
+
stream-end
197
203
- : unit = ()</code></pre><h3 id="building-yaml-with-events"><a href="#building-yaml-with-events" class="anchor"></a>Building YAML with Events</h3><p>You can also emit YAML by sending events:</p><pre class="language-ocaml"><code># let emitter = Stream.emitter ();;
198
204
val emitter : Stream.emitter = <abstr>
199
205
# Stream.stream_start emitter `Utf8;;
···
219
225
"ok"
220
226
with Yamlrw_error e ->
221
227
Error.to_string e;;
222
222
-
- : string =
223
223
-
"Parse error at line 1, column 15: while parsing a flow sequence, expected ',' or ']', but got end of stream"</code></pre><h3 id="type-errors"><a href="#type-errors" class="anchor"></a>Type Errors</h3><p>The <code>Yamlrw.Util</code> module raises <code>Yamlrw.Util.Type_error</code> for type mismatches:</p><pre class="language-ocaml"><code># try
228
228
+
- : string = "expected sequence end ']' at line 1, columns 15-15"</code></pre><h3 id="type-errors"><a href="#type-errors" class="anchor"></a>Type Errors</h3><p>The <code>Yamlrw.Util</code> module raises <code>Yamlrw.Util.Type_error</code> for type mismatches:</p><pre class="language-ocaml"><code># try
224
229
ignore (Util.get_string (`Float 42.));
225
230
"ok"
226
231
with Util.Type_error (expected, actual) ->
227
232
Printf.sprintf "expected %s, got %s" expected (Value.type_name actual);;
228
228
-
- : string = "expected string, got number"</code></pre><h2 id="common-patterns"><a href="#common-patterns" class="anchor"></a>Common Patterns</h2><h3 id="configuration-files"><a href="#configuration-files" class="anchor"></a>Configuration Files</h3><p>A typical configuration file pattern:</p><pre class="language-ocaml"><code># let config_yaml = {|
233
233
+
- : string = "expected string, got float"</code></pre><h2 id="common-patterns"><a href="#common-patterns" class="anchor"></a>Common Patterns</h2><h3 id="configuration-files"><a href="#configuration-files" class="anchor"></a>Configuration Files</h3><p>A typical configuration file pattern:</p><pre class="language-ocaml"><code># let config_yaml = {|
229
234
app:
230
235
name: myapp
231
236
version: 1.0.0
···
287
292
acc +. Util.get_float (Util.get "price" item)
288
293
) 0. items;;
289
294
val total : float = 59.97</code></pre><h3 id="transforming-data"><a href="#transforming-data" class="anchor"></a>Transforming Data</h3><p>Modifying YAML structures:</p><pre class="language-ocaml"><code># let original = of_string "name: Alice\nstatus: active";;
290
290
-
val original : value = `O [("name", `String "Alice"); ("status", `String "active")]
295
295
+
val original : value =
296
296
+
`O [("name", `String "Alice"); ("status", `String "active")]
291
297
# let updated = Util.update "status" (Util.string "inactive") original;;
292
292
-
val updated : Util.t =
298
298
+
val updated : Value.t =
293
299
`O [("name", `String "Alice"); ("status", `String "inactive")]
294
300
# let with_timestamp = Util.update "updated_at" (Util.string "2024-01-01") updated;;
295
295
-
val with_timestamp : Util.t =
301
301
+
val with_timestamp : Value.t =
296
302
`O
297
303
[("name", `String "Alice"); ("status", `String "inactive");
298
304
("updated_at", `String "2024-01-01")]
299
305
# print_string (to_string with_timestamp);;
300
306
name: Alice
301
307
status: inactive
302
302
-
updated_at: '2024-01-01'
308
308
+
updated_at: 2024-01-01
303
309
- : unit = ()</code></pre><h2 id="summary"><a href="#summary" class="anchor"></a>Summary</h2><p>The <code>yamlrw</code> library provides:</p><ol><li><b>Simple parsing</b>: <code>Yamlrw.of_string</code> for JSON-compatible values</li><li><b>Full fidelity</b>: <code>Yamlrw.yaml_of_string</code> preserves all YAML metadata</li><li><b>Easy serialization</b>: <code>Yamlrw.to_string</code> with style options</li><li><b>Navigation</b>: <code>Yamlrw.Util</code> module for accessing and modifying values</li><li><b>Multi-document</b>: <code>Yamlrw.documents_of_string</code> for YAML streams</li><li><b>Streaming</b>: <code>Yamlrw.Stream</code> module for event-based processing</li></ol><p>Key types:</p><ul><li><code>Yamlrw.value</code> - JSON-compatible representation (<code>`Null</code>, <code>`Bool</code>, <code>`Float</code>, <code>`String</code>, <code>`A</code>, <code>`O</code>)</li><li><code>Yamlrw.yaml</code> - Full YAML with scalars, anchors, aliases, and metadata</li><li><code>Yamlrw.document</code> - A complete document with directives</li></ul><p>For more details, see the <span class="xref-unresolved" title="Yamlrw">API reference</span>.</p></div></body></html>
+1
-1
lib/token.mli
reviewed
···
14
14
| Document_end (** ... *)
15
15
| Block_sequence_start
16
16
| Block_mapping_start
17
17
-
| Block_entry (** - *)
17
17
+
| Block_entry (** [-] *)
18
18
| Block_end (** implicit, from dedent *)
19
19
| Flow_sequence_start (** \[ *)
20
20
| Flow_sequence_end (** \] *)