Alpha of new version
This commit is contained in:
parent
2490707e5c
commit
136e5b6a94
3 changed files with 138 additions and 92 deletions
217
nyaml.php
217
nyaml.php
|
@ -1,106 +1,141 @@
|
|||
<?php
|
||||
|
||||
class nyaml {
|
||||
private $lines;
|
||||
namespace NXP;
|
||||
|
||||
public function file($fileName) {
|
||||
class nyaml
|
||||
{
|
||||
/**
|
||||
* Состояния
|
||||
*/
|
||||
const PARSE_KEY = 0;
|
||||
const PARSE_VALUE = 1;
|
||||
const PARSE_INDENT = 2;
|
||||
const PARSE_KEY_IN_QUOTE = 3;
|
||||
const PARSE_KEY_IN_DQUOTE = 4;
|
||||
const PARSE_VALUE_IN_QUOTE = 5;
|
||||
const PARSE_VALUE_IN_DQUOTE = 6;
|
||||
|
||||
/**
|
||||
* Термы
|
||||
*/
|
||||
const T_SPACE = 0;
|
||||
const T_NEWLINE = 1;
|
||||
const T_CHAR = 2;
|
||||
const T_QUOTE = 3;
|
||||
const T_DQUOTE = 4;
|
||||
|
||||
private $state = 0, $result = array();
|
||||
/**
|
||||
* Термы
|
||||
* @var array
|
||||
*/
|
||||
private $terms = array(
|
||||
self::T_SPACE => '/[\s|\t]/',
|
||||
self::T_NEWLINE => '/[\n]/',
|
||||
self::T_CHAR => '/[a-zA-Zа-яА-Я0-9]/',
|
||||
self::T_QUOTE => '/[\']/',
|
||||
self::T_DQUOTE => '/[\"]/'
|
||||
);
|
||||
|
||||
/**
|
||||
* Таблица переходов состояния
|
||||
* @var array
|
||||
*/
|
||||
private $actions = array(
|
||||
array(self::PARSE_KEY, self::T_CHAR, self::PARSE_KEY),
|
||||
array(self::PARSE_KEY, self::T_SPACE, self::PARSE_VALUE),
|
||||
array(self::PARSE_KEY, self::T_NEWLINE, self::PARSE_VALUE),
|
||||
array(self::PARSE_VALUE, self::T_NEWLINE, self::PARSE_KEY),
|
||||
array(self::PARSE_VALUE, self::T_SPACE, self::PARSE_VALUE),
|
||||
array(self::PARSE_VALUE, self::T_CHAR, self::PARSE_VALUE),
|
||||
array(self::PARSE_KEY, self::T_QUOTE, self::PARSE_KEY_IN_QUOTE),
|
||||
array(self::PARSE_KEY, self::T_DQUOTE, self::PARSE_KEY_IN_DQUOTE),
|
||||
array(self::PARSE_VALUE, self::T_QUOTE, self::PARSE_VALUE_IN_QUOTE),
|
||||
array(self::PARSE_VALUE, self::T_DQUOTE, self::PARSE_VALUE_IN_DQUOTE),
|
||||
array(self::PARSE_KEY_IN_QUOTE, self::T_QUOTE, self::PARSE_KEY),
|
||||
array(self::PARSE_KEY_IN_DQUOTE, self::T_DQUOTE, self::PARSE_KEY),
|
||||
array(self::PARSE_VALUE_IN_QUOTE, self::T_QUOTE, self::PARSE_VALUE),
|
||||
array(self::PARSE_VALUE_IN_DQUOTE, self::T_DQUOTE, self::PARSE_VALUE),
|
||||
array(self::PARSE_KEY_IN_QUOTE, self::T_CHAR, self::PARSE_KEY_IN_QUOTE),
|
||||
array(self::PARSE_KEY_IN_DQUOTE, self::T_CHAR, self::PARSE_KEY_IN_DQUOTE),
|
||||
array(self::PARSE_VALUE_IN_QUOTE, self::T_CHAR, self::PARSE_VALUE_IN_QUOTE),
|
||||
array(self::PARSE_VALUE_IN_DQUOTE, self::T_CHAR, self::PARSE_VALUE_IN_DQUOTE),
|
||||
array(self::PARSE_KEY_IN_QUOTE, self::T_SPACE, self::PARSE_KEY_IN_QUOTE),
|
||||
array(self::PARSE_KEY_IN_DQUOTE, self::T_SPACE, self::PARSE_KEY_IN_DQUOTE),
|
||||
array(self::PARSE_VALUE_IN_QUOTE, self::T_SPACE, self::PARSE_VALUE_IN_QUOTE),
|
||||
array(self::PARSE_VALUE_IN_DQUOTE, self::T_SPACE, self::PARSE_VALUE_IN_DQUOTE),
|
||||
array(self::PARSE_KEY_IN_QUOTE, self::T_NEWLINE, self::PARSE_KEY_IN_QUOTE),
|
||||
array(self::PARSE_KEY_IN_DQUOTE, self::T_NEWLINE, self::PARSE_KEY_IN_DQUOTE),
|
||||
array(self::PARSE_VALUE_IN_QUOTE, self::T_NEWLINE, self::PARSE_VALUE_IN_QUOTE),
|
||||
array(self::PARSE_VALUE_IN_DQUOTE, self::T_NEWLINE, self::PARSE_VALUE_IN_DQUOTE),
|
||||
);
|
||||
|
||||
public function file($fileName)
|
||||
{
|
||||
//Parse file
|
||||
return $this->string(file_get_contents($fileName));
|
||||
}
|
||||
|
||||
public function string($nyaml) {
|
||||
//Parse string
|
||||
|
||||
//Preprocessing
|
||||
$nyaml = preg_replace("/(\n|^)\s*\#.*?\n/", "\n", $nyaml); //Cleaning from one-line comments
|
||||
$nyaml = str_replace("\r", "", $nyaml); //Fix new lines
|
||||
$nyaml = str_replace("\n\n", "\n", $nyaml); //Cleaning clear lines
|
||||
$nyaml = trim($nyaml,"\n");
|
||||
|
||||
$this->lines = explode("\n", $nyaml);
|
||||
//Parsing
|
||||
return $this->parse(0);
|
||||
}
|
||||
|
||||
private function parse($level) {
|
||||
$return=array();
|
||||
$linelevel = $level;
|
||||
|
||||
while (count($this->lines)>0) {
|
||||
|
||||
$line = array_shift($this->lines);
|
||||
$linelevel = $this->countLevel($line);
|
||||
|
||||
if ($linelevel<$level) { //If next line from root node stop parsing
|
||||
array_unshift($this->lines, $line);
|
||||
return $return;
|
||||
}
|
||||
if (substr($line,-1,1)==":") { //If new node
|
||||
$key = substr($line, 0, strlen($line)-1);
|
||||
$value = $this->parse($linelevel+1);
|
||||
$return[trim($key)] = $value;
|
||||
} elseif (strpos($line,":")!==false) { //If key-value pair
|
||||
list($key, $value) = explode(":", $line, 2);
|
||||
$return[trim($key)] = $this->parseValue($value);
|
||||
} else { //If just value
|
||||
$return[] = trim($line);
|
||||
}
|
||||
}
|
||||
return $return;
|
||||
}
|
||||
|
||||
private function parseValue($value) {
|
||||
$value = trim($value);
|
||||
switch (substr($value,0,1)) {
|
||||
case "\"":
|
||||
return substr($value,1,(strlen($value)-2));
|
||||
break;
|
||||
case "'":
|
||||
return substr($value,1,(strlen($value)-2));
|
||||
break;
|
||||
case "[":
|
||||
$result = $this->explode(",", substr($value,1,(strlen($value)-2)));
|
||||
$result = array_map(array($this, "parseValue"), $result);
|
||||
return $result;
|
||||
break;
|
||||
default:
|
||||
return $value;
|
||||
}
|
||||
}
|
||||
|
||||
private function explode($letter, $string) {
|
||||
//smart exploding string
|
||||
$quotes = array("\"","'","[","]");
|
||||
$quote = '';
|
||||
public function string($nyaml)
|
||||
{
|
||||
$result = array();
|
||||
$token = "";
|
||||
for ($i = 0; $i<strlen($string); $i++) {
|
||||
$symbol = substr($string,$i,1);
|
||||
if ((in_array($symbol, $quotes)) && ($quote == '')) {
|
||||
if ($symbol == '[') {
|
||||
$symbol = ']';
|
||||
}
|
||||
$quote = $symbol;
|
||||
} elseif ((in_array($symbol, $quotes)) && ($quote == $symbol)) {
|
||||
if ($quote == ']') {
|
||||
$token = "[$token]";
|
||||
}
|
||||
$quote = '';
|
||||
} elseif (($symbol == $letter) && ($quote=='')) {
|
||||
$result[] = $token;
|
||||
$token = '';
|
||||
} else {
|
||||
$token .= $symbol;
|
||||
$key = '';
|
||||
$value = '';
|
||||
for ($i = 0; $i < strlen($nyaml); $i++) {
|
||||
|
||||
$char = substr($nyaml, $i, 1);
|
||||
$oldState = $this->state;
|
||||
$newState = $this->getState($char);
|
||||
$this->state = $newState;
|
||||
if (($newState == self::PARSE_KEY) && ($oldState == self::PARSE_VALUE)) {
|
||||
$result[$key] = $value;
|
||||
$key = '';
|
||||
$value = '';
|
||||
|
||||
}
|
||||
if (($newState == self::PARSE_KEY) && ($oldState == self::PARSE_KEY) && ($oldState != self::PARSE_VALUE_IN_QUOTE) && ($oldState != self::PARSE_VALUE_IN_DQUOTE)) {
|
||||
$key.=$char;
|
||||
}
|
||||
if ( ($newState == self::PARSE_VALUE) && ($oldState != self::PARSE_VALUE_IN_QUOTE) && ($oldState != self::PARSE_VALUE_IN_DQUOTE) ) {
|
||||
$value.=$char;
|
||||
}
|
||||
|
||||
if (($newState == self::PARSE_KEY_IN_QUOTE) && ($oldState != self::PARSE_KEY)) {
|
||||
$key.=$char;
|
||||
}
|
||||
if (($newState == self::PARSE_KEY_IN_DQUOTE) && ($oldState != self::PARSE_KEY)) {
|
||||
$key.=$char;
|
||||
}
|
||||
|
||||
if (($newState == self::PARSE_VALUE_IN_QUOTE) && ($oldState != self::PARSE_VALUE)) {
|
||||
$value.=$char;
|
||||
}
|
||||
if (($newState == self::PARSE_VALUE_IN_DQUOTE) && ($oldState != self::PARSE_VALUE)) {
|
||||
$value.=$char;
|
||||
}
|
||||
}
|
||||
if ($token!='') {
|
||||
$result[] = $token;
|
||||
}
|
||||
|
||||
$result[$key] = $value;
|
||||
return $result;
|
||||
}
|
||||
|
||||
private function countLevel($string) {
|
||||
//Counting level by indenting
|
||||
return (strlen($string) - strlen(ltrim($string,"\t ")));
|
||||
public function getState($char)
|
||||
{
|
||||
$currentTerm = null;
|
||||
foreach ($this->terms as $key => $term) {
|
||||
if (preg_match($term, $char)) {
|
||||
$currentTerm = $key;
|
||||
}
|
||||
}
|
||||
if ($currentTerm === null) {
|
||||
throw new Exception('Parse error');
|
||||
}
|
||||
foreach ($this->actions as $action) {
|
||||
if (( $action[0] == $this->state ) && ( $action[1] == $currentTerm )) {
|
||||
|
||||
return $action[2];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
3
test.nyaml
Normal file
3
test.nyaml
Normal file
|
@ -0,0 +1,3 @@
|
|||
node1 value 1
|
||||
'node 2' value 2
|
||||
'node 3' "value 3"
|
8
test.php
Normal file
8
test.php
Normal file
|
@ -0,0 +1,8 @@
|
|||
<?php
|
||||
|
||||
include 'nyaml.php';
|
||||
|
||||
$nyaml = new NXP\nyaml();
|
||||
|
||||
print_r($nyaml->file('test.nyaml'));
|
||||
|
Loading…
Reference in a new issue