scratch – Blame information for rev 75

Subversion Repositories:
Rev:
Rev Author Line No. Line
75 office 1 // Generated by CoffeeScript 1.10.0
2 var Inline, ParseException, Parser, Pattern, Utils;
3  
4 Inline = require('./Inline');
5  
6 Pattern = require('./Pattern');
7  
8 Utils = require('./Utils');
9  
10 ParseException = require('./Exception/ParseException');
11  
12 Parser = (function() {
13 Parser.prototype.PATTERN_FOLDED_SCALAR_ALL = new Pattern('^(?:(?<type>![^\\|>]*)\\s+)?(?<separator>\\||>)(?<modifiers>\\+|\\-|\\d+|\\+\\d+|\\-\\d+|\\d+\\+|\\d+\\-)?(?<comments> +#.*)?$');
14  
15 Parser.prototype.PATTERN_FOLDED_SCALAR_END = new Pattern('(?<separator>\\||>)(?<modifiers>\\+|\\-|\\d+|\\+\\d+|\\-\\d+|\\d+\\+|\\d+\\-)?(?<comments> +#.*)?$');
16  
17 Parser.prototype.PATTERN_SEQUENCE_ITEM = new Pattern('^\\-((?<leadspaces>\\s+)(?<value>.+?))?\\s*$');
18  
19 Parser.prototype.PATTERN_ANCHOR_VALUE = new Pattern('^&(?<ref>[^ ]+) *(?<value>.*)');
20  
21 Parser.prototype.PATTERN_COMPACT_NOTATION = new Pattern('^(?<key>' + Inline.REGEX_QUOTED_STRING + '|[^ \'"\\{\\[].*?) *\\:(\\s+(?<value>.+?))?\\s*$');
22  
23 Parser.prototype.PATTERN_MAPPING_ITEM = new Pattern('^(?<key>' + Inline.REGEX_QUOTED_STRING + '|[^ \'"\\[\\{].*?) *\\:(\\s+(?<value>.+?))?\\s*$');
24  
25 Parser.prototype.PATTERN_DECIMAL = new Pattern('\\d+');
26  
27 Parser.prototype.PATTERN_INDENT_SPACES = new Pattern('^ +');
28  
29 Parser.prototype.PATTERN_TRAILING_LINES = new Pattern('(\n*)$');
30  
31 Parser.prototype.PATTERN_YAML_HEADER = new Pattern('^\\%YAML[: ][\\d\\.]+.*\n');
32  
33 Parser.prototype.PATTERN_LEADING_COMMENTS = new Pattern('^(\\#.*?\n)+');
34  
35 Parser.prototype.PATTERN_DOCUMENT_MARKER_START = new Pattern('^\\-\\-\\-.*?\n');
36  
37 Parser.prototype.PATTERN_DOCUMENT_MARKER_END = new Pattern('^\\.\\.\\.\\s*$');
38  
39 Parser.prototype.PATTERN_FOLDED_SCALAR_BY_INDENTATION = {};
40  
41 Parser.prototype.CONTEXT_NONE = 0;
42  
43 Parser.prototype.CONTEXT_SEQUENCE = 1;
44  
45 Parser.prototype.CONTEXT_MAPPING = 2;
46  
47 function Parser(offset) {
48 this.offset = offset != null ? offset : 0;
49 this.lines = [];
50 this.currentLineNb = -1;
51 this.currentLine = '';
52 this.refs = {};
53 }
54  
55 Parser.prototype.parse = function(value, exceptionOnInvalidType, objectDecoder) {
56 var alias, allowOverwrite, block, c, context, data, e, error, error1, error2, first, i, indent, isRef, j, k, key, l, lastKey, len, len1, len2, len3, lineCount, m, matches, mergeNode, n, name, parsed, parsedItem, parser, ref, ref1, ref2, refName, refValue, val, values;
57 if (exceptionOnInvalidType == null) {
58 exceptionOnInvalidType = false;
59 }
60 if (objectDecoder == null) {
61 objectDecoder = null;
62 }
63 this.currentLineNb = -1;
64 this.currentLine = '';
65 this.lines = this.cleanup(value).split("\n");
66 data = null;
67 context = this.CONTEXT_NONE;
68 allowOverwrite = false;
69 while (this.moveToNextLine()) {
70 if (this.isCurrentLineEmpty()) {
71 continue;
72 }
73 if ("\t" === this.currentLine[0]) {
74 throw new ParseException('A YAML file cannot contain tabs as indentation.', this.getRealCurrentLineNb() + 1, this.currentLine);
75 }
76 isRef = mergeNode = false;
77 if (values = this.PATTERN_SEQUENCE_ITEM.exec(this.currentLine)) {
78 if (this.CONTEXT_MAPPING === context) {
79 throw new ParseException('You cannot define a sequence item when in a mapping');
80 }
81 context = this.CONTEXT_SEQUENCE;
82 if (data == null) {
83 data = [];
84 }
85 if ((values.value != null) && (matches = this.PATTERN_ANCHOR_VALUE.exec(values.value))) {
86 isRef = matches.ref;
87 values.value = matches.value;
88 }
89 if (!(values.value != null) || '' === Utils.trim(values.value, ' ') || Utils.ltrim(values.value, ' ').indexOf('#') === 0) {
90 if (this.currentLineNb < this.lines.length - 1 && !this.isNextLineUnIndentedCollection()) {
91 c = this.getRealCurrentLineNb() + 1;
92 parser = new Parser(c);
93 parser.refs = this.refs;
94 data.push(parser.parse(this.getNextEmbedBlock(null, true), exceptionOnInvalidType, objectDecoder));
95 } else {
96 data.push(null);
97 }
98 } else {
99 if (((ref = values.leadspaces) != null ? ref.length : void 0) && (matches = this.PATTERN_COMPACT_NOTATION.exec(values.value))) {
100 c = this.getRealCurrentLineNb();
101 parser = new Parser(c);
102 parser.refs = this.refs;
103 block = values.value;
104 indent = this.getCurrentLineIndentation();
105 if (this.isNextLineIndented(false)) {
106 block += "\n" + this.getNextEmbedBlock(indent + values.leadspaces.length + 1, true);
107 }
108 data.push(parser.parse(block, exceptionOnInvalidType, objectDecoder));
109 } else {
110 data.push(this.parseValue(values.value, exceptionOnInvalidType, objectDecoder));
111 }
112 }
113 } else if ((values = this.PATTERN_MAPPING_ITEM.exec(this.currentLine)) && values.key.indexOf(' #') === -1) {
114 if (this.CONTEXT_SEQUENCE === context) {
115 throw new ParseException('You cannot define a mapping item when in a sequence');
116 }
117 context = this.CONTEXT_MAPPING;
118 if (data == null) {
119 data = {};
120 }
121 Inline.configure(exceptionOnInvalidType, objectDecoder);
122 try {
123 key = Inline.parseScalar(values.key);
124 } catch (error) {
125 e = error;
126 e.parsedLine = this.getRealCurrentLineNb() + 1;
127 e.snippet = this.currentLine;
128 throw e;
129 }
130 if ('<<' === key) {
131 mergeNode = true;
132 allowOverwrite = true;
133 if (((ref1 = values.value) != null ? ref1.indexOf('*') : void 0) === 0) {
134 refName = values.value.slice(1);
135 if (this.refs[refName] == null) {
136 throw new ParseException('Reference "' + refName + '" does not exist.', this.getRealCurrentLineNb() + 1, this.currentLine);
137 }
138 refValue = this.refs[refName];
139 if (typeof refValue !== 'object') {
140 throw new ParseException('YAML merge keys used with a scalar value instead of an object.', this.getRealCurrentLineNb() + 1, this.currentLine);
141 }
142 if (refValue instanceof Array) {
143 for (i = j = 0, len = refValue.length; j < len; i = ++j) {
144 value = refValue[i];
145 if (data[name = String(i)] == null) {
146 data[name] = value;
147 }
148 }
149 } else {
150 for (key in refValue) {
151 value = refValue[key];
152 if (data[key] == null) {
153 data[key] = value;
154 }
155 }
156 }
157 } else {
158 if ((values.value != null) && values.value !== '') {
159 value = values.value;
160 } else {
161 value = this.getNextEmbedBlock();
162 }
163 c = this.getRealCurrentLineNb() + 1;
164 parser = new Parser(c);
165 parser.refs = this.refs;
166 parsed = parser.parse(value, exceptionOnInvalidType);
167 if (typeof parsed !== 'object') {
168 throw new ParseException('YAML merge keys used with a scalar value instead of an object.', this.getRealCurrentLineNb() + 1, this.currentLine);
169 }
170 if (parsed instanceof Array) {
171 for (l = 0, len1 = parsed.length; l < len1; l++) {
172 parsedItem = parsed[l];
173 if (typeof parsedItem !== 'object') {
174 throw new ParseException('Merge items must be objects.', this.getRealCurrentLineNb() + 1, parsedItem);
175 }
176 if (parsedItem instanceof Array) {
177 for (i = m = 0, len2 = parsedItem.length; m < len2; i = ++m) {
178 value = parsedItem[i];
179 k = String(i);
180 if (!data.hasOwnProperty(k)) {
181 data[k] = value;
182 }
183 }
184 } else {
185 for (key in parsedItem) {
186 value = parsedItem[key];
187 if (!data.hasOwnProperty(key)) {
188 data[key] = value;
189 }
190 }
191 }
192 }
193 } else {
194 for (key in parsed) {
195 value = parsed[key];
196 if (!data.hasOwnProperty(key)) {
197 data[key] = value;
198 }
199 }
200 }
201 }
202 } else if ((values.value != null) && (matches = this.PATTERN_ANCHOR_VALUE.exec(values.value))) {
203 isRef = matches.ref;
204 values.value = matches.value;
205 }
206 if (mergeNode) {
207  
208 } else if (!(values.value != null) || '' === Utils.trim(values.value, ' ') || Utils.ltrim(values.value, ' ').indexOf('#') === 0) {
209 if (!(this.isNextLineIndented()) && !(this.isNextLineUnIndentedCollection())) {
210 if (allowOverwrite || data[key] === void 0) {
211 data[key] = null;
212 }
213 } else {
214 c = this.getRealCurrentLineNb() + 1;
215 parser = new Parser(c);
216 parser.refs = this.refs;
217 val = parser.parse(this.getNextEmbedBlock(), exceptionOnInvalidType, objectDecoder);
218 if (allowOverwrite || data[key] === void 0) {
219 data[key] = val;
220 }
221 }
222 } else {
223 val = this.parseValue(values.value, exceptionOnInvalidType, objectDecoder);
224 if (allowOverwrite || data[key] === void 0) {
225 data[key] = val;
226 }
227 }
228 } else {
229 lineCount = this.lines.length;
230 if (1 === lineCount || (2 === lineCount && Utils.isEmpty(this.lines[1]))) {
231 try {
232 value = Inline.parse(this.lines[0], exceptionOnInvalidType, objectDecoder);
233 } catch (error1) {
234 e = error1;
235 e.parsedLine = this.getRealCurrentLineNb() + 1;
236 e.snippet = this.currentLine;
237 throw e;
238 }
239 if (typeof value === 'object') {
240 if (value instanceof Array) {
241 first = value[0];
242 } else {
243 for (key in value) {
244 first = value[key];
245 break;
246 }
247 }
248 if (typeof first === 'string' && first.indexOf('*') === 0) {
249 data = [];
250 for (n = 0, len3 = value.length; n < len3; n++) {
251 alias = value[n];
252 data.push(this.refs[alias.slice(1)]);
253 }
254 value = data;
255 }
256 }
257 return value;
258 } else if ((ref2 = Utils.ltrim(value).charAt(0)) === '[' || ref2 === '{') {
259 try {
260 return Inline.parse(value, exceptionOnInvalidType, objectDecoder);
261 } catch (error2) {
262 e = error2;
263 e.parsedLine = this.getRealCurrentLineNb() + 1;
264 e.snippet = this.currentLine;
265 throw e;
266 }
267 }
268 throw new ParseException('Unable to parse.', this.getRealCurrentLineNb() + 1, this.currentLine);
269 }
270 if (isRef) {
271 if (data instanceof Array) {
272 this.refs[isRef] = data[data.length - 1];
273 } else {
274 lastKey = null;
275 for (key in data) {
276 lastKey = key;
277 }
278 this.refs[isRef] = data[lastKey];
279 }
280 }
281 }
282 if (Utils.isEmpty(data)) {
283 return null;
284 } else {
285 return data;
286 }
287 };
288  
289 Parser.prototype.getRealCurrentLineNb = function() {
290 return this.currentLineNb + this.offset;
291 };
292  
293 Parser.prototype.getCurrentLineIndentation = function() {
294 return this.currentLine.length - Utils.ltrim(this.currentLine, ' ').length;
295 };
296  
297 Parser.prototype.getNextEmbedBlock = function(indentation, includeUnindentedCollection) {
298 var data, indent, isItUnindentedCollection, newIndent, removeComments, removeCommentsPattern, unindentedEmbedBlock;
299 if (indentation == null) {
300 indentation = null;
301 }
302 if (includeUnindentedCollection == null) {
303 includeUnindentedCollection = false;
304 }
305 this.moveToNextLine();
306 if (indentation == null) {
307 newIndent = this.getCurrentLineIndentation();
308 unindentedEmbedBlock = this.isStringUnIndentedCollectionItem(this.currentLine);
309 if (!(this.isCurrentLineEmpty()) && 0 === newIndent && !unindentedEmbedBlock) {
310 throw new ParseException('Indentation problem.', this.getRealCurrentLineNb() + 1, this.currentLine);
311 }
312 } else {
313 newIndent = indentation;
314 }
315 data = [this.currentLine.slice(newIndent)];
316 if (!includeUnindentedCollection) {
317 isItUnindentedCollection = this.isStringUnIndentedCollectionItem(this.currentLine);
318 }
319 removeCommentsPattern = this.PATTERN_FOLDED_SCALAR_END;
320 removeComments = !removeCommentsPattern.test(this.currentLine);
321 while (this.moveToNextLine()) {
322 indent = this.getCurrentLineIndentation();
323 if (indent === newIndent) {
324 removeComments = !removeCommentsPattern.test(this.currentLine);
325 }
326 if (isItUnindentedCollection && !this.isStringUnIndentedCollectionItem(this.currentLine) && indent === newIndent) {
327 this.moveToPreviousLine();
328 break;
329 }
330 if (this.isCurrentLineBlank()) {
331 data.push(this.currentLine.slice(newIndent));
332 continue;
333 }
334 if (removeComments && this.isCurrentLineComment()) {
335 if (indent === newIndent) {
336 continue;
337 }
338 }
339 if (indent >= newIndent) {
340 data.push(this.currentLine.slice(newIndent));
341 } else if (Utils.ltrim(this.currentLine).charAt(0) === '#') {
342  
343 } else if (0 === indent) {
344 this.moveToPreviousLine();
345 break;
346 } else {
347 throw new ParseException('Indentation problem.', this.getRealCurrentLineNb() + 1, this.currentLine);
348 }
349 }
350 return data.join("\n");
351 };
352  
353 Parser.prototype.moveToNextLine = function() {
354 if (this.currentLineNb >= this.lines.length - 1) {
355 return false;
356 }
357 this.currentLine = this.lines[++this.currentLineNb];
358 return true;
359 };
360  
361 Parser.prototype.moveToPreviousLine = function() {
362 this.currentLine = this.lines[--this.currentLineNb];
363 };
364  
365 Parser.prototype.parseValue = function(value, exceptionOnInvalidType, objectDecoder) {
366 var e, error, error1, foldedIndent, matches, modifiers, pos, ref, ref1, val;
367 if (0 === value.indexOf('*')) {
368 pos = value.indexOf('#');
369 if (pos !== -1) {
370 value = value.substr(1, pos - 2);
371 } else {
372 value = value.slice(1);
373 }
374 if (this.refs[value] === void 0) {
375 throw new ParseException('Reference "' + value + '" does not exist.', this.currentLine);
376 }
377 return this.refs[value];
378 }
379 if (matches = this.PATTERN_FOLDED_SCALAR_ALL.exec(value)) {
380 modifiers = (ref = matches.modifiers) != null ? ref : '';
381 foldedIndent = Math.abs(parseInt(modifiers));
382 if (isNaN(foldedIndent)) {
383 foldedIndent = 0;
384 }
385 val = this.parseFoldedScalar(matches.separator, this.PATTERN_DECIMAL.replace(modifiers, ''), foldedIndent);
386 if (matches.type != null) {
387 Inline.configure(exceptionOnInvalidType, objectDecoder);
388 return Inline.parseScalar(matches.type + ' ' + val);
389 } else {
390 return val;
391 }
392 }
393 try {
394 return Inline.parse(value, exceptionOnInvalidType, objectDecoder);
395 } catch (error) {
396 e = error;
397 if (((ref1 = value.charAt(0)) === '[' || ref1 === '{') && e instanceof ParseException && this.isNextLineIndented()) {
398 value += "\n" + this.getNextEmbedBlock();
399 try {
400 return Inline.parse(value, exceptionOnInvalidType, objectDecoder);
401 } catch (error1) {
402 e = error1;
403 e.parsedLine = this.getRealCurrentLineNb() + 1;
404 e.snippet = this.currentLine;
405 throw e;
406 }
407 } else {
408 e.parsedLine = this.getRealCurrentLineNb() + 1;
409 e.snippet = this.currentLine;
410 throw e;
411 }
412 }
413 };
414  
415 Parser.prototype.parseFoldedScalar = function(separator, indicator, indentation) {
416 var isCurrentLineBlank, j, len, line, matches, newText, notEOF, pattern, ref, text;
417 if (indicator == null) {
418 indicator = '';
419 }
420 if (indentation == null) {
421 indentation = 0;
422 }
423 notEOF = this.moveToNextLine();
424 if (!notEOF) {
425 return '';
426 }
427 isCurrentLineBlank = this.isCurrentLineBlank();
428 text = '';
429 while (notEOF && isCurrentLineBlank) {
430 if (notEOF = this.moveToNextLine()) {
431 text += "\n";
432 isCurrentLineBlank = this.isCurrentLineBlank();
433 }
434 }
435 if (0 === indentation) {
436 if (matches = this.PATTERN_INDENT_SPACES.exec(this.currentLine)) {
437 indentation = matches[0].length;
438 }
439 }
440 if (indentation > 0) {
441 pattern = this.PATTERN_FOLDED_SCALAR_BY_INDENTATION[indentation];
442 if (pattern == null) {
443 pattern = new Pattern('^ {' + indentation + '}(.*)$');
444 Parser.prototype.PATTERN_FOLDED_SCALAR_BY_INDENTATION[indentation] = pattern;
445 }
446 while (notEOF && (isCurrentLineBlank || (matches = pattern.exec(this.currentLine)))) {
447 if (isCurrentLineBlank) {
448 text += this.currentLine.slice(indentation);
449 } else {
450 text += matches[1];
451 }
452 if (notEOF = this.moveToNextLine()) {
453 text += "\n";
454 isCurrentLineBlank = this.isCurrentLineBlank();
455 }
456 }
457 } else if (notEOF) {
458 text += "\n";
459 }
460 if (notEOF) {
461 this.moveToPreviousLine();
462 }
463 if ('>' === separator) {
464 newText = '';
465 ref = text.split("\n");
466 for (j = 0, len = ref.length; j < len; j++) {
467 line = ref[j];
468 if (line.length === 0 || line.charAt(0) === ' ') {
469 newText = Utils.rtrim(newText, ' ') + line + "\n";
470 } else {
471 newText += line + ' ';
472 }
473 }
474 text = newText;
475 }
476 if ('+' !== indicator) {
477 text = Utils.rtrim(text);
478 }
479 if ('' === indicator) {
480 text = this.PATTERN_TRAILING_LINES.replace(text, "\n");
481 } else if ('-' === indicator) {
482 text = this.PATTERN_TRAILING_LINES.replace(text, '');
483 }
484 return text;
485 };
486  
487 Parser.prototype.isNextLineIndented = function(ignoreComments) {
488 var EOF, currentIndentation, ret;
489 if (ignoreComments == null) {
490 ignoreComments = true;
491 }
492 currentIndentation = this.getCurrentLineIndentation();
493 EOF = !this.moveToNextLine();
494 if (ignoreComments) {
495 while (!EOF && this.isCurrentLineEmpty()) {
496 EOF = !this.moveToNextLine();
497 }
498 } else {
499 while (!EOF && this.isCurrentLineBlank()) {
500 EOF = !this.moveToNextLine();
501 }
502 }
503 if (EOF) {
504 return false;
505 }
506 ret = false;
507 if (this.getCurrentLineIndentation() > currentIndentation) {
508 ret = true;
509 }
510 this.moveToPreviousLine();
511 return ret;
512 };
513  
514 Parser.prototype.isCurrentLineEmpty = function() {
515 var trimmedLine;
516 trimmedLine = Utils.trim(this.currentLine, ' ');
517 return trimmedLine.length === 0 || trimmedLine.charAt(0) === '#';
518 };
519  
520 Parser.prototype.isCurrentLineBlank = function() {
521 return '' === Utils.trim(this.currentLine, ' ');
522 };
523  
524 Parser.prototype.isCurrentLineComment = function() {
525 var ltrimmedLine;
526 ltrimmedLine = Utils.ltrim(this.currentLine, ' ');
527 return ltrimmedLine.charAt(0) === '#';
528 };
529  
530 Parser.prototype.cleanup = function(value) {
531 var count, i, indent, j, l, len, len1, line, lines, ref, ref1, ref2, smallestIndent, trimmedValue;
532 if (value.indexOf("\r") !== -1) {
533 value = value.split("\r\n").join("\n").split("\r").join("\n");
534 }
535 count = 0;
536 ref = this.PATTERN_YAML_HEADER.replaceAll(value, ''), value = ref[0], count = ref[1];
537 this.offset += count;
538 ref1 = this.PATTERN_LEADING_COMMENTS.replaceAll(value, '', 1), trimmedValue = ref1[0], count = ref1[1];
539 if (count === 1) {
540 this.offset += Utils.subStrCount(value, "\n") - Utils.subStrCount(trimmedValue, "\n");
541 value = trimmedValue;
542 }
543 ref2 = this.PATTERN_DOCUMENT_MARKER_START.replaceAll(value, '', 1), trimmedValue = ref2[0], count = ref2[1];
544 if (count === 1) {
545 this.offset += Utils.subStrCount(value, "\n") - Utils.subStrCount(trimmedValue, "\n");
546 value = trimmedValue;
547 value = this.PATTERN_DOCUMENT_MARKER_END.replace(value, '');
548 }
549 lines = value.split("\n");
550 smallestIndent = -1;
551 for (j = 0, len = lines.length; j < len; j++) {
552 line = lines[j];
553 if (Utils.trim(line, ' ').length === 0) {
554 continue;
555 }
556 indent = line.length - Utils.ltrim(line).length;
557 if (smallestIndent === -1 || indent < smallestIndent) {
558 smallestIndent = indent;
559 }
560 }
561 if (smallestIndent > 0) {
562 for (i = l = 0, len1 = lines.length; l < len1; i = ++l) {
563 line = lines[i];
564 lines[i] = line.slice(smallestIndent);
565 }
566 value = lines.join("\n");
567 }
568 return value;
569 };
570  
571 Parser.prototype.isNextLineUnIndentedCollection = function(currentIndentation) {
572 var notEOF, ret;
573 if (currentIndentation == null) {
574 currentIndentation = null;
575 }
576 if (currentIndentation == null) {
577 currentIndentation = this.getCurrentLineIndentation();
578 }
579 notEOF = this.moveToNextLine();
580 while (notEOF && this.isCurrentLineEmpty()) {
581 notEOF = this.moveToNextLine();
582 }
583 if (false === notEOF) {
584 return false;
585 }
586 ret = false;
587 if (this.getCurrentLineIndentation() === currentIndentation && this.isStringUnIndentedCollectionItem(this.currentLine)) {
588 ret = true;
589 }
590 this.moveToPreviousLine();
591 return ret;
592 };
593  
594 Parser.prototype.isStringUnIndentedCollectionItem = function() {
595 return this.currentLine === '-' || this.currentLine.slice(0, 2) === '- ';
596 };
597  
598 return Parser;
599  
600 })();
601  
602 module.exports = Parser;