1 2 // Copyright Ferdinand Majerech 2011. 3 // Distributed under the Boost Software License, Version 1.0. 4 // (See accompanying file LICENSE_1_0.txt or copy at 5 // http://www.boost.org/LICENSE_1_0.txt) 6 7 /** 8 * YAML events. 9 * Code based on PyYAML: http://www.pyyaml.org 10 */ 11 module dyaml.event; 12 13 import std.array; 14 import std.conv; 15 import std.typecons; 16 17 import dyaml.anchor; 18 import dyaml.encoding; 19 import dyaml.exception; 20 import dyaml.reader; 21 import dyaml.tag; 22 import dyaml.tagdirective; 23 import dyaml.style; 24 25 26 package: 27 ///Event types. 28 enum EventID : ubyte 29 { 30 Invalid = 0, /// Invalid (uninitialized) event. 31 StreamStart, /// Stream start 32 StreamEnd, /// Stream end 33 DocumentStart, /// Document start 34 DocumentEnd, /// Document end 35 Alias, /// Alias 36 Scalar, /// Scalar 37 SequenceStart, /// Sequence start 38 SequenceEnd, /// Sequence end 39 MappingStart, /// Mapping start 40 MappingEnd /// Mapping end 41 } 42 43 /** 44 * YAML event produced by parser. 45 * 46 * 48 bytes on 64bit. 47 */ 48 struct Event 49 { 50 @disable int opCmp(ref Event); 51 52 ///Value of the event, if any. 53 string value; 54 ///Start position of the event in file/stream. 55 Mark startMark; 56 ///End position of the event in file/stream. 57 Mark endMark; 58 union 59 { 60 struct 61 { 62 ///Anchor of the event, if any. 63 Anchor anchor; 64 ///Tag of the event, if any. 65 Tag tag; 66 } 67 ///Tag directives, if this is a DocumentStart. 68 //TagDirectives tagDirectives; 69 TagDirective[] tagDirectives; 70 } 71 ///Event type. 72 EventID id = EventID.Invalid; 73 ///Style of scalar event, if this is a scalar event. 74 ScalarStyle scalarStyle = ScalarStyle.Invalid; 75 union 76 { 77 ///Should the tag be implicitly resolved? 78 bool implicit; 79 /** 80 * Is this document event explicit? 81 * 82 * Used if this is a DocumentStart or DocumentEnd. 83 */ 84 bool explicitDocument; 85 } 86 ///TODO figure this out - Unknown, used by PyYAML with Scalar events. 87 bool implicit_2; 88 ///Encoding of the stream, if this is a StreamStart. 89 Encoding encoding; 90 ///Collection style, if this is a SequenceStart or MappingStart. 91 CollectionStyle collectionStyle = CollectionStyle.Invalid; 92 93 ///Is this a null (uninitialized) event? 94 @property bool isNull() const pure @system nothrow {return id == EventID.Invalid;} 95 96 ///Get string representation of the token ID. 97 @property string idString() const @system {return to!string(id);} 98 99 static assert(Event.sizeof <= 48, "Event struct larger than expected"); 100 } 101 102 /** 103 * Construct a simple event. 104 * 105 * Params: start = Start position of the event in the file/stream. 106 * end = End position of the event in the file/stream. 107 * anchor = Anchor, if this is an alias event. 108 */ 109 Event event(EventID id)(const Mark start, const Mark end, const Anchor anchor = Anchor()) 110 pure @trusted nothrow 111 { 112 Event result; 113 result.startMark = start; 114 result.endMark = end; 115 result.anchor = anchor; 116 result.id = id; 117 return result; 118 } 119 120 /** 121 * Construct a collection (mapping or sequence) start event. 122 * 123 * Params: start = Start position of the event in the file/stream. 124 * end = End position of the event in the file/stream. 125 * anchor = Anchor of the sequence, if any. 126 * tag = Tag of the sequence, if specified. 127 * implicit = Should the tag be implicitly resolved? 128 */ 129 Event collectionStartEvent(EventID id) 130 (const Mark start, const Mark end, const Anchor anchor, const Tag tag, 131 const bool implicit, const CollectionStyle style) pure @trusted nothrow 132 { 133 static assert(id == EventID.SequenceStart || id == EventID.SequenceEnd || 134 id == EventID.MappingStart || id == EventID.MappingEnd); 135 Event result; 136 result.startMark = start; 137 result.endMark = end; 138 result.anchor = anchor; 139 result.tag = tag; 140 result.id = id; 141 result.implicit = implicit; 142 result.collectionStyle = style; 143 return result; 144 } 145 146 /** 147 * Construct a stream start event. 148 * 149 * Params: start = Start position of the event in the file/stream. 150 * end = End position of the event in the file/stream. 151 * encoding = Encoding of the stream. 152 */ 153 Event streamStartEvent(const Mark start, const Mark end, const Encoding encoding) 154 pure @trusted nothrow 155 { 156 Event result; 157 result.startMark = start; 158 result.endMark = end; 159 result.id = EventID.StreamStart; 160 result.encoding = encoding; 161 return result; 162 } 163 164 ///Aliases for simple events. 165 alias event!(EventID.StreamEnd) streamEndEvent; 166 alias event!(EventID.Alias) aliasEvent; 167 alias event!(EventID.SequenceEnd) sequenceEndEvent; 168 alias event!(EventID.MappingEnd) mappingEndEvent; 169 170 ///Aliases for collection start events. 171 alias collectionStartEvent!(EventID.SequenceStart) sequenceStartEvent; 172 alias collectionStartEvent!(EventID.MappingStart) mappingStartEvent; 173 174 /** 175 * Construct a document start event. 176 * 177 * Params: start = Start position of the event in the file/stream. 178 * end = End position of the event in the file/stream. 179 * explicit = Is this an explicit document start? 180 * YAMLVersion = YAML version string of the document. 181 * tagDirectives = Tag directives of the document. 182 */ 183 Event documentStartEvent(const Mark start, const Mark end, const bool explicit, string YAMLVersion, 184 TagDirective[] tagDirectives) pure @trusted nothrow 185 { 186 Event result; 187 result.value = YAMLVersion; 188 result.startMark = start; 189 result.endMark = end; 190 result.id = EventID.DocumentStart; 191 result.explicitDocument = explicit; 192 result.tagDirectives = tagDirectives; 193 return result; 194 } 195 196 /** 197 * Construct a document end event. 198 * 199 * Params: start = Start position of the event in the file/stream. 200 * end = End position of the event in the file/stream. 201 * explicit = Is this an explicit document end? 202 */ 203 Event documentEndEvent(const Mark start, const Mark end, const bool explicit) pure @trusted nothrow 204 { 205 Event result; 206 result.startMark = start; 207 result.endMark = end; 208 result.id = EventID.DocumentEnd; 209 result.explicitDocument = explicit; 210 return result; 211 } 212 213 /// Construct a scalar event. 214 /// 215 /// Params: start = Start position of the event in the file/stream. 216 /// end = End position of the event in the file/stream. 217 /// anchor = Anchor of the scalar, if any. 218 /// tag = Tag of the scalar, if specified. 219 /// implicit = Should the tag be implicitly resolved? 220 /// value = String value of the scalar. 221 /// style = Scalar style. 222 Event scalarEvent(const Mark start, const Mark end, const Anchor anchor, const Tag tag, 223 const Tuple!(bool, bool) implicit, const string value, 224 const ScalarStyle style = ScalarStyle.Invalid) @safe pure nothrow @nogc 225 { 226 Event result; 227 result.value = value; 228 result.startMark = start; 229 result.endMark = end; 230 231 () @trusted { 232 result.anchor = anchor; 233 result.tag = tag; 234 }(); 235 236 result.id = EventID.Scalar; 237 result.scalarStyle = style; 238 result.implicit = implicit[0]; 239 result.implicit_2 = implicit[1]; 240 return result; 241 }