/**----------------------------------------------------------------*** * Copyright 2007 - Paul Seamons * * Distributed under the Perl Artistic License without warranty * * Based upon YAML.pm v0.35 from Perl * ***----------------------------------------------------------------**/ // $Revision: 1.18 $ // allow for missing methods in ie 5.0 if (! Array.prototype.unshift) Array.prototype.unshift = function (add) { for (var i=this.length; i > 0; i--) this[i] = this[i - 1]; this[0] = add; }; if (!Array.prototype.shift) Array.prototype.shift = function () { var ret = this[0]; for (var i=0; i\\|])([+\\-]?)\\d*\\s*'); if (m) { indicator = m[1]; chomp = m[2]; preface = preface.substring(0,m[0].length); } else { this.inline = preface; preface = ''; } } if (this.inline.length) { node = this.parse_inline(1, implicit, explicit, yclass); if (this.inline.length) return this.error("Parse error - must be single line ("+this.inline+')'); } else { this.level ++; // block items if (indicator) { node = ''; while (! this.done && this.indent == this.offset[this.level]) { node += this.content + '\n'; this.parse_next_line(1); // LEAF } if (indicator == '>') { node = node.replace(new RegExp('[ \\t]*\n[ \\t]*(\\S)','gm'), ' $1'); } if (! chomp || chomp == '-') node = node.replace(new RegExp('\n$',''),''); if (implicit) node = this.parse_implicit(node); } else { if (! this.offset[this.level]) this.offset[this.level] = 0; if (this.indent == this.offset[this.level]) { if (this.content.match('^-( |$)')) { node = this.parse_seq(anchor); } else if (this.content.match('(^\\?|:( |$))')) { node = this.parse_map(anchor); } else if (preface.match('^\\s*$')) { node = ''; //this.parse_implicit(''); } else { return this.error('Parse error - bad node +('+this.content+')('+preface+')'); } } else { node = ''; } } this.level -- } this.offset = this.offset.splice(0, this.level + 1); if (explicit) { if (yclass) return this.error("Parse error - classes not supported"); else node = this.parse_explicit(node, explicit); } if (anchor) this.anchors[anchor] = node; return node; } function yaml_parse_next_line (type) { var m; var level = this.level; var offset = this.offset[level]; if (offset == undefined) return this.error("Parse error - Bad level " + level); // done with the current line - get the next // remove following commented lines this.lines.shift(); this.line ++; this.eoy = this.done = ! this.lines.length; if (this.eoy) return; this.parse_throwaway(); if (this.eoy) return; // Determine the offset for a new leaf node if (this.preface && (m = this.preface.match('[>\\|][+\\-]?(\\d*)\\s*$'))) { if (m[1].length && m[1] == '0') return this.error("Parse error zero indent"); type = 1; if (m[1].length) { this.offset[level + 1] = offset + m[1]; } else if ((m = this.lines[0].match('^( *)\\S')) && m[1].length > offset) { this.offset[level + 1] = m[1].length; } else { this.offset[level + 1] = offset + 1; } level ++; offset = this.offset[level]; } // COLLECTION if (type == 2 && this.preface.match('^\\s*(!\\S*|&\\S+)*\\s*$')) { m = this.lines[0].match('^( *)\\S'); if (! m) return this.error("Missing leading space on line "+this.lines[0]); this.offset[level + 1] = (m[1].length > offset) ? m[1].length : offset + 1; offset = this.offset[++ level]; // LEAF } else if (type == 1) { // skip blank lines and comment lines while (this.lines.length && this.lines[0].match('^\\s*(#|$)')) { m = this.lines[0].match('^( *)'); if (! m) return this.error("Missing leading space on comment " + this.lines[0]); if (m[1].length > offset) break; this.lines.shift(); this.line ++; } this.eoy = this.done = ! this.lines.length; } else { this.parse_throwaway(); } if (this.eoy) return; if (this.lines[0].match('^---(\\s|$)')) { this.done = 1; return; } if (type == 1 && (m = this.lines[0].match('^ {'+offset+'}(.*)$'))) { this.indent = offset; this.content = m[1]; } else if (this.lines[0].match('^\\s*$')) { this.indent = offset; this.content = ''; } else { m = this.lines[0].match('^( *)(\\S.*)$'); // # yaml.warn(" indent(${\length($1)}) offsets(@{$o->{offset}}) \n"); var len = (m) ? m[1].length : 0; while (this.offset[level] > len) level --; if (this.offset[level] != len) return this.error("Parse error inconsitent indentation:\n" + '(this.lines[0]: '+this.lines[0]+', len: '+len+', level: '+level+', this.offset[level]: '+this.offset[level]+')\n'); this.indent = len; this.content = m ? m[2] : ''; } if (this.indent - offset > 1) return this.error("Parse error - indentation"); return; } function yaml_parse_qualifiers (preface) { var info = new Array(); // 0 = anchor // 1 = alias // 2 = explicit // 3 = implicit // 4 = class - not used for now // 5 = preface var m; while (preface.match('^[&\\*!]')) { // explicit, implicit if (m = preface.match('^\!(\\S*)\\s*')) { preface = preface.substring(m[0].length); if (m[1].length) info[2] = m[1]; else info[3] = 1; // anchor, alias } else if (m = preface.match('^([&\\*])([^ ,:]+)\\s*')) { preface = preface.substring(m[0].length); if (! m[2].match('^\\w+$')) return this.error("Bad name "+m[2]); if (info[0] || info[1]) return this.error("Already found anchor or alias "+m[2]); if (m[1] == '&') info[0] = m[2]; if (m[1] == '*') info[1] = m[2]; } } info[5] = preface; return info; } function yaml_parse_explicit (node, explicit) { var m; if (m = explicit.match('^(int|float|bool|date|time|datetime|binary)$')) { // return this.error("No handler yet for explict " + m[1]); // just won't check types for now return node; } else if (m = explicit.match('^perl/(glob|regexp|code|ref):(\\w(\\w|::)*)?$')) { return this.error("No handler yet for perltype " + m[1]); } else if (m = explicit.match('^perl/(\\@|\\$)?([a-zA-Z](\\w|::)+)$')) { return this.error("No handler yet for perl object " + m[1]); } else if (! (m = explicit.match('/'))) { return this.error("Load error - no conversion "+explicit); } else { return this.error("No YAML::Node handler made yet "+explicit); } } function yaml_parse_implicit (value) { value.replace(new RegExp('\\s*$',''),''); if (value == '') return ''; if (value.match('^-?\\d+$')) return 0 + value; if (value.match('^[+-]?(\\d*)(\\.\\d*|)?([Ee][+-]?\\d+)?$')) return 1 * value; if (value.match('^\\d{4}\-\\d{2}\-\\d{2}(T\\d{2}:\\d{2}:\\d{2}(\\.\\d*[1-9])?(Z|[-+]\\d{2}(:\\d{2})?))?$') || value.match('^\\w')) return "" + value; if (value == '~') return undefined; if (value == '+') return 1; if (value == '-') return 0; return this.error("Parse Error bad implicit value ("+value+")"); } function yaml_parse_map (anchor) { var m; var node = new Array (); if (anchor) this.anchors[anchor] = node; while (! this.done && this.indent == this.offset[this.level]) { var key; if (this.content.match('^\\?\\s*')) { this.preface = this.content; key = '' + this.parse_node(); } else if (m = this.content.match('^=\\s*')) { this.content = this.content.substring(m[0].length); key = "\x07YAML\x07VALUE\x07"; } else if (m = this.content.match('^//\\s*')) { this.content = this.content.substring(m[0].length); key = "\x07YAML\x07COMMENT\x07"; } else { this.inline = this.content; key = this.parse_inline(); this.content = this.inline; this.inline = ''; } if (! (m = this.content.match('^:\\s*'))) return this.error("Parse error - bad map element "+this.content); this.content = this.content.substring(m[0].length); this.preface = this.content; var value = this.parse_node(); if (node[key]) this.warn('Warn - duplicate key '+key); else node[key] = value; } return node; } function yaml_parse_seq (anchor) { var m; var node = new Array (); if (anchor) this.anchors[anchor] = node; while (! this.done && this.indent == this.offset[this.level]) { var m; if ((m = this.content.match('^- (.*)$')) || (m = this.content.match('^-()$'))) { this.preface = m[1]; } else return this.error("Parse error - bad seq element "+this.content); if (m = this.preface.match('^(\\s*)(\\w.*:( |$).*)$')) { this.indent = this.offset[this.level] + 2 + m[1].length; this.content = m[2]; this.offset[++ this.level] = this.indent; this.preface = ''; node.push(this.parse_map('')); this.level --; this.offset[this.offset.length - 1] = this.level; } else { node.push(this.parse_node()); } } return node; } function yaml_parse_inline (top, top_implicit, top_explicit, top_class) { this.inline = this.inline.replace('^\\s+','').replace(new RegExp('\\s+$',''),''); var info = this.parse_qualifiers(this.inline); var anchor = info[0]; var alias = info[1]; var explicit = info[2]; var implicit = info[3]; var yclass = info[4]; this.inline = info[5]; var node; var m; // copy the reference if (alias) { if (! this.anchors[alias]) return this.error("Parse error - missing alias: "+alias); node = this.anchors[alias]; // new key based array } else if (m = this.inline.match('^\\{\\s*')) { this.inline = this.inline.substring(m[0].length); node = new Array (); while (! (m = this.inline.match('^\\}'))) { var key = this.parse_inline(); if (! (m = this.inline.match('^:\\s+'))) return this.error("Parse error - bad map element "+this.inline); this.inline = this.inline.substring(m[0].length); var value = this.parse_inline(); if (node[key]) this.warn("Warn - duplicate key found: "+key); else node[key] = value; if (this.inline.match('^\\}')) break; if (! (m = this.inline.match('^,\\s*'))) return this.error("Parse error - missing map comma "+this.inline); this.inline = this.inline.substring(m[0].length); } this.inline = this.inline.substring(m[0].length); // new array } else if (m = this.inline.match('^\\[\\s*')) { this.inline = this.inline.substring(m[0].length); node = new Array (); while (! (m = this.inline.match('^\\]'))) { node.push(this.parse_inline()); if (m = this.inline.match('^\\]')) break; if (! (m = this.inline.match('^,\\s*'))) return this.error("Parse error - missing seq comma "+this.inline); this.inline = this.inline.substring(m[0].length); } this.inline = this.inline.substring(m[0].length); // double quoted } else if (this.inline.match('^"')) { if (m = this.inline.match('^"((?:"|[^"])*)"\\s*(.*)$')) { this.inline = m[2]; m[1] = m[1].replace(new RegExp('\\\\"','g'),'"'); node = m[1]; } else { return this.error("Bad double quote "+this.inline); } node = unescape(node); // built in if (implicit || top_implicit) node = this.parse_implicit(node); // single quoted } else if (this.inline.match("^'")) { if (m = this.inline.match("^'((?:''|[^'])*)'\\s*(.*)$")) { this.inline = m[2]; m[1] = m[1].replace(new RegExp("''",'g'),"'"); node = m[1]; } else { return this.error("Bad single quote "+this.inline); } node = unescape(node); // built in if (implicit || top_implicit) node = this.parse_implicit(node); // simple } else { if (top) { node = this.inline; this.inline = ''; } else { if (m = this.inline.match('^([^!@#%^&*,\\[\\]{}\\:]*)')) { this.inline = this.inline.substring(m[1].length); node = m[1]; } else { return this.error ("Bad simple match "+this.inline); } if (! explicit && ! top_explicit) node = this.parse_implicit(node); } } if (explicit || top_explicit) { if (! explicit) explicit = top_explicit; if (yclass) return this.error("Parse error - classes not supported"); else node = this.parse_explicit(node, explicit); } if (anchor) this.anchors[anchor] = node; return node; } document.yaml_load = function (text, anchors) { var yaml = new YAML(); return yaml.parse(text, anchors); } document.js_dump = function (obj, name) { var t = ''; if (! name) { name = '[obj]'; t = 'Dump:\n' } if (typeof(obj) == 'function') return name+'=[FUNCTION]\n' if (typeof(obj) != 'object') return name+'='+obj+'\n'; var hold = new Array(); for (var i in obj) hold[hold.length] = i; hold = hold.sort(); for (var i = 0; i < hold.length; i++) { var n = hold[i]; t += document.js_dump(obj[n], name +'.'+n); } return t; } // the end