Вот довольно простой анализатор обхода строк (изначально я пытался написать для него регулярное выражение, но отсутствие начального ;
в начале многострочного мастера действительно сильно усложнило (без этого ;
отсутствует, это достаточно просто написать). Я сдался и написал это):
function getTokens($string) {
$string = trim($string);;
$lines = explode("\n", $string);
$data = array();
$key = '';
$open = 0;
$buffer = '';
foreach ($lines as $line) {
$line = trim($line);
if (empty($line)) {
continue;
} elseif (strpos($line, '}') === 0) {
$open--;
if ($open == 0) {
$data[$key] = getTokens($buffer);
$buffer = '';
} elseif ($open < 0) {
throw new Exception('Unmatched }');
} else {
$buffer .= "\n" . $line;
}
} elseif ($open > 0) {
if (strpos($line, '{') !== false) {
$open++;
}
$buffer .= "\n" . $line;
} elseif ($line[0] == ';') {
if (strpos($line, "=") !== false) {
list ($key, $value) = explode("=", $line, 2);
$key = trim(substr($key, 1));
$value = trim($value);
$data[$key] = $value;
} elseif (strpos($line, "{") !== false) {
$open++;
list ($key, $value) = explode("{", $line, 2);
$key = trim(substr($key, 1));
} else {
throw new Exception('Unmatched token ;');
}
} elseif (strpos($line, '{') !== false) {
$open++;
list ($key, $value) = explode("{", $line, 2);
$key = trim($key);
} else {
$buffer .= "\n" . $line;
}
}
if ($open > 0) {
throw new Exception('Unmatched {');
} elseif (empty($data) && !empty($buffer)) {
return trim($buffer);
}
return $data;
}
Когда я передаю эту строку в качестве ввода, я получаю:
Array(
"token1" => "I am a top level single line token",
"token2" => "I am a top level
multiline line token",
"master1" => Array(
"servant1" => "I am Master1, Servant1 single line token",
"servant2" => "I am Master1, Servant2.
A mulit line token.",
"servant3" => "I am Master1, Servant3",
),
"master2" => Array(
"servant1" => "I am Master2, Servant1",
"servant2" => "I am Master2, Servant2
A mulit line token.",
"servant3" => "I am Master2, Servant3",
),
)