diff options
Diffstat (limited to 'src/ext_depends/D-YAML/docs/tutorials')
-rw-r--r-- | src/ext_depends/D-YAML/docs/tutorials/custom_types.md | 258 | ||||
-rw-r--r-- | src/ext_depends/D-YAML/docs/tutorials/getting_started.md | 140 | ||||
-rw-r--r-- | src/ext_depends/D-YAML/docs/tutorials/yaml_syntax.md | 241 |
3 files changed, 639 insertions, 0 deletions
diff --git a/src/ext_depends/D-YAML/docs/tutorials/custom_types.md b/src/ext_depends/D-YAML/docs/tutorials/custom_types.md new file mode 100644 index 0000000..7e4e10b --- /dev/null +++ b/src/ext_depends/D-YAML/docs/tutorials/custom_types.md @@ -0,0 +1,258 @@ +# Custom YAML data types + +Sometimes you need to serialize complex data types such as classes. To +do this you could use plain nodes such as mappings with classes' fields. +YAML also supports custom types with identifiers called *tags*. That is +the topic of this tutorial. + +Each YAML node has a tag specifying its type. For instance: strings use +the tag `tag:yaml.org,2002:str`. Tags of most default types are +*implicitly resolved* during parsing - you don't need to specify tag for +each float, integer, etc. D:YAML can also implicitly resolve custom +tags, as we will show later. + +## Constructor + +D:YAML supports conversion to user-defined types. Adding a constructor to read +the data from the node is all that is needed. + +We will implement support for an RGB color type. It is implemented as +the following struct: + +```D +struct Color +{ + ubyte red; + ubyte green; + ubyte blue; +} +``` + +First, we need our type to have an appropriate constructor. The constructor +will take a const *Node* to construct from. The node is guaranteed to +contain either a *string*, an array of *Node* or of *Node.Pair*, +depending on whether we're constructing our value from a scalar, +sequence, or mapping, respectively. + +In this tutorial, we have a constructor to construct a color from a scalar, +using CSS-like format, RRGGBB, or from a mapping, where we use the +following format: {r:RRR, g:GGG, b:BBB} . Code of these functions: + +```D + +this(const Node node, string tag) @safe +{ + if (tag == "!color-mapping") + { + //Will throw if a value is missing, is not an integer, or is out of range. + red = node["r"].as!ubyte; + green = node["g"].as!ubyte; + blue = node["b"].as!ubyte; + } + else + { + string value = node.as!string; + + if(value.length != 6) + { + throw new Exception("Invalid color: " ~ value); + } + //We don't need to check for uppercase chars this way. + value = value.toLower(); + + //Get value of a hex digit. + uint hex(char c) + { + import std.ascii; + if(!std.ascii.isHexDigit(c)) + { + throw new Exception("Invalid color: " ~ value); + } + + if(std.ascii.isDigit(c)) + { + return c - '0'; + } + return c - 'a' + 10; + } + + red = cast(ubyte)(16 * hex(value[0]) + hex(value[1])); + green = cast(ubyte)(16 * hex(value[2]) + hex(value[3])); + blue = cast(ubyte)(16 * hex(value[4]) + hex(value[5])); + } +} +``` + +Next, we need some YAML data using our new tag. Create a file called +`input.yaml` with the following contents: + +```YAML +scalar-red: !color FF0000 +scalar-orange: !color FFFF00 +mapping-red: !color-mapping {r: 255, g: 0, b: 0} +mapping-orange: + !color-mapping + r: 255 + g: 255 + b: 0 +``` + +You can see that we're using tag `!color` for scalar colors, and +`!color-mapping` for colors expressed as mappings. + +Finally, the code to put it all together: + +```D +void main() +{ + auto red = Color(255, 0, 0); + auto orange = Color(255, 255, 0); + + try + { + auto root = Loader.fromFile("input.yaml").load(); + + if(root["scalar-red"].as!Color == red && + root["mapping-red"].as!Color == red && + root["scalar-orange"].as!Color == orange && + root["mapping-orange"].as!Color == orange) + { + writeln("SUCCESS"); + return; + } + } + catch(YAMLException e) + { + writeln(e.msg); + } + + writeln("FAILURE"); +} +``` + +First we load the YAML document, and then have the resulting *Node*s converted +to Colors via their constructor. + +You can find the source code for what we've done so far in the +`examples/constructor` directory in the D:YAML package. + +## Resolver + +Specifying tag for every color can be tedious. D:YAML can implicitly +resolve scalar tags using regular expressions. This is how default types +are resolved. We will use the [Resolver](../api/dyaml.resolver.html) +class to add implicit tag resolution for the Color data type (in its +scalar form). + +We use the *addImplicitResolver()* method of *Resolver*, passing the +tag, regular expression the scalar must match to resolve to this tag, +and a string of possible starting characters of the scalar. Then we pass +the *Resolver* to *Loader*. + +Note that resolvers added first override ones added later. If no +resolver matches a scalar, YAML string tag is used. Therefore our custom +values must not be resolvable as any non-string YAML data type. + +Add this to your code to add implicit resolution of `!color`. + +```D +import std.regex; +auto resolver = new Resolver; +resolver.addImplicitResolver("!color", regex("[0-9a-fA-F]{6}"), + "0123456789abcdefABCDEF"); + +auto loader = Loader.fromFile("input.yaml"); + +loader.resolver = resolver; +``` + +Now, change contents of `input.yaml` to this: + +```YAML +scalar-red: FF0000 +scalar-orange: FFFF00 +mapping-red: !color-mapping {r: 255, g: 0, b: 0} +mapping-orange: + !color-mapping + r: 255 + g: 255 + b: 0 +``` + +We no longer need to specify the tag for scalar color values. Compile +and test the example. If everything went as expected, it should report +success. + +You can find the complete code in the `examples/resolver` directory in +the D:YAML package. + +## Representer + +Now that you can load custom data types, it might be good to know how to +dump them. + +The *Node* struct simply attempts to cast all unrecognized types to *Node*. +This gives each type a consistent and simple way of being represented in a +document. All we need to do is specify a `Node opCast(T: Node)()` method for +any types we wish to support. It is also possible to specify specific styles +for each representation. + +Each type may only have one opCast!Node. Default YAML types are already +supported. + +With the following code, we will add support for dumping the our Color +type. + +```D +Node opCast(T: Node)() const +{ + static immutable hex = "0123456789ABCDEF"; + + //Using the color format from the Constructor example. + string scalar; + foreach(channel; [red, green, blue]) + { + scalar ~= hex[channel / 16]; + scalar ~= hex[channel % 16]; + } + + //Representing as a scalar, with custom tag to specify this data type. + return Node(scalar, "!color"); +} +``` + +First we convert the colour data to a string with the CSS-like format we've +used before. Then, we create a scalar *Node* with our desired tag. + +Since a type can only have one opCast!Node method, we don't dump +*Color* both in the scalar and mapping formats we've used before. +However, you can decide to dump the node with different formats/tags in +the method itself. E.g. you could dump the Color as a +mapping based on some arbitrary condition, such as the color being +white. + +```D +void main() +{ + try + { + auto dumper = dumper(File("output.yaml", "w").lockingTextWriter); + + auto document = Node([Color(255, 0, 0), + Color(0, 255, 0), + Color(0, 0, 255)]); + + dumper.dump(document); + } + catch(YAMLException e) + { + writeln(e.msg); + } +} +``` + +We construct a *Dumper* to file `output.yaml`. Then, we create a simple node +containing a sequence of colors and finally, we dump it. + +Source code for this section can be found in the `examples/representer` +directory of the D:YAML package. diff --git a/src/ext_depends/D-YAML/docs/tutorials/getting_started.md b/src/ext_depends/D-YAML/docs/tutorials/getting_started.md new file mode 100644 index 0000000..58cf191 --- /dev/null +++ b/src/ext_depends/D-YAML/docs/tutorials/getting_started.md @@ -0,0 +1,140 @@ +# Getting started + +Welcome to D:YAML\! D:YAML is a +[YAML](http://en.wikipedia.org/wiki/YAML) parser library for the [D +programming language](http://dlang.org). This tutorial will explain how +to set D:YAML up and use it in your projects. + +This is meant to be the **simplest possible** introduction to D:YAML. +Some of this information might already be known to you. Only basic usage +is covered. + +## Setting up + +### Install the DMD compiler + +Digital Mars D compiler, or DMD, is the most commonly used D compiler. +You can find its newest version [here](http://dlang.org/download.html). +Download the version of DMD for your operating system and install it. + +Note: Other D compilers exist, such as [GDC](http://gdcproject.org/) and +[LDC](https://github.com/ldc-developers/ldc). + +## Your first D:YAML project + +First, create a directory for your project and navigate to that directory +using your preferred command line. Then simply execute these two commands: + + dub init + dub add dyaml + +In that directory, create a new file named `input.yaml` and paste this data +into the file: + +```YAML +Hello World : [Hello, World] +Answer: 42 +``` + +This will serve as input for our example. + +Now we need to parse it. Open the file named `source/app.d` and paste the +following code into the file: + +```D +import std.stdio; +import dyaml; + +void main() +{ + //Read the input. + Node root = Loader.fromFile("input.yaml").load(); + + //Display the data read. + foreach(string word; root["Hello World"]) + { + writeln(word); + } + writeln("The answer is ", root["Answer"].as!int); + + //Dump the loaded document to output.yaml. + dumper(File("output.yaml", "w").lockingTextWriter).dump(root); +} +``` + +### Explanation of the code + +First, we import the *dyaml* module. This is the only D:YAML module +you need to import - it automatically imports all needed modules. + +Next we load the file using the *Loader.fromFile().load()* method. *Loader* is a +struct used for parsing YAML documents. The *fromFile()* method loads the +document from a file. The *load()* method loads the +file as **one** YAML document, or throws *YAMLException*, D:YAML +exception type, if the file could not be parsed or contains more than +one document. Note that we don't do any error checking here in order to +keep the example as simple as possible. + +*Node* represents a node in a YAML document. It can be a sequence +(array), mapping (associative array) or a scalar (value). Here the root +node is a mapping, and we use the index operator to get subnodes with +keys "Hello World" and "Answer". We iterate over the former, as it is a +sequence, and use the *Node.as()* method on the latter to read its value +as an integer. + +You can iterate over a mapping or sequence as if it was an associative +or normal array, respectively. If you try to iterate over a scalar, it +will throw a *YAMLException*. + +You can iterate using *Node* as the iterated type, or specify the type +iterated nodes are expected to have. D:YAML will automatically convert +to that type if possible. Here we specify the *string* type, so we +iterate over the "Hello World" sequence as an array of strings. If it is +not possible to convert to iterated type, a *YAMLException* is thrown. +For instance, if we specified *int* here, we would get an error, as +"Hello" cannot be converted to an integer. + +The *Node.as()* method is used to read value of a scalar node as +specified type. If the scalar does not have the specified type, D:YAML +will try to convert it, throwing *YAMLException* if not possible. + +Finally we dump the document we just read to `output.yaml` with the +*Dumper.dump()* method. *Dumper* is a struct used to dump YAML +documents. *dumper()* accepts a range to write the document to. +The *dump()* method writes one or more documents to the range, +throwing *YAMLException* if it could not be written to. + +D:YAML tries to preserve style information in documents so e.g. `[Hello, +World]` is not turned into: + +```YAML +- Hello +- World +``` + +However, comments are not preserved and neither are any extra formatting +whitespace that doesn't affect the meaning of YAML contents. + +### Compiling + +Run the following command in your project's directory: + + dub build + +DUB will automatically download D:YAML and compile it, and then it +will compile our program. This will generate an executable called +`getting-started` or `getting-started.exe` in your directory. When you +run it, it should produce the following output: + + Hello + World + The answer is 42 + +You may also run ```dub run``` to combine the compile+run steps. + +### Conclusion + +You should now have a basic idea about how to use D:YAML. To learn more, +look at the [API documentation](https://dyaml.dpldocs.info/dyaml.html) and other tutorials. +You can find code for this example in the `example/getting_started` +directory in the package. diff --git a/src/ext_depends/D-YAML/docs/tutorials/yaml_syntax.md b/src/ext_depends/D-YAML/docs/tutorials/yaml_syntax.md new file mode 100644 index 0000000..2df7f8b --- /dev/null +++ b/src/ext_depends/D-YAML/docs/tutorials/yaml_syntax.md @@ -0,0 +1,241 @@ +# YAML syntax + +This is an introduction to the most common YAML constructs. For more detailed +information, see [PyYAML documentation](http://pyyaml.org/wiki/PyYAMLDocumentation), +which this article is based on, +[Chapter 2 of the YAML specification](http://yaml.org/spec/1.1/#id857168) +or the [Wikipedia page](http://en.wikipedia.org/wiki/YAML). + +YAML is a data serialization format designed for human readability. YAML is a +recursive acronym for "YAML Ain't Markup Language". + +YAML is similar to JSON, and in fact, JSON is a subset of YAML 1.2; but YAML has +some more advanced features and is easier to read. However, it is also more +difficult to parse (and probably somewhat slower). Data is stored in mappings +(associative arrays), sequences (lists) and scalars (single values). Data +structure hierarchy depends either on indentation (block context, similar to +Python code), or nesting of brackets and braces (flow context, similar to JSON). +YAML comments begin with `#` and continue until the end of line. + + +## Documents + +A YAML stream consists of one or more documents starting with `---` and +optionally ending with `...` . `---` can be left out for the first document. + +Single document with no explicit start or end: + +``` + - Red + - Green + - Blue +``` +Same document with explicit start and end: +``` + --- + - Red + - Green + - Blue + ... +``` +A stream containing multiple documents: +``` + --- + - Red + - Green + - Blue + --- + - Linux + - BSD + --- + answer : 42 +``` + +## Sequences + +Sequences are arrays of nodes of any type, similar e.g. to Python lists. +In block context, each item begins with hyphen+space "- ". In flow context, +sequences have syntax similar to D arrays. + +``` + #Block context + - Red + - Green + - Blue +``` +``` + #Flow context + [Red, Green, Blue] +``` +``` + #Nested + - + - Red + - Green + - Blue + - + - Linux + - BSD +``` +``` + #Nested flow + [[Red, Green, Blue], [Linux, BSD]] +``` +``` + #Nested in a mapping + Colors: + - Red + - Green + - Blue + Operating systems: + - Linux + - BSD +``` + +## Mappings + +Mappings are associative arrays where each key and value can be of any type, +similar e.g. to Python dictionaries. In block context, keys and values are +separated by colon+space ": ". In flow context, mappings have syntax similar +to D associative arrays, but with braces instead of brackets: + +``` + #Block context + CPU: Athlon + GPU: Radeon + OS: Linux + +``` +``` + #Flow context + {CPU: Athlon, GPU: Radeon, OS: Linux} + +``` +``` + #Nested + PC: + CPU: Athlon + GPU: Radeon + OS: Debian + Phone: + CPU: Cortex + GPU: PowerVR + OS: Android + +``` +``` + #Nested flow + {PC: {CPU: Athlon, GPU: Radeon, OS: Debian}, + Phone: {CPU: Cortex, GPU: PowerVR, OS: Android}} +``` +``` + #Nested in a sequence + - CPU: Athlon + GPU: Radeon + OS: Debian + - CPU: Cortex + GPU: PowerVR + OS: Android +``` + +Complex keys start with question mark+space "? ". + +``` + #Nested in a sequence + ? [CPU, GPU]: [Athlon, Radeon] + OS: Debian +``` + +## Scalars + +Scalars are simple values such as integers, strings, timestamps and so on. +There are multiple scalar styles. + +Plain scalars use no quotes, start with the first non-space and end with the +last non-space character: + +``` + scalar: Plain scalar +``` + +Single quoted scalars start and end with single quotes. A single quote is +represented by a pair of single quotes ''. + +``` + scalar: 'Single quoted scalar ending with some spaces ' +``` + +Double quoted scalars support C-style escape sequences. + +``` + scalar: "Double quoted scalar \n with some \\ escape sequences" +``` + +Block scalars are convenient for multi-line values. They start either with +`|` or with `>`. With `|`, the newlines in the scalar are preserved. +With `>`, the newlines between two non-empty lines are removed. + +``` + scalar: | + Newlines are preserved + First line + Second line +``` +``` + scalar: > + Newlines are folded + This is still the first paragraph + + This is the second + paragraph +``` + +## Anchors and aliases + +Anchors and aliases can reduce size of YAML code by allowing you to define a +value once, assign an anchor to it and use alias referring to that anchor +anywhere else you need that value. It is possible to use this to create +recursive data structures and some parsers support this; however, D:YAML does +not (this might change in the future, but it is unlikely). + +``` + Person: &AD + gender: male + name: Arthur Dent + Clone: *AD +``` + +## Tags + +Tags are identifiers that specify data types of YAML nodes. Most default YAML +tags are resolved implicitly, so there is no need to specify them. D:YAML also +supports implicit resolution for custom, user specified tags. + +Explicitly specified tags: + +``` + answer: !!int "42" + name: !!str "Arthur Dent" +``` + +Implicit tags: + +``` + answer: 42 #int + name: Arthur Dent #string +``` + +This table shows D types stored in *yaml.Node* default YAML tags are converted to. +Some of these might change in the future (especially !!map and !!set). + +|YAML tag |D type | +|-----------------------|-----------------------| +|!!null |dyaml.node.YAMLNull | +|!!bool |bool | +|!!int |long | +|!!float |real | +|!!binary |ubyte[] | +|!!timestamp |std.datetime.SysTime | +|!!map, !!omap, !!pairs |dyaml.node.Node.Pair[] | +|!!seq, !!set |dyaml.node.Node[] | +|!!str |string | |