1 2 // Copyright Ferdinand Majerech 2011-2014. 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 /// YAML tokens. 8 /// Code based on PyYAML: http://www.pyyaml.org 9 module dyaml.token; 10 11 12 import std.conv; 13 14 import dyaml.encoding; 15 import dyaml.exception; 16 import dyaml.reader; 17 import dyaml.style; 18 19 20 package: 21 22 /// Token types. 23 enum TokenID : ubyte 24 { 25 // Invalid (uninitialized) token 26 invalid = 0, 27 directive, 28 documentStart, 29 documentEnd, 30 streamStart, 31 streamEnd, 32 blockSequenceStart, 33 blockMappingStart, 34 blockEnd, 35 flowSequenceStart, 36 flowMappingStart, 37 flowSequenceEnd, 38 flowMappingEnd, 39 key, 40 value, 41 blockEntry, 42 flowEntry, 43 alias_, 44 anchor, 45 tag, 46 scalar 47 } 48 49 /// Specifies the type of a tag directive token. 50 enum DirectiveType : ubyte 51 { 52 // YAML version directive. 53 yaml, 54 // Tag directive. 55 tag, 56 // Any other directive is "reserved" for future YAML versions. 57 reserved 58 } 59 60 /// Token produced by scanner. 61 /// 62 /// 32 bytes on 64-bit. 63 struct Token 64 { 65 @disable int opCmp(ref Token); 66 67 // 16B 68 /// Value of the token, if any. 69 /// 70 /// Values are char[] instead of string, as Parser may still change them in a few 71 /// cases. Parser casts values to strings when producing Events. 72 char[] value; 73 // 4B 74 /// Start position of the token in file/stream. 75 Mark startMark; 76 // 4B 77 /// End position of the token in file/stream. 78 Mark endMark; 79 // 1B 80 /// Token type. 81 TokenID id; 82 // 1B 83 /// Style of scalar token, if this is a scalar token. 84 ScalarStyle style; 85 // 1B 86 /// Encoding, if this is a stream start token. 87 Encoding encoding; 88 // 1B 89 /// Type of directive for directiveToken. 90 DirectiveType directive; 91 // 4B 92 /// Used to split value into 2 substrings for tokens that need 2 values (tagToken) 93 uint valueDivider; 94 95 /// Get string representation of the token ID. 96 @property string idString() @safe pure const {return id.to!string;} 97 } 98 99 /// Construct a directive token. 100 /// 101 /// Params: start = Start position of the token. 102 /// end = End position of the token. 103 /// value = Value of the token. 104 /// directive = Directive type (YAML or TAG in YAML 1.1). 105 /// nameEnd = Position of the end of the name 106 Token directiveToken(const Mark start, const Mark end, char[] value, 107 DirectiveType directive, const uint nameEnd) @safe pure nothrow @nogc 108 { 109 return Token(value, start, end, TokenID.directive, ScalarStyle.init, Encoding.init, 110 directive, nameEnd); 111 } 112 113 /// Construct a simple (no value) token with specified type. 114 /// 115 /// Params: id = Type of the token. 116 /// start = Start position of the token. 117 /// end = End position of the token. 118 Token simpleToken(TokenID id)(const Mark start, const Mark end) 119 { 120 return Token(null, start, end, id); 121 } 122 123 /// Construct a stream start token. 124 /// 125 /// Params: start = Start position of the token. 126 /// end = End position of the token. 127 /// encoding = Encoding of the stream. 128 Token streamStartToken(const Mark start, const Mark end, const Encoding encoding) @safe pure nothrow @nogc 129 { 130 return Token(null, start, end, TokenID.streamStart, ScalarStyle.invalid, encoding); 131 } 132 133 /// Aliases for construction of simple token types. 134 alias streamEndToken = simpleToken!(TokenID.streamEnd); 135 alias blockSequenceStartToken = simpleToken!(TokenID.blockSequenceStart); 136 alias blockMappingStartToken = simpleToken!(TokenID.blockMappingStart); 137 alias blockEndToken = simpleToken!(TokenID.blockEnd); 138 alias keyToken = simpleToken!(TokenID.key); 139 alias valueToken = simpleToken!(TokenID.value); 140 alias blockEntryToken = simpleToken!(TokenID.blockEntry); 141 alias flowEntryToken = simpleToken!(TokenID.flowEntry); 142 143 /// Construct a simple token with value with specified type. 144 /// 145 /// Params: id = Type of the token. 146 /// start = Start position of the token. 147 /// end = End position of the token. 148 /// value = Value of the token. 149 /// valueDivider = A hack for TagToken to store 2 values in value; the first 150 /// value goes up to valueDivider, the second after it. 151 Token simpleValueToken(TokenID id)(const Mark start, const Mark end, char[] value, 152 const uint valueDivider = uint.max) 153 { 154 return Token(value, start, end, id, ScalarStyle.invalid, Encoding.init, 155 DirectiveType.init, valueDivider); 156 } 157 158 /// Alias for construction of tag token. 159 alias tagToken = simpleValueToken!(TokenID.tag); 160 alias aliasToken = simpleValueToken!(TokenID.alias_); 161 alias anchorToken = simpleValueToken!(TokenID.anchor); 162 163 /// Construct a scalar token. 164 /// 165 /// Params: start = Start position of the token. 166 /// end = End position of the token. 167 /// value = Value of the token. 168 /// style = Style of the token. 169 Token scalarToken(const Mark start, const Mark end, char[] value, const ScalarStyle style) @safe pure nothrow @nogc 170 { 171 return Token(value, start, end, TokenID.scalar, style); 172 }