scratch – Diff between revs 75 and 125

Subversion Repositories:
Rev:
Only display areas with differencesIgnore whitespace
Rev 75 Rev 125
1   1  
2 Pattern = require './Pattern' 2 Pattern = require './Pattern'
3 Unescaper = require './Unescaper' 3 Unescaper = require './Unescaper'
4 Escaper = require './Escaper' 4 Escaper = require './Escaper'
5 Utils = require './Utils' 5 Utils = require './Utils'
6 ParseException = require './Exception/ParseException' 6 ParseException = require './Exception/ParseException'
-   7 ParseMore = require './Exception/ParseMore'
7 DumpException = require './Exception/DumpException' 8 DumpException = require './Exception/DumpException'
8   9  
9 # Inline YAML parsing and dumping 10 # Inline YAML parsing and dumping
10 class Inline 11 class Inline
11   12  
12 # Quoted string regular expression 13 # Quoted string regular expression
13 @REGEX_QUOTED_STRING: '(?:"(?:[^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'(?:[^\']*(?:\'\'[^\']*)*)\')' 14 @REGEX_QUOTED_STRING: '(?:"(?:[^"\\\\]*(?:\\\\.[^"\\\\]*)*)"|\'(?:[^\']*(?:\'\'[^\']*)*)\')'
14   15  
15 # Pre-compiled patterns 16 # Pre-compiled patterns
16 # 17 #
17 @PATTERN_TRAILING_COMMENTS: new Pattern '^\\s*#.*$' 18 @PATTERN_TRAILING_COMMENTS: new Pattern '^\\s*#.*$'
18 @PATTERN_QUOTED_SCALAR: new Pattern '^'+@REGEX_QUOTED_STRING 19 @PATTERN_QUOTED_SCALAR: new Pattern '^'+@REGEX_QUOTED_STRING
19 @PATTERN_THOUSAND_NUMERIC_SCALAR: new Pattern '^(-|\\+)?[0-9,]+(\\.[0-9]+)?$' 20 @PATTERN_THOUSAND_NUMERIC_SCALAR: new Pattern '^(-|\\+)?[0-9,]+(\\.[0-9]+)?$'
20 @PATTERN_SCALAR_BY_DELIMITERS: {} 21 @PATTERN_SCALAR_BY_DELIMITERS: {}
21   22  
22 # Settings 23 # Settings
23 @settings: {} 24 @settings: {}
24   25  
25   26  
26 # Configure YAML inline. 27 # Configure YAML inline.
27 # 28 #
28 # @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise 29 # @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise
29 # @param [Function] objectDecoder A function to deserialize custom objects, null otherwise 30 # @param [Function] objectDecoder A function to deserialize custom objects, null otherwise
30 # 31 #
31 @configure: (exceptionOnInvalidType = null, objectDecoder = null) -> 32 @configure: (exceptionOnInvalidType = null, objectDecoder = null) ->
32 # Update settings 33 # Update settings
33 @settings.exceptionOnInvalidType = exceptionOnInvalidType 34 @settings.exceptionOnInvalidType = exceptionOnInvalidType
34 @settings.objectDecoder = objectDecoder 35 @settings.objectDecoder = objectDecoder
35 return 36 return
36   37  
37   38  
38 # Converts a YAML string to a JavaScript object. 39 # Converts a YAML string to a JavaScript object.
39 # 40 #
40 # @param [String] value A YAML string 41 # @param [String] value A YAML string
41 # @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise 42 # @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise
42 # @param [Function] objectDecoder A function to deserialize custom objects, null otherwise 43 # @param [Function] objectDecoder A function to deserialize custom objects, null otherwise
43 # 44 #
44 # @return [Object] A JavaScript object representing the YAML string 45 # @return [Object] A JavaScript object representing the YAML string
45 # 46 #
46 # @throw [ParseException] 47 # @throw [ParseException]
47 # 48 #
48 @parse: (value, exceptionOnInvalidType = false, objectDecoder = null) -> 49 @parse: (value, exceptionOnInvalidType = false, objectDecoder = null) ->
49 # Update settings from last call of Inline.parse() 50 # Update settings from last call of Inline.parse()
50 @settings.exceptionOnInvalidType = exceptionOnInvalidType 51 @settings.exceptionOnInvalidType = exceptionOnInvalidType
51 @settings.objectDecoder = objectDecoder 52 @settings.objectDecoder = objectDecoder
52   53  
53 if not value? 54 if not value?
54 return '' 55 return ''
55   56  
56 value = Utils.trim value 57 value = Utils.trim value
57   58  
58 if 0 is value.length 59 if 0 is value.length
59 return '' 60 return ''
60   61  
61 # Keep a context object to pass through static methods 62 # Keep a context object to pass through static methods
62 context = {exceptionOnInvalidType, objectDecoder, i: 0} 63 context = {exceptionOnInvalidType, objectDecoder, i: 0}
63   64  
64 switch value.charAt(0) 65 switch value.charAt(0)
65 when '[' 66 when '['
66 result = @parseSequence value, context 67 result = @parseSequence value, context
67 ++context.i 68 ++context.i
68 when '{' 69 when '{'
69 result = @parseMapping value, context 70 result = @parseMapping value, context
70 ++context.i 71 ++context.i
71 else 72 else
72 result = @parseScalar value, null, ['"', "'"], context 73 result = @parseScalar value, null, ['"', "'"], context
73   74  
74 # Some comments are allowed at the end 75 # Some comments are allowed at the end
75 if @PATTERN_TRAILING_COMMENTS.replace(value[context.i..], '') isnt '' 76 if @PATTERN_TRAILING_COMMENTS.replace(value[context.i..], '') isnt ''
76 throw new ParseException 'Unexpected characters near "'+value[context.i..]+'".' 77 throw new ParseException 'Unexpected characters near "'+value[context.i..]+'".'
77   78  
78 return result 79 return result
79   80  
80   81  
81 # Dumps a given JavaScript variable to a YAML string. 82 # Dumps a given JavaScript variable to a YAML string.
82 # 83 #
83 # @param [Object] value The JavaScript variable to convert 84 # @param [Object] value The JavaScript variable to convert
84 # @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise 85 # @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise
85 # @param [Function] objectEncoder A function to serialize custom objects, null otherwise 86 # @param [Function] objectEncoder A function to serialize custom objects, null otherwise
86 # 87 #
87 # @return [String] The YAML string representing the JavaScript object 88 # @return [String] The YAML string representing the JavaScript object
88 # 89 #
89 # @throw [DumpException] 90 # @throw [DumpException]
90 # 91 #
91 @dump: (value, exceptionOnInvalidType = false, objectEncoder = null) -> 92 @dump: (value, exceptionOnInvalidType = false, objectEncoder = null) ->
92 if not value? 93 if not value?
93 return 'null' 94 return 'null'
94 type = typeof value 95 type = typeof value
95 if type is 'object' 96 if type is 'object'
96 if value instanceof Date 97 if value instanceof Date
97 return value.toISOString() 98 return value.toISOString()
98 else if objectEncoder? 99 else if objectEncoder?
99 result = objectEncoder value 100 result = objectEncoder value
100 if typeof result is 'string' or result? 101 if typeof result is 'string' or result?
101 return result 102 return result
102 return @dumpObject value 103 return @dumpObject value
103 if type is 'boolean' 104 if type is 'boolean'
104 return (if value then 'true' else 'false') 105 return (if value then 'true' else 'false')
105 if Utils.isDigits(value) 106 if Utils.isDigits(value)
106 return (if type is 'string' then "'"+value+"'" else String(parseInt(value))) 107 return (if type is 'string' then "'"+value+"'" else String(parseInt(value)))
107 if Utils.isNumeric(value) 108 if Utils.isNumeric(value)
108 return (if type is 'string' then "'"+value+"'" else String(parseFloat(value))) 109 return (if type is 'string' then "'"+value+"'" else String(parseFloat(value)))
109 if type is 'number' 110 if type is 'number'
110 return (if value is Infinity then '.Inf' else (if value is -Infinity then '-.Inf' else (if isNaN(value) then '.NaN' else value))) 111 return (if value is Infinity then '.Inf' else (if value is -Infinity then '-.Inf' else (if isNaN(value) then '.NaN' else value)))
111 if Escaper.requiresDoubleQuoting value 112 if Escaper.requiresDoubleQuoting value
112 return Escaper.escapeWithDoubleQuotes value 113 return Escaper.escapeWithDoubleQuotes value
113 if Escaper.requiresSingleQuoting value 114 if Escaper.requiresSingleQuoting value
114 return Escaper.escapeWithSingleQuotes value 115 return Escaper.escapeWithSingleQuotes value
115 if '' is value 116 if '' is value
116 return '""' 117 return '""'
117 if Utils.PATTERN_DATE.test value 118 if Utils.PATTERN_DATE.test value
118 return "'"+value+"'"; 119 return "'"+value+"'";
119 if value.toLowerCase() in ['null','~','true','false'] 120 if value.toLowerCase() in ['null','~','true','false']
120 return "'"+value+"'" 121 return "'"+value+"'"
121 # Default 122 # Default
122 return value; 123 return value;
123   124  
124   125  
125 # Dumps a JavaScript object to a YAML string. 126 # Dumps a JavaScript object to a YAML string.
126 # 127 #
127 # @param [Object] value The JavaScript object to dump 128 # @param [Object] value The JavaScript object to dump
128 # @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise 129 # @param [Boolean] exceptionOnInvalidType true if an exception must be thrown on invalid types (a JavaScript resource or object), false otherwise
129 # @param [Function] objectEncoder A function do serialize custom objects, null otherwise 130 # @param [Function] objectEncoder A function do serialize custom objects, null otherwise
130 # 131 #
131 # @return string The YAML string representing the JavaScript object 132 # @return string The YAML string representing the JavaScript object
132 # 133 #
133 @dumpObject: (value, exceptionOnInvalidType, objectSupport = null) -> 134 @dumpObject: (value, exceptionOnInvalidType, objectSupport = null) ->
134 # Array 135 # Array
135 if value instanceof Array 136 if value instanceof Array
136 output = [] 137 output = []
137 for val in value 138 for val in value
138 output.push @dump val 139 output.push @dump val
139 return '['+output.join(', ')+']' 140 return '['+output.join(', ')+']'
140   141  
141 # Mapping 142 # Mapping
142 else 143 else
143 output = [] 144 output = []
144 for key, val of value 145 for key, val of value
145 output.push @dump(key)+': '+@dump(val) 146 output.push @dump(key)+': '+@dump(val)
146 return '{'+output.join(', ')+'}' 147 return '{'+output.join(', ')+'}'
147   148  
148   149  
149 # Parses a scalar to a YAML string. 150 # Parses a scalar to a YAML string.
150 # 151 #
151 # @param [Object] scalar 152 # @param [Object] scalar
152 # @param [Array] delimiters 153 # @param [Array] delimiters
153 # @param [Array] stringDelimiters 154 # @param [Array] stringDelimiters
154 # @param [Object] context 155 # @param [Object] context
155 # @param [Boolean] evaluate 156 # @param [Boolean] evaluate
156 # 157 #
157 # @return [String] A YAML string 158 # @return [String] A YAML string
158 # 159 #
159 # @throw [ParseException] When malformed inline YAML string is parsed 160 # @throw [ParseException] When malformed inline YAML string is parsed
160 # 161 #
161 @parseScalar: (scalar, delimiters = null, stringDelimiters = ['"', "'"], context = null, evaluate = true) -> 162 @parseScalar: (scalar, delimiters = null, stringDelimiters = ['"', "'"], context = null, evaluate = true) ->
162 unless context? 163 unless context?
163 context = exceptionOnInvalidType: @settings.exceptionOnInvalidType, objectDecoder: @settings.objectDecoder, i: 0 164 context = exceptionOnInvalidType: @settings.exceptionOnInvalidType, objectDecoder: @settings.objectDecoder, i: 0
164 {i} = context 165 {i} = context
165   166  
166 if scalar.charAt(i) in stringDelimiters 167 if scalar.charAt(i) in stringDelimiters
167 # Quoted scalar 168 # Quoted scalar
168 output = @parseQuotedScalar scalar, context 169 output = @parseQuotedScalar scalar, context
169 {i} = context 170 {i} = context
170   171  
171 if delimiters? 172 if delimiters?
172 tmp = Utils.ltrim scalar[i..], ' ' 173 tmp = Utils.ltrim scalar[i..], ' '
173 if not(tmp.charAt(0) in delimiters) 174 if not(tmp.charAt(0) in delimiters)
174 throw new ParseException 'Unexpected characters ('+scalar[i..]+').' 175 throw new ParseException 'Unexpected characters ('+scalar[i..]+').'
175   176  
176 else 177 else
177 # "normal" string 178 # "normal" string
178 if not delimiters 179 if not delimiters
179 output = scalar[i..] 180 output = scalar[i..]
180 i += output.length 181 i += output.length
181   182  
182 # Remove comments 183 # Remove comments
183 strpos = output.indexOf ' #' 184 strpos = output.indexOf ' #'
184 if strpos isnt -1 185 if strpos isnt -1
185 output = Utils.rtrim output[0...strpos] 186 output = Utils.rtrim output[0...strpos]
186   187  
187 else 188 else
188 joinedDelimiters = delimiters.join('|') 189 joinedDelimiters = delimiters.join('|')
189 pattern = @PATTERN_SCALAR_BY_DELIMITERS[joinedDelimiters] 190 pattern = @PATTERN_SCALAR_BY_DELIMITERS[joinedDelimiters]
190 unless pattern? 191 unless pattern?
191 pattern = new Pattern '^(.+?)('+joinedDelimiters+')' 192 pattern = new Pattern '^(.+?)('+joinedDelimiters+')'
192 @PATTERN_SCALAR_BY_DELIMITERS[joinedDelimiters] = pattern 193 @PATTERN_SCALAR_BY_DELIMITERS[joinedDelimiters] = pattern
193 if match = pattern.exec scalar[i..] 194 if match = pattern.exec scalar[i..]
194 output = match[1] 195 output = match[1]
195 i += output.length 196 i += output.length
196 else 197 else
197 throw new ParseException 'Malformed inline YAML string ('+scalar+').' 198 throw new ParseException 'Malformed inline YAML string ('+scalar+').'
198   199  
199   200  
200 if evaluate 201 if evaluate
201 output = @evaluateScalar output, context 202 output = @evaluateScalar output, context
202   203  
203 context.i = i 204 context.i = i
204 return output 205 return output
205   206  
206   207  
207 # Parses a quoted scalar to YAML. 208 # Parses a quoted scalar to YAML.
208 # 209 #
209 # @param [String] scalar 210 # @param [String] scalar
210 # @param [Object] context 211 # @param [Object] context
211 # 212 #
212 # @return [String] A YAML string 213 # @return [String] A YAML string
213 # 214 #
214 # @throw [ParseException] When malformed inline YAML string is parsed 215 # @throw [ParseMore] When malformed inline YAML string is parsed
215 # 216 #
216 @parseQuotedScalar: (scalar, context) -> 217 @parseQuotedScalar: (scalar, context) ->
217 {i} = context 218 {i} = context
218   219  
219 unless match = @PATTERN_QUOTED_SCALAR.exec scalar[i..] 220 unless match = @PATTERN_QUOTED_SCALAR.exec scalar[i..]
220 throw new ParseException 'Malformed inline YAML string ('+scalar[i..]+').' 221 throw new ParseMore 'Malformed inline YAML string ('+scalar[i..]+').'
221   222  
222 output = match[0].substr(1, match[0].length - 2) 223 output = match[0].substr(1, match[0].length - 2)
223   224  
224 if '"' is scalar.charAt(i) 225 if '"' is scalar.charAt(i)
225 output = Unescaper.unescapeDoubleQuotedString output 226 output = Unescaper.unescapeDoubleQuotedString output
226 else 227 else
227 output = Unescaper.unescapeSingleQuotedString output 228 output = Unescaper.unescapeSingleQuotedString output
228   229  
229 i += match[0].length 230 i += match[0].length
230   231  
231 context.i = i 232 context.i = i
232 return output 233 return output
233   234  
234   235  
235 # Parses a sequence to a YAML string. 236 # Parses a sequence to a YAML string.
236 # 237 #
237 # @param [String] sequence 238 # @param [String] sequence
238 # @param [Object] context 239 # @param [Object] context
239 # 240 #
240 # @return [String] A YAML string 241 # @return [String] A YAML string
241 # 242 #
242 # @throw [ParseException] When malformed inline YAML string is parsed 243 # @throw [ParseMore] When malformed inline YAML string is parsed
243 # 244 #
244 @parseSequence: (sequence, context) -> 245 @parseSequence: (sequence, context) ->
245 output = [] 246 output = []
246 len = sequence.length 247 len = sequence.length
247 {i} = context 248 {i} = context
248 i += 1 249 i += 1
249   250  
250 # [foo, bar, ...] 251 # [foo, bar, ...]
251 while i < len 252 while i < len
252 context.i = i 253 context.i = i
253 switch sequence.charAt(i) 254 switch sequence.charAt(i)
254 when '[' 255 when '['
255 # Nested sequence 256 # Nested sequence
256 output.push @parseSequence sequence, context 257 output.push @parseSequence sequence, context
257 {i} = context 258 {i} = context
258 when '{' 259 when '{'
259 # Nested mapping 260 # Nested mapping
260 output.push @parseMapping sequence, context 261 output.push @parseMapping sequence, context
261 {i} = context 262 {i} = context
262 when ']' 263 when ']'
263 return output 264 return output
264 when ',', ' ', "\n" 265 when ',', ' ', "\n"
265 # Do nothing 266 # Do nothing
266 else 267 else
267 isQuoted = (sequence.charAt(i) in ['"', "'"]) 268 isQuoted = (sequence.charAt(i) in ['"', "'"])
268 value = @parseScalar sequence, [',', ']'], ['"', "'"], context 269 value = @parseScalar sequence, [',', ']'], ['"', "'"], context
269 {i} = context 270 {i} = context
270   271  
271 if not(isQuoted) and typeof(value) is 'string' and (value.indexOf(': ') isnt -1 or value.indexOf(":\n") isnt -1) 272 if not(isQuoted) and typeof(value) is 'string' and (value.indexOf(': ') isnt -1 or value.indexOf(":\n") isnt -1)
272 # Embedded mapping? 273 # Embedded mapping?
273 try 274 try
274 value = @parseMapping '{'+value+'}' 275 value = @parseMapping '{'+value+'}'
275 catch e 276 catch e
276 # No, it's not 277 # No, it's not
277   278  
278   279  
279 output.push value 280 output.push value
280   281  
281 --i 282 --i
282   283  
283 ++i 284 ++i
284   285  
285 throw new ParseException 'Malformed inline YAML string '+sequence 286 throw new ParseMore 'Malformed inline YAML string '+sequence
286   287  
287   288  
288 # Parses a mapping to a YAML string. 289 # Parses a mapping to a YAML string.
289 # 290 #
290 # @param [String] mapping 291 # @param [String] mapping
291 # @param [Object] context 292 # @param [Object] context
292 # 293 #
293 # @return [String] A YAML string 294 # @return [String] A YAML string
294 # 295 #
295 # @throw [ParseException] When malformed inline YAML string is parsed 296 # @throw [ParseMore] When malformed inline YAML string is parsed
296 # 297 #
297 @parseMapping: (mapping, context) -> 298 @parseMapping: (mapping, context) ->
298 output = {} 299 output = {}
299 len = mapping.length 300 len = mapping.length
300 {i} = context 301 {i} = context
301 i += 1 302 i += 1
302   303  
303 # {foo: bar, bar:foo, ...} 304 # {foo: bar, bar:foo, ...}
304 shouldContinueWhileLoop = false 305 shouldContinueWhileLoop = false
305 while i < len 306 while i < len
306 context.i = i 307 context.i = i
307 switch mapping.charAt(i) 308 switch mapping.charAt(i)
308 when ' ', ',', "\n" 309 when ' ', ',', "\n"
309 ++i 310 ++i
310 context.i = i 311 context.i = i
311 shouldContinueWhileLoop = true 312 shouldContinueWhileLoop = true
312 when '}' 313 when '}'
313 return output 314 return output
314   315  
315 if shouldContinueWhileLoop 316 if shouldContinueWhileLoop
316 shouldContinueWhileLoop = false 317 shouldContinueWhileLoop = false
317 continue 318 continue
318   319  
319 # Key 320 # Key
320 key = @parseScalar mapping, [':', ' ', "\n"], ['"', "'"], context, false 321 key = @parseScalar mapping, [':', ' ', "\n"], ['"', "'"], context, false
321 {i} = context 322 {i} = context
322   323  
323 # Value 324 # Value
324 done = false 325 done = false
325   326  
326 while i < len 327 while i < len
327 context.i = i 328 context.i = i
328 switch mapping.charAt(i) 329 switch mapping.charAt(i)
329 when '[' 330 when '['
330 # Nested sequence 331 # Nested sequence
331 value = @parseSequence mapping, context 332 value = @parseSequence mapping, context
332 {i} = context 333 {i} = context
333 # Spec: Keys MUST be unique; first one wins. 334 # Spec: Keys MUST be unique; first one wins.
334 # Parser cannot abort this mapping earlier, since lines 335 # Parser cannot abort this mapping earlier, since lines
335 # are processed sequentially. 336 # are processed sequentially.
336 if output[key] == undefined 337 if output[key] == undefined
337 output[key] = value 338 output[key] = value
338 done = true 339 done = true
339 when '{' 340 when '{'
340 # Nested mapping 341 # Nested mapping
341 value = @parseMapping mapping, context 342 value = @parseMapping mapping, context
342 {i} = context 343 {i} = context
343 # Spec: Keys MUST be unique; first one wins. 344 # Spec: Keys MUST be unique; first one wins.
344 # Parser cannot abort this mapping earlier, since lines 345 # Parser cannot abort this mapping earlier, since lines
345 # are processed sequentially. 346 # are processed sequentially.
346 if output[key] == undefined 347 if output[key] == undefined
347 output[key] = value 348 output[key] = value
348 done = true 349 done = true
349 when ':', ' ', "\n" 350 when ':', ' ', "\n"
350 # Do nothing 351 # Do nothing
351 else 352 else
352 value = @parseScalar mapping, [',', '}'], ['"', "'"], context 353 value = @parseScalar mapping, [',', '}'], ['"', "'"], context
353 {i} = context 354 {i} = context
354 # Spec: Keys MUST be unique; first one wins. 355 # Spec: Keys MUST be unique; first one wins.
355 # Parser cannot abort this mapping earlier, since lines 356 # Parser cannot abort this mapping earlier, since lines
356 # are processed sequentially. 357 # are processed sequentially.
357 if output[key] == undefined 358 if output[key] == undefined
358 output[key] = value 359 output[key] = value
359 done = true 360 done = true
360 --i 361 --i
361   362  
362 ++i 363 ++i
363   364  
364 if done 365 if done
365 break 366 break
366   367  
367 throw new ParseException 'Malformed inline YAML string '+mapping 368 throw new ParseMore 'Malformed inline YAML string '+mapping
368   369  
369   370  
370 # Evaluates scalars and replaces magic values. 371 # Evaluates scalars and replaces magic values.
371 # 372 #
372 # @param [String] scalar 373 # @param [String] scalar
373 # 374 #
374 # @return [String] A YAML string 375 # @return [String] A YAML string
375 # 376 #
376 @evaluateScalar: (scalar, context) -> 377 @evaluateScalar: (scalar, context) ->
377 scalar = Utils.trim(scalar) 378 scalar = Utils.trim(scalar)
378 scalarLower = scalar.toLowerCase() 379 scalarLower = scalar.toLowerCase()
379   380  
380 switch scalarLower 381 switch scalarLower
381 when 'null', '', '~' 382 when 'null', '', '~'
382 return null 383 return null
383 when 'true' 384 when 'true'
384 return true 385 return true
385 when 'false' 386 when 'false'
386 return false 387 return false
387 when '.inf' 388 when '.inf'
388 return Infinity 389 return Infinity
389 when '.nan' 390 when '.nan'
390 return NaN 391 return NaN
391 when '-.inf' 392 when '-.inf'
392 return Infinity 393 return Infinity
393 else 394 else
394 firstChar = scalarLower.charAt(0) 395 firstChar = scalarLower.charAt(0)
395 switch firstChar 396 switch firstChar
396 when '!' 397 when '!'
397 firstSpace = scalar.indexOf(' ') 398 firstSpace = scalar.indexOf(' ')
398 if firstSpace is -1 399 if firstSpace is -1
399 firstWord = scalarLower 400 firstWord = scalarLower
400 else 401 else
401 firstWord = scalarLower[0...firstSpace] 402 firstWord = scalarLower[0...firstSpace]
402 switch firstWord 403 switch firstWord
403 when '!' 404 when '!'
404 if firstSpace isnt -1 405 if firstSpace isnt -1
405 return parseInt @parseScalar(scalar[2..]) 406 return parseInt @parseScalar(scalar[2..])
406 return null 407 return null
407 when '!str' 408 when '!str'
408 return Utils.ltrim scalar[4..] 409 return Utils.ltrim scalar[4..]
409 when '!!str' 410 when '!!str'
410 return Utils.ltrim scalar[5..] 411 return Utils.ltrim scalar[5..]
411 when '!!int' 412 when '!!int'
412 return parseInt(@parseScalar(scalar[5..])) 413 return parseInt(@parseScalar(scalar[5..]))
413 when '!!bool' 414 when '!!bool'
414 return Utils.parseBoolean(@parseScalar(scalar[6..]), false) 415 return Utils.parseBoolean(@parseScalar(scalar[6..]), false)
415 when '!!float' 416 when '!!float'
416 return parseFloat(@parseScalar(scalar[7..])) 417 return parseFloat(@parseScalar(scalar[7..]))
417 when '!!timestamp' 418 when '!!timestamp'
418 return Utils.stringToDate(Utils.ltrim(scalar[11..])) 419 return Utils.stringToDate(Utils.ltrim(scalar[11..]))
419 else 420 else
420 unless context? 421 unless context?
421 context = exceptionOnInvalidType: @settings.exceptionOnInvalidType, objectDecoder: @settings.objectDecoder, i: 0 422 context = exceptionOnInvalidType: @settings.exceptionOnInvalidType, objectDecoder: @settings.objectDecoder, i: 0
422 {objectDecoder, exceptionOnInvalidType} = context 423 {objectDecoder, exceptionOnInvalidType} = context
423   424  
424 if objectDecoder 425 if objectDecoder
425 # If objectDecoder function is given, we can do custom decoding of custom types 426 # If objectDecoder function is given, we can do custom decoding of custom types
426 trimmedScalar = Utils.rtrim scalar 427 trimmedScalar = Utils.rtrim scalar
427 firstSpace = trimmedScalar.indexOf(' ') 428 firstSpace = trimmedScalar.indexOf(' ')
428 if firstSpace is -1 429 if firstSpace is -1
429 return objectDecoder trimmedScalar, null 430 return objectDecoder trimmedScalar, null
430 else 431 else
431 subValue = Utils.ltrim trimmedScalar[firstSpace+1..] 432 subValue = Utils.ltrim trimmedScalar[firstSpace+1..]
432 unless subValue.length > 0 433 unless subValue.length > 0
433 subValue = null 434 subValue = null
434 return objectDecoder trimmedScalar[0...firstSpace], subValue 435 return objectDecoder trimmedScalar[0...firstSpace], subValue
435   436  
436 if exceptionOnInvalidType 437 if exceptionOnInvalidType
437 throw new ParseException 'Custom object support when parsing a YAML file has been disabled.' 438 throw new ParseException 'Custom object support when parsing a YAML file has been disabled.'
438   439  
439 return null 440 return null
440 when '0' 441 when '0'
441 if '0x' is scalar[0...2] 442 if '0x' is scalar[0...2]
442 return Utils.hexDec scalar 443 return Utils.hexDec scalar
443 else if Utils.isDigits scalar 444 else if Utils.isDigits scalar
444 return Utils.octDec scalar 445 return Utils.octDec scalar
445 else if Utils.isNumeric scalar 446 else if Utils.isNumeric scalar
446 return parseFloat scalar 447 return parseFloat scalar
447 else 448 else
448 return scalar 449 return scalar
449 when '+' 450 when '+'
450 if Utils.isDigits scalar 451 if Utils.isDigits scalar
451 raw = scalar 452 raw = scalar
452 cast = parseInt(raw) 453 cast = parseInt(raw)
453 if raw is String(cast) 454 if raw is String(cast)
454 return cast 455 return cast
455 else 456 else
456 return raw 457 return raw
457 else if Utils.isNumeric scalar 458 else if Utils.isNumeric scalar
458 return parseFloat scalar 459 return parseFloat scalar
459 else if @PATTERN_THOUSAND_NUMERIC_SCALAR.test scalar 460 else if @PATTERN_THOUSAND_NUMERIC_SCALAR.test scalar
460 return parseFloat(scalar.replace(',', '')) 461 return parseFloat(scalar.replace(',', ''))
461 return scalar 462 return scalar
462 when '-' 463 when '-'
463 if Utils.isDigits(scalar[1..]) 464 if Utils.isDigits(scalar[1..])
464 if '0' is scalar.charAt(1) 465 if '0' is scalar.charAt(1)
465 return -Utils.octDec(scalar[1..]) 466 return -Utils.octDec(scalar[1..])
466 else 467 else
467 raw = scalar[1..] 468 raw = scalar[1..]
468 cast = parseInt(raw) 469 cast = parseInt(raw)
469 if raw is String(cast) 470 if raw is String(cast)
470 return -cast 471 return -cast
471 else 472 else
472 return -raw 473 return -raw
473 else if Utils.isNumeric scalar 474 else if Utils.isNumeric scalar
474 return parseFloat scalar 475 return parseFloat scalar
475 else if @PATTERN_THOUSAND_NUMERIC_SCALAR.test scalar 476 else if @PATTERN_THOUSAND_NUMERIC_SCALAR.test scalar
476 return parseFloat(scalar.replace(',', '')) 477 return parseFloat(scalar.replace(',', ''))
477 return scalar 478 return scalar
478 else 479 else
479 if date = Utils.stringToDate(scalar) 480 if date = Utils.stringToDate(scalar)
480 return date 481 return date
481 else if Utils.isNumeric(scalar) 482 else if Utils.isNumeric(scalar)
482 return parseFloat scalar 483 return parseFloat scalar
483 else if @PATTERN_THOUSAND_NUMERIC_SCALAR.test scalar 484 else if @PATTERN_THOUSAND_NUMERIC_SCALAR.test scalar
484 return parseFloat(scalar.replace(',', '')) 485 return parseFloat(scalar.replace(',', ''))
485 return scalar 486 return scalar
486   487  
487 module.exports = Inline 488 module.exports = Inline
488   489