RbYAML 0.0.2 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (44) hide show
  1. data/README +1 -1
  2. data/lib/rbyaml/composer.rb +28 -25
  3. data/lib/rbyaml/composer.rb.~1.2.~ +109 -0
  4. data/lib/rbyaml/constructor.rb +94 -84
  5. data/lib/rbyaml/constructor.rb.~1.2.~ +381 -0
  6. data/lib/rbyaml/dumper.rb +10 -17
  7. data/lib/rbyaml/dumper.rb.~1.2.~ +43 -0
  8. data/lib/rbyaml/emitter.rb +13 -26
  9. data/lib/rbyaml/emitter.rb.~1.2.~ +1116 -0
  10. data/lib/rbyaml/error.rb +15 -21
  11. data/lib/rbyaml/events.rb +29 -5
  12. data/lib/rbyaml/events.rb.~1.2.~ +93 -0
  13. data/lib/rbyaml/loader.rb +11 -23
  14. data/lib/rbyaml/loader.rb.~1.2.~ +52 -0
  15. data/lib/rbyaml/nodes.rb +13 -9
  16. data/lib/rbyaml/nodes.rb.~1.2.~ +52 -0
  17. data/lib/rbyaml/parser.rb +481 -343
  18. data/lib/rbyaml/parser.rb.old +531 -0
  19. data/lib/rbyaml/parser.rb.~1.2.~ +494 -0
  20. data/lib/rbyaml/reader.rb.~1.1.1.1.~ +127 -0
  21. data/lib/rbyaml/representer.rb +26 -17
  22. data/lib/rbyaml/representer.rb.~1.2.~ +239 -0
  23. data/lib/rbyaml/resolver.rb +15 -15
  24. data/lib/rbyaml/resolver.rb.~1.1.~ +163 -0
  25. data/lib/rbyaml/scanner.rb +457 -366
  26. data/lib/rbyaml/scanner.rb.~1.2.~ +1259 -0
  27. data/lib/rbyaml/serializer.rb +19 -17
  28. data/lib/rbyaml/serializer.rb.~1.2.~ +115 -0
  29. data/lib/rbyaml/tokens.rb +44 -4
  30. data/lib/rbyaml/tokens.rb.~1.2.~ +164 -0
  31. data/lib/rbyaml/util.rb +28 -0
  32. data/lib/rbyaml/yaml.rb +12 -12
  33. data/lib/rbyaml/yaml.rb.~1.2.~ +136 -0
  34. data/test/test_bm.rb +28 -0
  35. data/test/test_bm_syck.rb +28 -0
  36. data/test/test_invoke.rb +31 -0
  37. data/test/test_one.rb +5 -0
  38. data/test/test_profile.rb +32 -0
  39. data/test/test_rbyaml.rb +2 -1
  40. data/test/test_rbyaml.rb.~1.2.~ +31 -0
  41. data/test/test_time.rb +13 -8
  42. data/test/test_time.rb.~1.1.~ +29 -0
  43. data/test/yamlx.rb +3563 -0
  44. metadata +27 -2
@@ -0,0 +1,494 @@
1
+
2
+ # YAML can be parsed by an LL(1) parser!
3
+ #
4
+ # We use the following production rules:
5
+ # stream ::= STREAM-START implicit_document? explicit_document* STREAM-END
6
+ # explicit_document ::= DIRECTIVE* DOCUMENT-START block_node? DOCUMENT-END?
7
+ # implicit_document ::= block_node DOCUMENT-END?
8
+ # block_node ::= ALIAS | properties? block_content
9
+ # flow_node ::= ALIAS | properties? flow_content
10
+ # properties ::= TAG ANCHOR? | ANCHOR TAG?
11
+ # block_content ::= block_collection | flow_collection | SCALAR
12
+ # flow_content ::= flow_collection | SCALAR
13
+ # block_collection ::= block_sequence | block_mapping
14
+ # block_sequence ::= BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
15
+ # block_mapping ::= BLOCK-MAPPING_START ((KEY block_node_or_indentless_sequence?)? (VALUE block_node_or_indentless_sequence?)?)* BLOCK-END
16
+ # block_node_or_indentless_sequence ::= ALIAS | properties? (block_content | indentless_block_sequence)
17
+ # indentless_block_sequence ::= (BLOCK-ENTRY block_node?)+
18
+ # flow_collection ::= flow_sequence | flow_mapping
19
+ # flow_sequence ::= FLOW-SEQUENCE-START (flow_sequence_entry FLOW-ENTRY)* flow_sequence_entry? FLOW-SEQUENCE-END
20
+ # flow_mapping ::= FLOW-MAPPING-START (flow_mapping_entry FLOW-ENTRY)* flow_mapping_entry? FLOW-MAPPING-END
21
+ # flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
22
+ # flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
23
+
24
+ # TODO: support for BOM within a stream.
25
+ # stream ::= (BOM? implicit_document)? (BOM? explicit_document)* STREAM-END
26
+
27
+ # FIRST sets:
28
+ # stream: { STREAM-START }
29
+ # explicit_document: { DIRECTIVE DOCUMENT-START }
30
+ # implicit_document: FIRST(block_node)
31
+ # block_node: { ALIAS TAG ANCHOR SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START }
32
+ # flow_node: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START }
33
+ # block_content: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR }
34
+ # flow_content: { FLOW-SEQUENCE-START FLOW-MAPPING-START SCALAR }
35
+ # block_collection: { BLOCK-SEQUENCE-START BLOCK-MAPPING-START }
36
+ # flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START }
37
+ # block_sequence: { BLOCK-SEQUENCE-START }
38
+ # block_mapping: { BLOCK-MAPPING-START }
39
+ # block_node_or_indentless_sequence: { ALIAS ANCHOR TAG SCALAR BLOCK-SEQUENCE-START BLOCK-MAPPING-START FLOW-SEQUENCE-START FLOW-MAPPING-START BLOCK-ENTRY }
40
+ # indentless_sequence: { ENTRY }
41
+ # flow_collection: { FLOW-SEQUENCE-START FLOW-MAPPING-START }
42
+ # flow_sequence: { FLOW-SEQUENCE-START }
43
+ # flow_mapping: { FLOW-MAPPING-START }
44
+ # flow_sequence_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY }
45
+ # flow_mapping_entry: { ALIAS ANCHOR TAG SCALAR FLOW-SEQUENCE-START FLOW-MAPPING-START KEY }
46
+
47
+ require 'rbyaml/error'
48
+ require 'rbyaml/tokens'
49
+ require 'rbyaml/events'
50
+ require 'rbyaml/scanner'
51
+
52
+ module RbYAML
53
+ class ParserError < MarkedYAMLError
54
+ end
55
+
56
+ module Parser
57
+
58
+ DEFAULT_TAGS = {
59
+ '!' => '!',
60
+ '!!' => 'tag:yaml.org,2002:'
61
+ }
62
+
63
+ def initialize_parser
64
+ @current_event = nil
65
+ @yaml_version = nil
66
+ @events = nil
67
+ @working_events = nil
68
+ @tag_handles = { }
69
+ end
70
+
71
+ def check_event(*choices)
72
+ init_events
73
+ @current_event = @working_events.shift if @current_event.nil?
74
+ if @current_event
75
+ return true if choices.empty?
76
+ for choice in choices
77
+ return true if choice === @current_event
78
+ end
79
+ end
80
+ false
81
+ end
82
+
83
+ def peek_event
84
+ init_events
85
+ @current_event = @working_events.shift if @current_event.nil?
86
+ @current_event
87
+ end
88
+
89
+ def get_event
90
+ init_events
91
+ @current_event = @working_events.shift if @current_event.nil?
92
+ value = @current_event
93
+ @current_event = nil
94
+ value
95
+ end
96
+
97
+ def init_events
98
+ @events ||= parse_stream
99
+ @working_events ||= @events
100
+ end
101
+
102
+ def each_event(&block)
103
+ init_events
104
+ @events.each(&block)
105
+ end
106
+
107
+ def parse_stream
108
+ # STREAM-START implicit_document? explicit_document* STREAM-END
109
+
110
+ # Parse start of stream.
111
+ events = []
112
+ token = get_token
113
+ events << StreamStartEvent.new(token.start_mark, token.end_mark,token.encoding)
114
+
115
+ # Parse implicit document.
116
+ unless check_token(DirectiveToken, DocumentStartToken,StreamEndToken)
117
+ @tag_handles = DEFAULT_TAGS
118
+ token = peek_token
119
+ start_mark = end_mark = token.start_mark
120
+ events << DocumentStartEvent.new(start_mark, end_mark,false)
121
+ events += parse_block_node
122
+ token = peek_token
123
+ start_mark = end_mark = token.start_mark
124
+ explicit = false
125
+ while check_token(DocumentEndToken)
126
+ token = get_token
127
+ end_mark = token.end_mark
128
+ explicit = true
129
+ end
130
+ events << DocumentEndEvent.new(start_mark, end_mark,explicit)
131
+ end
132
+
133
+ # Parse explicit documents.
134
+ while !check_token(StreamEndToken)
135
+ token = peek_token
136
+ start_mark = token.start_mark
137
+ version, tags = process_directives
138
+ raise ParserError.new(nil, nil,"expected '<document start>', but found #{peek_token.id}",peek_token.start_mark) unless check_token(DocumentStartToken)
139
+ token = get_token
140
+ end_mark = token.end_mark
141
+ events << DocumentStartEvent.new(start_mark, end_mark,true,version,tags)
142
+ if check_token(DirectiveToken,DocumentStartToken, DocumentEndToken, StreamEndToken)
143
+ events << process_empty_scalar(token.end_mark)
144
+ else
145
+ events += parse_block_node
146
+ end
147
+ token = peek_token
148
+ start_mark = end_mark = token.start_mark
149
+ explicit = false
150
+ while check_token(DocumentEndToken)
151
+ token = get_token
152
+ end_mark = token.end_mark
153
+ explicit=true
154
+ end
155
+ events << DocumentEndEvent.new(start_mark, end_mark,explicit)
156
+ end
157
+ # Parse end of stream.
158
+ token = get_token
159
+ events << StreamEndEvent.new(token.start_mark, token.end_mark)
160
+ events
161
+ end
162
+
163
+ def process_directives
164
+ # DIRECTIVE*
165
+ while check_token(DirectiveToken)
166
+ token = get_token
167
+ if token.name == "YAML"
168
+ raise ParserError.new(nil, nil,"found duplicate YAML directive", token.start_mark) if !@yaml_version.nil?
169
+ major, minor = token.value[0].to_i, token.value[1].to_i
170
+ raise ParserError.new(nil,nil,"found incompatible YAML document (version 1.* is required)",token.start_mark) if major != 1
171
+ @yaml_version = [major,minor]
172
+ elsif token.name == "TAG"
173
+ handle, prefix = token.value
174
+ raise ParserError.new(nil,nil,"duplicate tag handle #{handle}",token.start_mark) if @tag_handles.member?(handle)
175
+ @tag_handles[handle] = prefix
176
+ end
177
+ end
178
+ if !@tag_handles.empty?
179
+ value = @yaml_version, @tag_handles.dup
180
+ else
181
+ value = @yaml_version, nil
182
+ end
183
+ for key in DEFAULT_TAGS.keys
184
+ @tag_handles[key] = DEFAULT_TAGS[key] if !@tag_handles.include?(key)
185
+ end
186
+ value
187
+ end
188
+
189
+ def parse_block_node
190
+ parse_node(true)
191
+ end
192
+
193
+ def parse_flow_node
194
+ parse_node
195
+ end
196
+
197
+ def parse_block_node_or_indentless_sequence
198
+ parse_node(true, true)
199
+ end
200
+
201
+ def parse_node(block=false, indentless_sequence=false)
202
+ # block_node ::= ALIAS | properties? block_content
203
+ # flow_node ::= ALIAS | properties? flow_content
204
+ # properties ::= TAG ANCHOR? | ANCHOR TAG?
205
+ # block_content ::= block_collection | flow_collection | SCALAR
206
+ # flow_content ::= flow_collection | SCALAR
207
+ # block_collection ::= block_sequence | block_mapping
208
+ # block_node_or_indentless_sequence ::= ALIAS | properties?
209
+ # (block_content | indentless_block_sequence)
210
+ events = []
211
+ if check_token(AliasToken)
212
+ token = get_token
213
+ events << AliasEvent.new(token.value, token.start_mark, token.end_mark)
214
+ else
215
+ anchor = nil
216
+ tag = nil
217
+ start_mark = end_mark = tag_mark = nil
218
+ if check_token(AnchorToken)
219
+ token = get_token
220
+ start_mark = token.start_mark
221
+ end_mark = token.end_mark
222
+ anchor = token.value
223
+ if check_token(TagToken)
224
+ token = get_token
225
+ tag_mark = token.start_mark
226
+ end_mark = token.end_mark
227
+ tag = token.value
228
+ end
229
+ elsif check_token(TagToken)
230
+ token = get_token
231
+ start_mark = tag_mark = token.start_mark
232
+ end_mark = token.end_mark
233
+ tag = token.value
234
+ if check_token(AnchorToken)
235
+ token = get_token
236
+ end_mark = token.end_mark
237
+ anchor = token.value
238
+ end
239
+ end
240
+
241
+ if !tag.nil? and tag != "!"
242
+ handle, suffix = tag
243
+ if !handle.nil?
244
+ raise ParserError.new("while parsing a node", start_mark,"found undefined tag handle #{handle}",tag_mark) if !@tag_handles.include?(handle)
245
+ tag = @tag_handles[handle]+suffix
246
+ else
247
+ tag = suffix
248
+ end
249
+ end
250
+
251
+ #if tag == u'!':
252
+ # raise ParserError("while parsing a node", start_mark,
253
+ # "found non-specific tag '!'", tag_mark,
254
+ # "Please check 'http://pyyaml.org/wiki/YAMLNonSpecificTag' and share your opinion.")
255
+ if start_mark.nil?
256
+ start_mark = end_mark = peek_token.start_mark
257
+ end
258
+ event = nil
259
+ collection_events = nil
260
+ implicit = tag.nil? || tag == ?!
261
+ if indentless_sequence && check_token(BlockEntryToken)
262
+ end_mark = peek_token.end_mark
263
+ event = SequenceStartEvent.new(anchor, tag, implicit, start_mark, end_mark)
264
+ collection_events = parse_indentless_sequence
265
+ else
266
+ if check_token(ScalarToken)
267
+ token = get_token
268
+ end_mark = token.end_mark
269
+ if (token.plain && tag.nil?) || tag == ?!
270
+ implicit = [true, false]
271
+ elsif tag.nil?
272
+ implicit = [false, true]
273
+ else
274
+ implicit = [false, false]
275
+ end
276
+ event = ScalarEvent.new(anchor, tag, implicit, token.value,start_mark, end_mark,token.style)
277
+ elsif check_token(FlowSequenceStartToken)
278
+ end_mark = peek_token.end_mark
279
+ event = SequenceStartEvent.new(anchor, tag, implicit, start_mark, end_mark,true)
280
+ collection_events = parse_flow_sequence
281
+ elsif check_token(FlowMappingStartToken)
282
+ end_mark = peek_token.end_mark
283
+ event = MappingStartEvent.new(anchor, tag, implicit, start_mark, end_mark,true)
284
+ collection_events = parse_flow_mapping
285
+ elsif block && check_token(BlockSequenceStartToken)
286
+ end_mark = peek_token.start_mark
287
+ event = SequenceStartEvent.new(anchor, tag, implicit, start_mark, end_mark,false)
288
+ collection_events = parse_block_sequence
289
+ elsif block && check_token(BlockMappingStartToken)
290
+ end_mark = peek_token.start_mark
291
+ event = MappingStartEvent.new(anchor, tag, implicit, start_mark, end_mark,false)
292
+ collection_events = parse_block_mapping
293
+ elsif !anchor.nil? || !tag.nil?
294
+ # Empty scalars are allowed even if a tag or an anchor is
295
+ # specified.
296
+ event = ScalarEvent.new(anchor, tag, [implicit,false],"",start_mark, end_mark)
297
+ else
298
+ if block
299
+ node = "block"
300
+ else
301
+ node = "flow"
302
+ end
303
+ token = peek_token
304
+ raise ParserError.new("while scanning a #{node} node", start_mark,"expected the node content, but found #{token.tid}",token.start_mark)
305
+ end
306
+ end
307
+ events << event
308
+ events += collection_events if collection_events
309
+ end
310
+ events
311
+ end
312
+
313
+ def parse_block_sequence
314
+ # BLOCK-SEQUENCE-START (BLOCK-ENTRY block_node?)* BLOCK-END
315
+ events = []
316
+ token = get_token
317
+ start_mark = token.start_mark
318
+ while check_token(BlockEntryToken)
319
+ token = get_token
320
+ if !check_token(BlockEntryToken, BlockEndToken)
321
+ events += parse_block_node
322
+ else
323
+ events << process_empty_scalar(token.end_mark)
324
+ end
325
+ end
326
+ if !check_token(BlockEndToken)
327
+ token = peek_token
328
+ raise ParserError.new("while scanning a block collection", start_mark,"expected <block end>, but found #{token.tid}", token.start_mark)
329
+ end
330
+ token = get_token
331
+ events << SequenceEndEvent.new(token.start_mark, token.end_mark)
332
+ events
333
+ end
334
+
335
+ def parse_indentless_sequence
336
+ # (BLOCK-ENTRY block_node?)+
337
+ events = []
338
+ while check_token(BlockEntryToken)
339
+ token = get_token
340
+ if !check_token(BlockEntryToken,KeyToken, ValueToken, BlockEndToken)
341
+ events += parse_block_node
342
+ else
343
+ events << process_empty_scalar(token.end_mark)
344
+ end
345
+ end
346
+ token = peek_token
347
+ events << SequenceEndEvent.new(token.start_mark, token.start_mark)
348
+ events
349
+ end
350
+
351
+
352
+ def parse_block_mapping
353
+ # BLOCK-MAPPING_START
354
+ # ((KEY block_node_or_indentless_sequence?)?
355
+ # (VALUE block_node_or_indentless_sequence?)?)*
356
+ # BLOCK-END
357
+ events = []
358
+ token = get_token
359
+ start_mark = token.start_mark
360
+ while check_token(KeyToken, ValueToken)
361
+ if check_token(KeyToken)
362
+ token = get_token
363
+ if !check_token(KeyToken, ValueToken, BlockEndToken)
364
+ events += parse_block_node_or_indentless_sequence
365
+ else
366
+ events << process_empty_scalar(token.end_mark)
367
+ end
368
+ end
369
+ if check_token(ValueToken)
370
+ token = get_token
371
+ if !check_token(KeyToken, ValueToken, BlockEndToken)
372
+ events += parse_block_node_or_indentless_sequence
373
+ else
374
+ events << process_empty_scalar(token.end_mark)
375
+ end
376
+ else
377
+ token = peek_token
378
+ events << process_empty_scalar(token.start_mark)
379
+ end
380
+ end
381
+ if !check_token(BlockEndToken)
382
+ token = peek_token
383
+ raise ParserError.new("while scanning a block mapping", start_mark,"expected <block end>, but found #{token.tid}", token.start_mark)
384
+ end
385
+ token = get_token
386
+ events << MappingEndEvent.new(token.start_mark, token.end_mark)
387
+ events
388
+ end
389
+
390
+ def parse_flow_sequence
391
+ # flow_sequence ::= FLOW-SEQUENCE-START
392
+ # (flow_sequence_entry FLOW-ENTRY)*
393
+ # flow_sequence_entry?
394
+ # FLOW-SEQUENCE-END
395
+ # flow_sequence_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
396
+ #
397
+ # Note that while production rules for both flow_sequence_entry and
398
+ # flow_mapping_entry are equal, their interpretations are different.
399
+ # For `flow_sequence_entry`, the part `KEY flow_node? (VALUE flow_node?)?`
400
+ # generate an inline mapping (set syntax).
401
+ events = []
402
+ token = get_token
403
+ start_mark = token.start_mark
404
+ while !check_token(FlowSequenceEndToken)
405
+ if check_token(KeyToken)
406
+ token = get_token
407
+ events << MappingStartEvent.new(nil,nil,true,token.start_mark, token.end_mark,true)
408
+ if !check_token(ValueToken,FlowEntryToken, FlowSequenceEndToken)
409
+ events += parse_flow_node
410
+ else
411
+ events << process_empty_scalar(token.end_mark)
412
+ end
413
+ if check_token(ValueToken)
414
+ token = get_token
415
+ if !check_token(FlowEntryToken, FlowSequenceEndToken)
416
+ events += parse_flow_node
417
+ else
418
+ events << process_empty_scalar(token.end_mark)
419
+ end
420
+ else
421
+ token = peek_token
422
+ events << process_empty_scalar(token.start_mark)
423
+ end
424
+ token = peek_token
425
+ events << MappingEndEvent.new(token.start_mark, token.start_mark)
426
+ else
427
+ events += parse_flow_node
428
+ end
429
+ if !check_token(FlowEntryToken, FlowSequenceEndToken)
430
+ token = peek_token
431
+ raise ParserError.new("while scanning a flow sequence", start_mark,"expected ',' or ']', but got #{token.tid}", token.start_mark)
432
+ end
433
+ if check_token(FlowEntryToken)
434
+ get_token
435
+ end
436
+ end
437
+ token = get_token
438
+ events << SequenceEndEvent.new(token.start_mark, token.end_mark)
439
+ events
440
+ end
441
+
442
+ def parse_flow_mapping
443
+ # flow_mapping ::= FLOW-MAPPING-START
444
+ # (flow_mapping_entry FLOW-ENTRY)*
445
+ # flow_mapping_entry?
446
+ # FLOW-MAPPING-END
447
+ # flow_mapping_entry ::= flow_node | KEY flow_node? (VALUE flow_node?)?
448
+ events = []
449
+ token = get_token
450
+ start_mark = token.start_mark
451
+ while !check_token(FlowMappingEndToken)
452
+ if check_token(KeyToken)
453
+ token = get_token
454
+ if !check_token(ValueToken,FlowEntryToken, FlowMappingEndToken)
455
+ events += parse_flow_node
456
+ else
457
+ events << process_empty_scalar(token.end_mark)
458
+ end
459
+ if check_token(ValueToken)
460
+ token = get_token
461
+ if !check_token(FlowEntryToken, FlowMappingEndToken)
462
+ events += parse_flow_node
463
+ else
464
+ events << process_empty_scalar(token.end_mark)
465
+ end
466
+ else
467
+ token = peek_token
468
+ events << process_empty_scalar(token.start_mark)
469
+ end
470
+ else
471
+ events += parse_flow_node
472
+ events << process_empty_scalar(peek_token.start_mark)
473
+ end
474
+ if !check_token(FlowEntryToken, FlowMappingEndToken)
475
+ token = peek_token
476
+ raise ParserError.new("while scanning a flow mapping", start_mark,"expected ',' or '}', but got #{token.tid}", token.start_mark)
477
+ end
478
+ get_token if check_token(FlowEntryToken)
479
+ end
480
+ if !check_token(FlowMappingEndToken)
481
+ token = peek_token
482
+ raise ParserError.new("while scanning a flow mapping", start_mark,"expected '}', but found #{token.tid}", token.start_mark)
483
+ end
484
+ token = get_token
485
+ events << MappingEndEvent.new(token.start_mark, token.end_mark)
486
+ events
487
+ end
488
+
489
+ def process_empty_scalar(mark)
490
+ ScalarEvent.new(nil, nil, [true, false], "", mark, mark)
491
+ end
492
+ end
493
+ end
494
+