aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Kiryukhin <alexander.kiryukhin@tatar.ru>2012-08-28 18:03:50 +0400
committerAlexander Kiryukhin <alexander.kiryukhin@tatar.ru>2012-08-28 18:03:50 +0400
commit136e5b6a9469e3fa9bb6ee64f5b3a20d2eeb4fc4 (patch)
tree11b6d9b44c5727835eca67df9a803f3b9d671680
parent2490707e5cd7dc70a915a931e4e76a2922011065 (diff)
Alpha of new versionHEADmaster
-rw-r--r--nyaml.php205
-rw-r--r--test.nyaml3
-rw-r--r--test.php8
3 files changed, 131 insertions, 85 deletions
diff --git a/nyaml.php b/nyaml.php
index 2caf399..6ba2716 100644
--- a/nyaml.php
+++ b/nyaml.php
@@ -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'));
+