diff options
author | Alexander Kiryukhin <alexander.kiryukhin@tatar.ru> | 2012-08-28 18:03:50 +0400 |
---|---|---|
committer | Alexander Kiryukhin <alexander.kiryukhin@tatar.ru> | 2012-08-28 18:03:50 +0400 |
commit | 136e5b6a9469e3fa9bb6ee64f5b3a20d2eeb4fc4 (patch) | |
tree | 11b6d9b44c5727835eca67df9a803f3b9d671680 | |
parent | 2490707e5cd7dc70a915a931e4e76a2922011065 (diff) |
-rw-r--r-- | nyaml.php | 205 | ||||
-rw-r--r-- | test.nyaml | 3 | ||||
-rw-r--r-- | test.php | 8 |
3 files changed, 131 insertions, 85 deletions
@@ -1,106 +1,141 @@ <?php -class nyaml { - private $lines; +namespace NXP; - public function file($fileName) { - //Parse file - return $this->string(file_get_contents($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; - public function string($nyaml) { - //Parse string + /** + * Термы + */ + const T_SPACE = 0; + const T_NEWLINE = 1; + const T_CHAR = 2; + const T_QUOTE = 3; + const T_DQUOTE = 4; - //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"); + 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 => '/[\"]/' + ); - $this->lines = explode("\n", $nyaml); - //Parsing - return $this->parse(0); - } + /** + * Таблица переходов состояния + * @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), + ); - private function parse($level) { - $return=array(); - $linelevel = $level; + public function file($fileName) + { + //Parse file + return $this->string(file_get_contents($fileName)); + } - while (count($this->lines)>0) { + public function string($nyaml) + { + $result = array(); + $key = ''; + $value = ''; + for ($i = 0; $i < strlen($nyaml); $i++) { - $line = array_shift($this->lines); - $linelevel = $this->countLevel($line); + $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 ($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); + 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; } - } - 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; + 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; + } } + + $result[$key] = $value; + return $result; } - - private function explode($letter, $string) { - //smart exploding string - $quotes = array("\"","'","[","]"); - $quote = ''; - $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; + + public function getState($char) + { + $currentTerm = null; + foreach ($this->terms as $key => $term) { + if (preg_match($term, $char)) { + $currentTerm = $key; } } - if ($token!='') { - $result[] = $token; + if ($currentTerm === null) { + throw new Exception('Parse error'); } - return $result; - } + foreach ($this->actions as $action) { + if (( $action[0] == $this->state ) && ( $action[1] == $currentTerm )) { - private function countLevel($string) { - //Counting level by indenting - return (strlen($string) - strlen(ltrim($string,"\t "))); + return $action[2]; + } + } } + } diff --git a/test.nyaml b/test.nyaml new file mode 100644 index 0000000..ac55a4a --- /dev/null +++ b/test.nyaml @@ -0,0 +1,3 @@ +node1 value 1 +'node 2' value 2 +'node 3' "value 3"
\ No newline at end of file diff --git a/test.php b/test.php new file mode 100644 index 0000000..b57b514 --- /dev/null +++ b/test.php @@ -0,0 +1,8 @@ +<?php + +include 'nyaml.php'; + +$nyaml = new NXP\nyaml(); + +print_r($nyaml->file('test.nyaml')); + |