NOTE: a new version in the Wiki
Had some time to kill, and I thought it would be fun to make a YAML parser (OK, I’ll get back to MPTtree soon :red: ).
It relies heavily on regex, and I haven’t built it as the YAML specification says, but it supports many parts of the YAML standard.
It is built as a helper, so make a file in your helpers dir and copy and paste:
<?php
/*
* Created on 2008 May 31
* by Martin Wernstahl <m4rw3r@gmail.com>
*/
/*
* Copyright (c) 2008, Martin Wernstahl
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * The name of Martin Wernstahl may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY Martin Wernstahl ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL Martin Wernstahl BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
if(!defined('YAYPARSER_key'))
define('YAYPARSER_key','([^\n\S]*)(?:\?[^\S\n]*)?(\S*?)(?:[^\S]*)?:(?:[^\S\n]*)?');
if(!defined('YAYPARSER_list'))
define('YAYPARSER_list','([^\n]*?)?-(?:[\s]*?)');
if(!defined('YAYPARSER_multiline'))
define('YAYPARSER_multiline','(?:(?:\||>)(?:[^\n]*)?\n((?:(?:\1)([^\n\S]+)(?:[^#\n\s][^#\n]*)(?:#.*?)?)(?:\n(?:\1)(?:[^\n\S]+?)(?:[^#\n\s][^#\n]*)(?:#.*?)?)*))');
if(!defined('YAYPARSER_val'))
define('YAYPARSER_val','([^#\n\s][^#\n]*)');
if(!defined('YAYPARSER_comment'))
define('YAYPARSER_comment','(?:#.*?)?');
if(!function_exists('yayparser')){
/**
* YAYParser - Yet Anoter Yaml Parser.
*
* @param $string The string to be processed
*
* @return An array which contains data built from the string
*/
function yayparser($string){
$ret = array();
if(!strlen($string))
return array();
// try to match single "key: value" first
$num = preg_match('@^'.YAYPARSER_key.'(?:'.YAYPARSER_multiline.'|'.YAYPARSER_val.')'.YAYPARSER_comment.'(?:(?:\n([\w\W]*))|$)@',$string,$result);
if($num < 1){
/* if no found, try to match "key:
* key: value"
*/
$num = preg_match('@'.YAYPARSER_key.'(#[^\n]*?)?\n((?:(?:\1)([^\n\S]+?)(?:(?:(?:\?[^\S\n]*)?(?:\S*?)(?:[^\S]*)?:(?:[^\S\n]*)?(?:(?:\||>)(?:[^\S]*)?((?:\1\4(?:[^\n\S]+?)(?:[^#\n\s][^#\n]*)(?:#.*?)?\n)+))|(?:(?:[^#]*?)?))|(?:#[^\n]*?)|(?:-(?:\s*)?(?:[^#\n\s]*)?))(?:#[^\n]*?)?\n)*)([\w\W]*)@',$string,$result);
if($num){
$ret[$result[2]] = yayparser($result[4]);
$ret = $ret + yayparser($result[7]);
return $ret;
}
// try to match all "-listvalue"
$result = array();
preg_match_all('@'.YAYPARSER_list.'(?:'.YAYPARSER_multiline.'|'.YAYPARSER_val.')'.YAYPARSER_comment.'\n@',$string,$result);
foreach($result[4] as $key => $val){
// do we have a multiline?
if(!empty($result[2][$key])){
// yes
$str = explode("\n",$result[2][$key]);
$indent_len = strlen($result[1][$key]) + strlen($result[3][$key]);
array_walk($str,'YAYPARSER_substr',$indent_len);
$ret[$key] = implode("\n",$str);
}
else
$ret[$key] = $val;
// if the line is surrounded with [], remove them and split the line into an array
if($ret[$key][0] == '[' && substr($ret[$key],-1) == ']'){
$ret[$key] = explode(',',trim($ret[$key],'[]'));
}
}
return $ret;
}
if(strlen($result[3])){
// we have multiline
$str = explode("\n",$result[3]);
$indent_len = strlen($result[1]) + strlen($result[4]);
array_walk($str,'YAYPARSER_substr',$indent_len);
$ret[$result[2]] = implode("\n",$str);
}
else // normal
$ret[$result[2]] = trim($result[5]);
// if the line is surrounded with [], remove them and split the line into an array
if($ret[$result[2]][0] == '[' && substr($ret[$result[2]],-1) == ']'){
$ret[$result[2]] = explode(',',trim($ret[$result[2]],'[]'));
}
if(isset($result[6]) && strlen($result[6]))
$ret = $ret + yayparser($result[6]);
return $ret;
}
}
if(!function_exists('YAYPARSER_substr')){
/**
* A substr wrapper for use with array_walk().
*/
function YAYPARSER_substr(&$value,&$key,&$len){
$value = substr($value,$len);
}
}
?>
Whew, only 121 chars left…