public function parse($source){ $root = new Node(); $char = new Char(); $tokenParsers = $this->initParsers(); $token = $this->resetToken(); $len = strlen($source); $parent = array(&$root); $current = new Node(); $inBracket = false; for($i =0; $i<$len; ++$i){ $c = $source[$i]; // handle text first if(in_array($c, array('"', "'", '['))){ $ret = $this->findCDataEnd($source, $this->match[$c], $i+1); $i = $ret[1]; if(!$inBracket && $c == '['){ $this->proceedToken($token, $current, $tokenParsers); $this->resetToken($token); $current->setAttribute('[]', $ret[0]); }else{ $token[$token[0]] .= $ret[0]; } } // ',' ')' and '=' for attributes setting in '()' elseif($c == ',' || $c ==')'){ if($token[$token[0]] != ''){ if($token[0] == 1){ $current->setAtAttribute($token[1]); $this->resetToken($token); }else if($token[0] == 2){ $current->setAttribute($token[1], $token[2]); $this->resetToken($token); }else{ // should be error... } } if($c == ')'){ $inBracket = false; } }else if($c == '='){ $token[0] = 2; } // handle '()' and '{}' bracket else if(in_array($c, array('(', '{', '}'))){ $this->proceedToken($token, $current, $tokenParsers); $this->resetToken($token); if($c == '{'){ array_push($parent, $current); $current = new Node(); }elseif($c == '}'){ $p = array_pop($parent); if(!$current->isEmpty()){ $p->addChild($current); } if(!$p->isEmpty()){ $pp = end($parent); $pp->addChild($p); } $current = new Node(); }elseif($c == '('){ $inBracket = true; } } // handle tokens elseif($char->isSpecialChar($c)){ $this->proceedToken($token, $current, $tokenParsers); $this->resetToken($token); $token[$token[0]] .= $c; }elseif($char->isTokenChar($c)){ $token[$token[0]] .= $c; } else{ $this->proceedToken($token, $current, $tokenParsers); $this->resetToken($token); if(!$current->isEmpty() && !$inBracket){ $p = end($parent); $p->addChild($current); $current = new Node(); } } } $this->proceedToken($token, $current, $tokenParsers); if(!$current->isEmpty() && !$inBracket){ $p = end($parent); $p->addChild($current); } return $root; }