]>
Dogcows Code - chaz/p5-CGI-Ex/blob - lib/CGI/Ex/yaml_load.js
1 /**----------------------------------------------------------------***
2 * Copyright 2007 - Paul Seamons *
3 * Distributed under the Perl Artistic License without warranty *
4 * Based upon YAML.pm v0.35 from Perl *
5 ***----------------------------------------------------------------**/
9 // allow for missing methods in ie 5.0
11 if (! Array
.prototype.unshift
)
12 Array
.prototype.unshift = function (add
) {
13 for (var i
=this.length
; i
> 0; i
--) this[i
] = this[i
- 1];
17 if (!Array
.prototype.shift
)
18 Array
.prototype.shift = function () {
20 for (var i
=0; i
<this.length
-1; i
++) this[i
] = this[i
+ 1];
25 if (!Array
.prototype.push
)
26 Array
.prototype.push = function (add
) {
27 this[this.length
] = add
;
30 // and now - the rest of the library
33 this.parse
= yaml_parse
;
34 this.error
= yaml_error
;
35 this.warn
= yaml_warn
;
36 this.parse_throwaway
= yaml_parse_throwaway
;
37 this.parse_node
= yaml_parse_node
;
38 this.parse_next_line
= yaml_parse_next_line
;
39 this.parse_qualifiers
= yaml_parse_qualifiers
;
40 this.parse_explicit
= yaml_parse_explicit
;
41 this.parse_implicit
= yaml_parse_implicit
;
42 this.parse_map
= yaml_parse_map
;
43 this.parse_seq
= yaml_parse_seq
;
44 this.parse_inline
= yaml_parse_inline
;
47 function yaml_error (err
) {
48 err
+= '\nDocument: '+this.document
+'\n';
49 err
+= '\nLine: ' +this.line
+'\n';
50 if (! document
.hide_yaml_errors
) alert(err
);
51 document
.yaml_error_occured
= 1;
55 function yaml_warn (err
) {
56 if (! document
.hide_yaml_errors
) alert(err
);
60 function yaml_parse (text
) {
61 document
.yaml_error_occured
= undefined;
63 // translate line endings down to \012
64 text
= text
.replace(new RegExp('\015\012','g'), '\012');
65 text
= text
.replace(new RegExp('\015','g'), '\012');
66 if (text
.match('[\\x00-\\x08\\x0B-\\x0D\\x0E-\\x1F]'))
67 return this.error("Bad characters found");
68 if (text
.length
&& ! text
.match('\012$'))
72 this.lines
= text
.split("\012");
74 this.documents
= new Array();
76 this.parse_throwaway();
77 if (! this.eoy
&& ! this.lines
[0].match('^---(\\s|$)')) {
78 this.lines
.unshift('--- #YAML:1.0');
82 // loop looking for data structures
84 this.anchors
= new Array();
85 this.offset
= new Array();
86 this.options
= new Array();
95 var m
= this.lines
[0].match('---\\s*(.*)$')
96 if (! m
) return this.error("Missing YAML separator\n("+this.lines
[0]+")");
97 var words
= m
[1].split("\\s+");
98 while (words
.length
&& (m
= words
[0].match('^#(\\w+):(\\S.*)$'))) {
100 if (this.options
[m
[1]]) {
101 yaml
.warn("Parse warn - multiple options " + m
[1]);
104 this.options
[m
[1]] = m
[2];
107 if (this.options
['YAML'] && this.options
['YAML'] != '1.0')
108 return this.error('Bad YAML version number - must be 1.0');
109 if (this.options
['TAB'] && ! this.options
['TAB'].match('^(NONE|\\d+)(:HARD)?$'))
110 return this.error('Unrecognized TAB policy');
112 this.documents
.push(this.parse_node());
115 return this.documents
;
118 function yaml_parse_throwaway () {
119 while (this.lines
.length
&& this.lines
[0].match('^\\s*(#|$)')) {
123 this.eoy
= this.done
= ! this.lines
.length
;
126 function yaml_parse_node (no_next
) {
127 if (! no_next
) this.parse_next_line(2); // COLLECTION
129 var preface
= this.preface
;
137 var info
= this.parse_qualifiers(preface
);
138 var anchor
= info
[0];
140 var explicit
= info
[2];
141 var implicit
= info
[3];
142 var yclass
= info
[4];
147 if (! this.anchors
[alias
]) return this.error("Parse error - missing alias: "+alias
);
148 return this.anchors
[alias
];
151 // see if this is a literal or an unfold block
153 if (preface
.length
) {
154 m
= preface
.match('^([>\\|])([+\\-]?)\\d*\\s*');
158 preface
= preface
.substring(0,m
[0].length
);
160 this.inline
= preface
;
166 if (this.inline
.length
) {
167 node
= this.parse_inline(1, implicit
, explicit
, yclass
);
168 if (this.inline
.length
) return this.error("Parse error - must be single line ("+this.inline
+')');
174 while (! this.done
&& this.indent
== this.offset
[this.level
]) {
175 node
+= this.content
+ '\n';
176 this.parse_next_line(1); // LEAF
178 if (indicator
== '>') {
179 node
= node
.replace(new RegExp('[ \\t]*\n[ \\t]*(\\S)','gm'), ' $1');
181 if (! chomp
|| chomp
== '-') node
= node
.replace(new RegExp('\n$',''),'');
182 if (implicit
) node
= this.parse_implicit(node
);
185 if (! this.offset
[this.level
]) this.offset
[this.level
] = 0;
186 if (this.indent
== this.offset
[this.level
]) {
187 if (this.content
.match('^-( |$)')) {
188 node
= this.parse_seq(anchor
);
189 } else if (this.content
.match('(^\\?|:( |$))')) {
190 node
= this.parse_map(anchor
);
191 } else if (preface
.match('^\\s*$')) {
192 node
= ''; //this.parse_implicit('');
194 return this.error('Parse error - bad node +('+this.content
+')('+preface
+')');
202 this.offset
= this.offset
.splice(0, this.level
+ 1);
205 if (yclass
) return this.error("Parse error - classes not supported");
206 else node
= this.parse_explicit(node
, explicit
);
208 if (anchor
) this.anchors
[anchor
] = node
;
213 function yaml_parse_next_line (type
) {
215 var level
= this.level
;
216 var offset
= this.offset
[level
];
218 if (offset
== undefined) return this.error("Parse error - Bad level " + level
);
220 // done with the current line - get the next
221 // remove following commented lines
224 this.eoy
= this.done
= ! this.lines
.length
;
225 if (this.eoy
) return;
226 this.parse_throwaway();
227 if (this.eoy
) return;
229 // Determine the offset for a new leaf node
230 if (this.preface
&& (m
= this.preface
.match('[>\\|][+\\-]?(\\d*)\\s*$'))) {
231 if (m
[1].length
&& m
[1] == '0') return this.error("Parse error zero indent");
234 this.offset
[level
+ 1] = offset
+ m
[1];
235 } else if ((m
= this.lines
[0].match('^( *)\\S')) && m
[1].length
> offset
) {
236 this.offset
[level
+ 1] = m
[1].length
;
238 this.offset
[level
+ 1] = offset
+ 1;
241 offset
= this.offset
[level
];
245 if (type
== 2 && this.preface
.match('^\\s*(!\\S*|&\\S+)*\\s*$')) {
246 m
= this.lines
[0].match('^( *)\\S');
247 if (! m
) return this.error("Missing leading space on line "+this.lines
[0]);
248 this.offset
[level
+ 1] = (m
[1].length
> offset
) ? m
[1].length : offset
+ 1;
249 offset
= this.offset
[++ level
];
252 } else if (type
== 1) {
253 // skip blank lines and comment lines
254 while (this.lines
.length
&& this.lines
[0].match('^\\s*(#|$)')) {
255 m
= this.lines
[0].match('^( *)');
256 if (! m
) return this.error("Missing leading space on comment " + this.lines
[0]);
257 if (m
[1].length
> offset
) break;
261 this.eoy
= this.done
= ! this.lines
.length
;
263 this.parse_throwaway();
266 if (this.eoy
) return;
267 if (this.lines
[0].match('^---(\\s|$)')) {
272 if (type
== 1 && (m
= this.lines
[0].match('^ {'+offset
+'}(.*)$'))) {
273 this.indent
= offset
;
275 } else if (this.lines
[0].match('^\\s*$')) {
276 this.indent
= offset
;
279 m
= this.lines
[0].match('^( *)(\\S.*)$');
280 // # yaml.warn(" indent(${\length($1)}) offsets(@{$o->{offset}}) \n");
281 var len
= (m
) ? m
[1].length : 0;
282 while (this.offset
[level
] > len
) level
--;
283 if (this.offset
[level
] != len
)
284 return this.error("Parse error inconsitent indentation:\n"
285 + '(this.lines[0]: '+this.lines
[0]+', len: '+len
+', level: '+level
+', this.offset[level]: '+this.offset
[level
]+')\n');
288 this.content
= m
? m
[2] : '';
291 if (this.indent
- offset
> 1)
292 return this.error("Parse error - indentation");
297 function yaml_parse_qualifiers (preface
) {
298 var info
= new Array();
303 // 4 = class - not used for now
307 while (preface
.match('^[&\\*!]')) {
308 // explicit, implicit
309 if (m
= preface
.match('^\!(\\S*)\\s*')) {
310 preface
= preface
.substring(m
[0].length
);
311 if (m
[1].length
) info
[2] = m
[1];
314 } else if (m
= preface
.match('^([&\\*])([^ ,:]+)\\s*')) {
315 preface
= preface
.substring(m
[0].length
);
316 if (! m
[2].match('^\\w+$')) return this.error("Bad name "+m
[2]);
317 if (info
[0] || info
[1]) return this.error("Already found anchor or alias "+m
[2]);
318 if (m
[1] == '&') info
[0] = m
[2];
319 if (m
[1] == '*') info
[1] = m
[2];
327 function yaml_parse_explicit (node
, explicit
) {
329 if (m
= explicit
.match('^(int|float|bool|date|time|datetime|binary)$')) {
330 // return this.error("No handler yet for explict " + m[1]);
331 // just won't check types for now
333 } else if (m
= explicit
.match('^perl/(glob|regexp|code|ref):(\\w(\\w|::)*)?$')) {
334 return this.error("No handler yet for perltype " + m
[1]);
335 } else if (m
= explicit
.match('^perl/(\\@|\\$)?([a-zA-Z](\\w|::)+)$')) {
336 return this.error("No handler yet for perl object " + m
[1]);
337 } else if (! (m
= explicit
.match('/'))) {
338 return this.error("Load error - no conversion "+explicit
);
340 return this.error("No YAML::Node handler made yet "+explicit
);
344 function yaml_parse_implicit (value
) {
345 value
.replace(new RegExp('\\s*$',''),'');
346 if (value
== '') return '';
347 if (value
.match('^-?\\d+$')) return 0 + value
;
348 if (value
.match('^[+-]?(\\d*)(\\.\\d*|)?([Ee][+-]?\\d+)?$')) return 1 * value
;
349 if (value
.match('^\\d{4}\-\\d{2}\-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d*[1-9])?(Z|[-+]\\d{2}(:\\d{2})?))?$')
350 || value
.match('^\\w')) return "" + value
;
351 if (value
== '~') return undefined;
352 if (value
== '+') return 1;
353 if (value
== '-') return 0;
354 return this.error("Parse Error bad implicit value ("+value
+")");
357 function yaml_parse_map (anchor
) {
359 var node
= new Array ();
360 if (anchor
) this.anchors
[anchor
] = node
;
362 while (! this.done
&& this.indent
== this.offset
[this.level
]) {
364 if (this.content
.match('^\\?\\s*')) {
365 this.preface
= this.content
;
366 key
= '' + this.parse_node();
367 } else if (m
= this.content
.match('^=\\s*')) {
368 this.content
= this.content
.substring(m
[0].length
);
369 key
= "\x07YAML\x07VALUE\x07";
370 } else if (m
= this.content
.match('^//\\s*')) {
371 this.content
= this.content
.substring(m
[0].length
);
372 key
= "\x07YAML\x07COMMENT\x07";
375 this.inline
= this.content
;
376 key
= this.parse_inline();
377 this.content
= this.inline
;
381 if (! (m
= this.content
.match('^:\\s*'))) return this.error("Parse error - bad map element "+this.content
);
382 this.content
= this.content
.substring(m
[0].length
);
384 this.preface
= this.content
;
386 var value
= this.parse_node();
388 if (node
[key
]) this.warn('Warn - duplicate key '+key
);
389 else node
[key
] = value
;
396 function yaml_parse_seq (anchor
) {
398 var node
= new Array ();
399 if (anchor
) this.anchors
[anchor
] = node
;
400 while (! this.done
&& this.indent
== this.offset
[this.level
]) {
402 if ((m
= this.content
.match('^- (.*)$')) || (m
= this.content
.match('^-()$'))) {
404 } else return this.error("Parse error - bad seq element "+this.content
);
406 if (m
= this.preface
.match('^(\\s*)(\\w.*:( |$).*)$')) {
407 this.indent
= this.offset
[this.level
] + 2 + m
[1].length
;
409 this.offset
[++ this.level
] = this.indent
;
411 node
.push(this.parse_map(''));
413 this.offset
[this.offset
.length
- 1] = this.level
;
415 node
.push(this.parse_node());
422 function yaml_parse_inline (top
, top_implicit
, top_explicit
, top_class
) {
423 this.inline
= this.inline
.replace('^\\s+','').replace(new RegExp('\\s+$',''),'');
425 var info
= this.parse_qualifiers(this.inline
);
426 var anchor
= info
[0];
428 var explicit
= info
[2];
429 var implicit
= info
[3];
430 var yclass
= info
[4];
431 this.inline
= info
[5];
435 // copy the reference
437 if (! this.anchors
[alias
]) return this.error("Parse error - missing alias: "+alias
);
438 node
= this.anchors
[alias
];
440 // new key based array
441 } else if (m
= this.inline
.match('^\\{\\s*')) {
442 this.inline
= this.inline
.substring(m
[0].length
);
444 while (! (m
= this.inline
.match('^\\}'))) {
445 var key
= this.parse_inline();
446 if (! (m
= this.inline
.match('^:\\s+'))) return this.error("Parse error - bad map element "+this.inline
);
447 this.inline
= this.inline
.substring(m
[0].length
);
448 var value
= this.parse_inline();
449 if (node
[key
]) this.warn("Warn - duplicate key found: "+key
);
450 else node
[key
] = value
;
451 if (this.inline
.match('^\\}')) break;
452 if (! (m
= this.inline
.match('^,\\s*'))) return this.error("Parse error - missing map comma "+this.inline
);
453 this.inline
= this.inline
.substring(m
[0].length
);
455 this.inline
= this.inline
.substring(m
[0].length
);
458 } else if (m
= this.inline
.match('^\\[\\s*')) {
459 this.inline
= this.inline
.substring(m
[0].length
);
461 while (! (m
= this.inline
.match('^\\]'))) {
462 node
.push(this.parse_inline());
463 if (m
= this.inline
.match('^\\]')) break;
464 if (! (m
= this.inline
.match('^,\\s*'))) return this.error("Parse error - missing seq comma "+this.inline
);
465 this.inline
= this.inline
.substring(m
[0].length
);
467 this.inline
= this.inline
.substring(m
[0].length
);
470 } else if (this.inline
.match('^"')) {
471 if (m
= this.inline
.match('^"((?:"|[^"])*)"\\s*(.*)$')) {
473 m
[1] = m
[1].replace(new RegExp('\\\\"','g'),'"');
476 return this.error("Bad double quote "+this.inline
);
478 node
= unescape(node
); // built in
479 if (implicit
|| top_implicit
) node
= this.parse_implicit(node
);
482 } else if (this.inline
.match("^'")) {
483 if (m
= this.inline
.match("^'((?:''|[^'])*)'\\s*(.*)$")) {
485 m
[1] = m
[1].replace(new RegExp("''",'g'),"'");
488 return this.error("Bad single quote "+this.inline
);
490 node
= unescape(node
); // built in
491 if (implicit
|| top_implicit
) node
= this.parse_implicit(node
);
499 if (m
= this.inline
.match('^([^!@#%^&*,\\[\\]{}\\:]*)')) {
500 this.inline
= this.inline
.substring(m
[1].length
);
503 return this.error ("Bad simple match "+this.inline
);
505 if (! explicit
&& ! top_explicit
) node
= this.parse_implicit(node
);
508 if (explicit
|| top_explicit
) {
509 if (! explicit
) explicit
= top_explicit
;
510 if (yclass
) return this.error("Parse error - classes not supported");
511 else node
= this.parse_explicit(node
, explicit
);
514 if (anchor
) this.anchors
[anchor
] = node
;
519 document
.yaml_load = function (text
, anchors
) {
520 var yaml
= new YAML();
521 return yaml
.parse(text
, anchors
);
524 document
.js_dump = function (obj
, name
) {
530 if (typeof(obj
) == 'function') return name
+'=[FUNCTION]\n'
531 if (typeof(obj
) != 'object') return name
+'='+obj
+'\n';
532 var hold
= new Array();
533 for (var i
in obj
) hold
[hold
.length
] = i
;
535 for (var i
= 0; i
< hold
.length
; i
++) {
537 t
+= document
.js_dump(obj
[n
], name
+'.'+n
);
This page took 0.066625 seconds and 4 git commands to generate.