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