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: