module YAML::Nodes # Abstract class of all YAML tree nodes. abstract class Node # The optional tag of a node. property tag : String? # The optional anchor of a node. property anchor : String? # The line where this node starts. property start_line = 0 # The column where this node starts. property start_column = 0 # The line where this node ends. property end_line = 0 # The column where this node ends. property end_column = 0 # Returns a tuple of `start_line` and `start_column`. def location : {Int32, Int32} {start_line, start_column} end # Raises a `YAML::ParseException` with the given message # located at this node's `location`. def raise(message) : NoReturn ::raise YAML::ParseException.new(message, *location) end # Returns the kind of this node, which is equivalent to the class name. abstract def kind : String end # A YAML document. class Document < Node # The nodes inside this document. # # A document can hold at most one node. getter nodes = [] of Node # Appends a node to this document. Raises if more # than one node is appended. def <<(node) if nodes.empty? nodes << node else raise ArgumentError.new("Attempted to append more than one node") end end def to_yaml(builder : YAML::Builder) : Nil nodes.each &.to_yaml(builder) end def kind : String "document" end end # A scalar value. class Scalar < Node # The style of this scalar. property style : ScalarStyle = ScalarStyle::ANY # The value of this scalar. property value : String # Creates a scalar with the given *value*. def initialize(@value : String) end def to_yaml(builder : YAML::Builder) : Nil builder.scalar(value, anchor, tag, style) end def kind : String "scalar" end end # A sequence of nodes. class Sequence < Node include Enumerable(Node) # The nodes in this sequence. getter nodes = [] of Node # The style of this sequence. property style : SequenceStyle = SequenceStyle::ANY # Appends a node into this sequence. def <<(node) @nodes << node end def each(&) @nodes.each do |node| yield node end end def to_yaml(builder : YAML::Builder) : Nil builder.sequence(anchor, tag, style) do each &.to_yaml(builder) end end def kind : String "sequence" end end # A mapping of nodes. class Mapping < Node property style : MappingStyle = MappingStyle::ANY # The nodes inside this mapping, stored linearly # as key1 - value1 - key2 - value2 - etc. getter nodes = [] of Node # Appends two nodes into this mapping. def []=(key, value) @nodes << key << value end # Appends a single node into this mapping. def <<(node) @nodes << node end # Yields each key-value pair in this mapping. def each(&) 0.step(by: 2, to: @nodes.size - 1) do |i| yield({@nodes[i], @nodes[i + 1]}) end end def to_yaml(builder : YAML::Builder) : Nil builder.mapping(anchor, tag, style) do each do |key, value| key.to_yaml(builder) value.to_yaml(builder) end end end def kind : String "mapping" end end # An alias. class Alias < Node # The node this alias points to. # This is set by `YAML::Nodes.parse`, and is `nil` by default. property value : Node? # Creates an alias with the given *anchor*. def initialize(@anchor : String) end def to_yaml(builder : YAML::Builder) : Nil builder.alias(anchor.not_nil!) end def kind : String "alias" end end end