Gracias, Wikipedia.
ShareCode
Permalink: http://www.treeweb.es/u/974/ 01/02/2011

ShareCode

1 <pre>2 < ?php3 4  /**5  * Documentar esto6  *7  * autor: gerardooscarjt@gmail.com8  * fecha: 13/04/20119  * Uso típico:10  * $parse = TreeScript::getParse($codigo);11  * print_r($parse->getTokens());12  */13  14  class TreeScript {15  16  private $encoding;17  private $pos;18  private $len;19  private $code;20  private $tokens = array();21  private $token = null;22  private $last_key = null;23  private $equal = false;24  private $errors = array();25  private $line = 1;26  27  /**28  * Documentar esto29  */30  private function __construct($code, $encoding='UTF-8') {31  Profiling::start("TreeScript __construct");32  $this->encoding = $encoding;33  $this->pos = 0;34  $this->code = $code;35  $this->len = mb_strlen($code, $this->encoding);36  $this->parse();37  Profiling::end();38  }39  40  /**41  * Documentar esto42  */43  public function getParse($code) {44  return new TreeScript($code);45  }46  47  /**48  * Documentar esto49  */50  51  private function parse() {52  $asignacion = '( *[:|=] *)';53  54  $sin_comillas = '[^ ]*';55  $comillas_simples = "'[^']*'";56  $comillas_dobles = '"[^"]*"';57  $atributos = "(([^ |^=|^:]*)$asignacion($comillas_dobles|$comillas_simples|$sin_comillas))"; // FUNCIONA DE PUTA MADREEEERL58  59  $info1 = array();60  $pattern1 = '((([^\[]|\[(?!\[))*)(\[\[([^ |^\]\]]*)([^\]\]]*)\]\])*(([^\[]|\[(?!\[))*))'; // Obtengo los tokens de texto, los tags y cadenas de atributos61 62  preg_match_all($pattern1, $this->code, $info1, PREG_SET_ORDER );63  64  foreach($info1 as $i) {65  66  if (strlen($i[1])) {67  $this->tokens[] = array(68  'type'=>'text',69  'data'=>$i[1]70  );71  }72  73  if (strlen($i[4])) {74  75  $info2 = array();76  preg_match_all($atributos, $i[5], $info2, PREG_SET_ORDER);77  $data = array();78  foreach ($info2 as $i2) {79  $key = $i2[1];80  $value = $i2[3];81  if ($value[0]=='"') {82  $value = trim($value, '"');83  } else if ($value[0]=="'") {84  $value = trim($value, "'");85  }86  87  $data[$key] = $value;88  }89  90  $this->tokens[] = array(91  'type'=>'token',92  'data'=>$data,93  'name'=>$i[4]94  );95  }96  97  if (strlen($i[6])) {98  $this->tokens[] = array(99  'type'=>'text',100  'data'=>$i[6]101  );102  }103  }104  return true;105  }106  107  private function parse_old() {108  $state = 0;109  $this->tokens = array();110  111  112  $this->token = array('type'=>'text', 'data'=>'');113  $key = null;114  115  while (null !== $c = $this->getc()) {116  if ($c == "\n") $this->line++;117  switch ($state) {118  case 0:119  if ($c == '[') {120  $state = 1;121  } else if ($c == '{') {122  $state = 9;123  } else {124  $this->token['data'] .= $c;125  }126  break;127  case 1:128  if ($c == '[') {129  $this->tokens[] = $this->token;130  $this->token = array('type'=>'token', 'name'=>'', 'data'=>array());131  $state = 2;132  } else {133  $this->token['data'] .= '['.$c;134  $state = 0;135  }136  break;137  case 2:138  if ($this->is_blank($c) || $c == ']') {139  $this->error('Se esperaba un identificador justo después de \'[[\'');140  } else {141  $this->token['name'] = $c;142  $state = 20;143  }144  break;145  case 20:146  if ($this->is_blank($c)) {147  $state = 5;148  } else if ($c == ']') {149  $state = 4;150  } else {151  $this->token['name'] .= $c;152  }153  break;154  case 4:155  if ($c == ']') {156  $this->tokens[] = $this->token;157  $this->token = array('type'=>'text', 'data'=>'');158  $state = 0;159  } else {160  $this->error('Se esperaba \']\'');161  $state = 0;162  }163  break;164  case 5:165  if ($this->is_blank($c)) {166  // No hago nada167  } else if ($c==']') {168  $state = 4;169  } else if ($c=="'") {170  $state = 7;171  } else if ($c=='"') {172  $state = 8;173  } else if ($c=='=' || $c==':') {174  if ($this->equal || $this->last_key == null) {175  $this->error('No se permiten dos asignaciones seguidas (\'=\' o \':\')');176  } else {177  $this->equal = true;178  }179  } else {180  $key = $c;181  $state = 6;182  }183  break;184  case 6:185  if ($this->is_blank($c)) {186  $this->addKey($key);187  $state = 5;188  } else if ($c == ']') {189  $this->addKey($key);190  $state = 4;191  } else if ($c == '=' || $c == ':') {192  $this->addKey($key);193  $state = 5;194  if ($this->equal || $this->last_key == null) {195  $this->error('No se permiten dos asignaciones seguidas (\'=\' o \':\')');196  } else {197  $this->equal = true;198  }199  }else {200  $key .= $c;201  }202  break;203  case 7:204  if ($c=="'") {205  $this->addKey($key);206  $state = 5;207  } else {208  $key .= $c;209  }210  break;211  case 8:212  if ($c=='"') {213  $this->addKey($key);214  $state = 5;215  } else {216  $key .= $c;217  }218  break;219  case 11:220  if ($c =='}') {221  $this->tokens[] = $this->token;222  $this->token = array('type'=>'text', 'data'=>'');223  } else {224  $this->error('Se esperaba una llave de cierre de comentario adicional \'}\'');225  }226  $state = 0;227  break;228  case 10:229  if ($c == '}') {230  $state = 11;231  } else {232  $this->token['data'] .= $c;233  }234  break;235  case 9:236  if ($c == '{') {237  $this->tokens[] = $this->token;238  $this->token = array('type'=>'comment', 'data'=>'');239  $state = 10;240  } else {241  $this->token['data'] .= '{'.$c;242  $state = 0;243  }244  break;245  246  }247  248  }249  250  if ($this->token['type'] == 'text') {251  $this->tokens[] = $this->token;252  } else {253  //ERROR, has dejado un token abierto !!!254  $this->error('Hay una etiqueta abierta, falta de cerrar con \']]\'');255  return false;256  }257  return true;258  }259  260  /**261  * Documentar esto262  */263  public function &getErrors() {264  if (count($this->errors))265  return $this->errors;266  return false;267  }268  269  /**270  * Documentar esto271  */272  private function error($error) {273  $this->errors[] = 'ERROR (line '.$this->line.'): '.$error;274  }275  276  /**277  * Documentar esto278  */279  private function addKey(&$key) {280  if ($this->equal) {281  $this->token['data'][$this->last_key] = $key;282  $this->last_key = null;283  } else {284  $this->token['data'][$key] = null;285  $this->last_key = $key;286  }287  $this->equal = false;288  $key = '';289  }290  291  /**292  * Documentar esto293  */294  private function is_letterordigit($c) {295  return in_array($c, self::$letterordigit);296  }297  298  /**299  * Documentar esto300  */301  private function is_blank($c) {302  return $c == "\n" || $c == "\c" || $c == "\t" || $c == " ";303  }304  305  /**306  * Documentar esto307  */308  private function getc() {309  if ($this->pos < $this->len) {310  $c = mb_substr($this->code, $this->pos, 1, $this->encoding);311  //$c = $this->code[$this->pos];312  $this->pos++;313  return $c;314  } else {315  return null;316  }317  }318  319  /**320  * Documentar esto321  */322  public function &getTokens() {323  return $this->tokens;324  }325  }326 327 328 ?>
Enlace
El enlace para compartir es: