Lightweight yaml parser and emitter stripped from VYaml
YamlParser
struct provides access to the complete meta-information of yaml.
YamlParser.Read()
reads through to the next syntax on yaml. (If end of stream then return false.)YamlParser.ParseEventType
indicates the state of the currently read yaml parsing result.- How to access scalar value:
YamlParser.GetScalarAs*
families take the result of converting a scalar at the current position to a specified type.YamlParser.TryGetScalarAs*
families return true and take a result if the current position is a scalar and of the specified type.YamlParser.ReadScalarAs*
families is similar to GetScalarAs*, but advances the present position to after the scalar read.
- How to access meta information:
YamlParser.TryGetTag(out Tag tag)
YamlParser.TryGetCurrentAnchor(out Anchor anchor)
Basic example:
var parser = YamlParser.FromBytes(utf8Bytes);
// YAML contains more than one `Document`.
// Here we skip to before first document content.
parser.SkipAfter(ParseEventType.DocumentStart);
// Scanning...
while (parser.Read())
{
// If the current syntax is Scalar,
if (parser.CurrentEventType == ParseEventType.Scalar)
{
var intValue = parser.GetScalarAsInt32();
var stringValue = parser.GetScalarAsString();
// ...
if (parser.TryGetCurrentTag(out var tag))
{
// Check for the tag...
}
if (parser.TryGetCurrentAnchor(out var anchor))
{
// Check for the anchor...
}
}
// If the current syntax is Sequence (Like a list in yaml)
else if (parser.CurrentEventType == ParseEventType.SequenceStart)
{
// We can check for the tag...
// We can check for the anchor...
parser.Read(); // Skip SequenceStart
// Read to end of sequence
while (!parser.End && parser.CurrentEventType != ParseEventType.SequenceEnd)
{
// A sequence element may be a scalar or other...
if (parser.CurrentEventType = ParseEventType.Scalar)
{
// ...
}
// ...
// ...
else
{
// We can skip current element. (It could be a scalar, or alias, sequence, mapping...)
parser.SkipCurrentNode();
}
}
parser.Read(); // Skip SequenceEnd.
}
// If the current syntax is Mapping (like a Dictionary in yaml)
else if (parser.CurrentEventType == ParseEventType.MappingStart)
{
// We can check for the tag...
// We can check for the anchor...
parser.Read(); // Skip MappingStart
// Read to end of mapping
while (parser.CurrentEventType != ParseEventType.MappingEnd)
{
// After Mapping start, key and value appear alternately.
var key = parser.ReadScalarAsString(); // if key is scalar
var value = parser.ReadScalarAsString(); // if value is scalar
// Or we can skip current key/value. (It could be a scalar, or alias, sequence, mapping...)
// parser.SkipCurrentNode(); // skip key
// parser.SkipCurrentNode(); // skip value
}
parser.Read(); // Skip MappingEnd.
}
// Alias
else if (parser.CurrentEventType == ParseEventType.Alias)
{
// If Alias is used, the previous anchors must be holded somewhere.
// In the High level Deserialize API, `YamlDeserializationContext` does exactly this.
}
}
See test code for more information.
The above test covers various patterns for the order of ParsingEvent
.
Utf8YamlEmitter
struct provides to write YAML formatted string.
Basic usage:
var buffer = new ArrayBufferWriter();
var emitter = new Utf8YamlEmitter(buffer); // It needs buffer implemented `IBufferWriter<byte>`
emitter.BeginMapping(); // Mapping is a collection like Dictionary in YAML
{
emitter.WriteString("key1");
emitter.WriteString("value-1");
emitter.WriteString("key2");
emitter.WriteInt32(222);
emitter.WriteString("key3");
emitter.WriteFloat(3.333f);
}
emitter.EndMapping();
// If you want to expand a string in memory, you can do this.
System.Text.Encoding.UTF8.GetString(buffer.WrittenSpan);
key1: value-1
key2: 222
key3: 3.333
By default, WriteString() automatically determines the format of a scalar.
Multi-line strings are automatically format as a literal scalar:
emitter.WriteString("Hello,\nWorld!\n");
|
Hello,
World!
Special characters contained strings are automatically quoted.
emitter.WriteString("&aaaaa ");
"&aaaaa "
Or you can specify the style explicitly:
emitter.WriteString("aaaaaaa", ScalarStyle.Literal);
|-
aaaaaaaa
e.g:
emitter.BeginSequence();
{
emitter.BeginSequence(SequenceStyle.Flow);
{
emitter.WriteInt32(100);
emitter.WriteString("&hoge");
emitter.WriteString("bra");
}
emitter.EndSequence();
emitter.BeginMapping();
{
emitter.WriteString("key1");
emitter.WriteString("item1");
emitter.WriteString("key2");
emitter.BeginSequence();
{
emitter.WriteString("nested-item1")
emitter.WriteString("nested-item2")
emitter.BeginMapping();
{
emitter.WriteString("nested-key1")
emitter.WriteInt32(100)
}
emitter.EndMapping();
}
emitter.EndSequence();
}
emitter.EndMapping();
}
emitter.EndMapping();
- [100, "&hoge", bra]
- key1: item1
key2:
- nested-item1
- nested-item2
- nested-key1: 100
The following is the default implicit type interpretation.
Basically, it follows YAML Core Schema. https://yaml.org/spec/1.2.2/#103-core-schema
Support | Regular expression | Resolved to type |
---|---|---|
✅ | null | Null | NULL | ~ |
null |
✅ | /* Empty */ |
null |
✅ | true | True | TRUE | false | False | FALSE |
boolean |
✅ | [-+]? [0-9]+ |
int (Base 10) |
✅ | 0o [0-7]+ |
int (Base 8) |
✅ | 0x [0-9a-fA-F]+ |
int (Base 16) |
✅ | [-+]? ( \. [0-9]+ | [0-9]+ ( \. [0-9]* )? ) ( [eE] [-+]? [0-9]+ )? |
float |
✅ | [-+]? ( \.inf | \.Inf | \.INF ) |
float (Infinity) |
✅ | \.nan | \.NaN | \.NAN |
float (Not a number) |
Following is the results of the test for the examples from the yaml spec page.
- 2.1. Collections
- ✅ Example 2.1 Sequence of Scalars (ball players)
- ✅ Example 2.2 Mapping Scalars to Scalars (player statistics)
- ✅ Example 2.3 Mapping Scalars to Sequences (ball clubs in each league)
- ✅ Example 2.4 Sequence of Mappings (players statistics)
- ✅ Example 2.5 Sequence of Sequences
- ✅ Example 2.6 Mapping of Mappings
- 2.2. Structures
- ✅ Example 2.7 Two Documents in a Stream (each with a leading comment)
- ✅ Example 2.8 Play by Play Feed from a Game
- ✅ Example 2.9 Single Document with Two Comments
- ✅ Example 2.10 Node for Sammy Sosa appears twice in this document
- ✅ Example 2.11 Mapping between Sequences
- ✅ Example 2.12 Compact Nested Mapping
- 2.3. Scalars
- ✅ Example 2.13 In literals, newlines are preserved
- ✅ Example 2.14 In the folded scalars, newlines become spaces
- ✅ Example 2.15 Folded newlines are preserved for more indented and blank lines
- ✅ Example 2.16 Indentation determines scope
- ✅ Example 2.17 Quoted Scalars
- ✅ Example 2.18 Multi-line Flow Scalars
- 2.4. Tags
- ✅ Example 2.19 Integers
- ✅ Example 2.20 Floating Point
- ✅ Example 2.21 Miscellaneous
- ✅ Example 2.22 Timestamps
- ✅ Example 2.23 Various Explicit Tags
- ✅ Example 2.24 Global Tags
- ✅ Example 2.25 Unordered Sets
- ✅ Example 2.26 Ordered Mappings
- 2.5. Full Length Example
- ✅ Example 2.27 Invoice
- ✅ Example 2.28 Log File
- 5.2. Character Encodings
- ✅ Example 5.1 Byte Order Mark
- ✅ Example 5.2 Invalid Byte Order Mark
- 5.3. Indicator Characters
- ✅ Example 5.3 Block Structure Indicators
- ✅ Example 5.4 Flow Collection Indicators
- ✅ Example 5.5 Comment Indicator
- ✅ Example 5.6 Node Property Indicators
- ✅ Example 5.7 Block Scalar Indicators
- ✅ Example 5.8 Quoted Scalar Indicators
- ✅ Example 5.9 Directive Indicator
- ✅ Example 5.10 Invalid use of Reserved Indicators
- 5.4. Line Break Characters
- ✅ Example 5.11 Line Break Characters
- ✅ Example 5.12 Tabs and Spaces
- ✅ Example 5.13 Escaped Characters
- ✅ Example 5.14 Invalid Escaped Characters
- 6.1. Indentation Spaces
- ✅ Example 6.1 Indentation Spaces
- ✅ Example 6.2 Indentation Indicators
- 6.2. Separation Spaces
- ✅ Example 6.3 Separation Spaces
- 6.3. Line Prefixes
- ✅ Example 6.4 Line Prefixes
- 6.4. Empty Lines
- ✅ Example 6.5 Empty Lines
- 6.5. Line Folding
- ✅ Example 6.6 Line Folding
- ✅ Example 6.7 Block Folding
- ✅ Example 6.8 Flow Folding
- 6.6. Comments
- ✅ Example 6.9 Separated Comment
- ✅ Example 6.10 Comment Lines
- ✅ Example 6.11 Multi-Line Comments
- 6.7. Separation Lines
- ✅ Example 6.12 Separation Spaces
- 6.8. Directives
- ✅ Example 6.13 Reserved Directives
- ✅ Example 6.14 YAML directive
- ✅ Example 6.15 Invalid Repeated YAML directive
- ✅ Example 6.16 TAG directive
- ✅ Example 6.17 Invalid Repeated TAG directive
- ✅ Example 6.18 Primary Tag Handle
- ✅ Example 6.19 Secondary Tag Handle
- ✅ Example 6.20 Tag Handles
- ✅ Example 6.21 Local Tag Prefix
- ✅ Example 6.22 Global Tag Prefix
- 6.9. Node Properties
- ✅ Example 6.23 Node Properties
- ✅ Example 6.24 Verbatim Tags
- ✅ Example 6.25 Invalid Verbatim Tags
- ✅ Example 6.26 Tag Shorthands
- ✅ Example 6.27 Invalid Tag Shorthands
- ✅ Example 6.28 Non-Specific Tags
- ✅ Example 6.29 Node Anchors
- 7.1. Alias Nodes
- ✅ Example 7.1 Alias Nodes
- 7.2. Empty Nodes
- ✅ Example 7.2 Empty Content
- ✅ Example 7.3 Completely Empty Flow Nodes
- 7.3. Flow Scalar Styles
- ✅ Example 7.4 Double Quoted Implicit Keys
- ✅ Example 7.5 Double Quoted Line Breaks
- ✅ Example 7.6 Double Quoted Lines
- ✅ Example 7.7 Single Quoted Characters
- ✅ Example 7.8 Single Quoted Implicit Keys
- ✅ Example 7.9 Single Quoted Lines
- ✅ Example 7.10 Plain Characters
- ✅ Example 7.11 Plain Implicit Keys
- ✅ Example 7.12 Plain Lines
- 7.4. Flow Collection Styles
- ✅ Example 7.13 Flow Sequence
- ✅ Example 7.14 Flow Sequence Entries
- ✅ Example 7.15 Flow Mappings
- ✅ Example 7.16 Flow Mapping Entries
- ✅ Example 7.17 Flow Mapping Separate Values
- ✅ Example 7.18 Flow Mapping Adjacent Values
- ✅ Example 7.20 Single Pair Explicit Entry
- ❌ Example 7.21 Single Pair Implicit Entries
- ✅ Example 7.22 Invalid Implicit Keys
- ✅ Example 7.23 Flow Content
- ✅ Example 7.24 Flow Nodes
- 8.1. Block Scalar Styles
- ✅ Example 8.1 Block Scalar Header
- ❌ Example 8.2 Block Indentation Indicator
- ✅ Example 8.3 Invalid Block Scalar Indentation Indicators
- ✅ Example 8.4 Chomping Final Line Break
- ✅ Example 8.5 Chomping Trailing Lines
- ✅ Example 8.6 Empty Scalar Chomping
- ✅ Example 8.7 Literal Scalar
- ✅ Example 8.8 Literal Content
- ✅ Example 8.9 Folded Scalar
- ✅ Example 8.10 Folded Lines
- ✅ Example 8.11 More Indented Lines
- ✅ Example 8.12 Empty Separation Lines
- ✅ Example 8.13 Final Empty Lines
- ✅ Example 8.14 Block Sequence
- ✅ Example 8.15 Block Sequence Entry Types
- ✅ Example 8.16 Block Mappings
- ✅ Example 8.17 Explicit Block Mapping Entries
- ✅ Example 8.18 Implicit Block Mapping Entries
- ✅ Example 8.19 Compact Block Mappings
- ✅ Example 8.20 Block Node Types
- ✅ Example 8.21 Block Scalar Nodes
- ✅ Example 8.22 Block Collection Nodes
LiteYaml is a stripped back version of VYaml with minor updates.