Newer
Older
dub_jkp / source / dub / internal / dyaml / event.d
  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 dub.internal.dyaml.event;
  12.  
  13. import std.array;
  14. import std.conv;
  15.  
  16. import dub.internal.dyaml.exception;
  17. import dub.internal.dyaml.reader;
  18. import dub.internal.dyaml.tagdirective;
  19. import dub.internal.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. }