scratch – Blame information for rev 125

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