Changeset 2532
- Timestamp:
- 12/06/07 13:16:54 (5 years ago)
- Files:
-
- 1 modified
-
lang/php/mumu/trunk/GunyaTemplate.php (modified) (8 diffs)
Legend:
- Unmodified
- Added
- Removed
-
lang/php/mumu/trunk/GunyaTemplate.php
r2531 r2532 52 52 class GTNodeList { 53 53 private $nodes; 54 function __construct() { 55 $this->nodes = array(); 56 } 54 57 public function render($context) { 55 58 $bits = array(); 56 foreach ($ nodes as $node) {59 foreach ($this->nodes as $node) { 57 60 array_push($bits, $node->render($context)); 58 61 } 59 62 return implode('', $bits); 60 63 } 64 public function push($node) { 65 array_push($this->nodes, $node); 66 } 61 67 } 62 68 63 69 class GTTextNode extends GTNode { 70 private $text; 71 function __construct($text) { 72 $this->text = $text; 73 } 74 function render($context) { 75 return $text; 76 } 64 77 } 65 78 … … 89 102 90 103 class GTIfNode extends GTNode { 104 private $bool_exprs; 105 private $nodelist_true; 106 private $nodelist_false; 107 private $link_type; 108 109 const LINKTYPE_AND = 0; 110 const LINKTYPE_OR = 1; 111 112 function __construct($bool_exprs, $nodelist_true, $nodelist_false, $link_type) { 113 $this->bool_exprs = $bool_exprs; 114 $this->nodelist_true = $nodelist_true; 115 $this->nodelist_false = $nodelist_false; 116 $this->link_type = $link_type; 117 } 118 function render($context) { 119 if ($this->link_type == self::LINKTYPE_OR) { 120 // TODO: ����(resolve) 121 return $nodelist_false->render($context); 122 } else { // self::LINKTYPE_AND 123 // TODO: ����(resolve) 124 return $nodelist_true>render($context); 125 } 126 } 91 127 } 92 128 93 129 class GTNowNode extends GTNode { 94 } 95 96 class GunyaTemplate { 130 private $format_string; 131 function __construct($format_string) { 132 $this->format_string = $format_string; 133 } 134 function render($context) { 135 return date($this->format_string); 136 } 137 } 138 139 class GTUnknownNode extends GTNode { 140 function render($context) { 141 return 'unknown...'; 142 } 143 } 144 145 class GTParser { 97 146 private $template; // �ѡ�����Υƥ�졼����� private $errorStr; // ���顼ʸ�� private $ptemplate; // �ѡ������ƥ�졼��Node��rray) 98 147 … … 101 150 private $outmode; // 'a': ���'i': ̵��b': �֥�����ɲ� 102 151 # template syntax constants 103 FILTER_SEPARATOR = '|' 104 FILTER_ARGUMENT_SEPARATOR = ':' 105 VARIABLE_ATTRIBUTE_SEPARATOR = '.' 106 BLOCK_TAG_START = '{%' 107 BLOCK_TAG_END = '%}' 108 VARIABLE_TAG_START = '{{' 109 VARIABLE_TAG_END = '}}' 110 COMMENT_TAG_START = '{#' 111 COMMENT_TAG_END = '#}' 112 SINGLE_BRACE_START = '{' 113 SINGLE_BRACE_END = '}' 114 115 function GunyaTemplate($templatePath) { 152 const FILTER_SEPARATOR = '|'; 153 const FILTER_ARGUMENT_SEPARATOR = ':'; 154 const VARIABLE_ATTRIBUTE_SEPARATOR = '.'; 155 const BLOCK_TAG_START = '{%'; 156 const BLOCK_TAG_END = '%}'; 157 const VARIABLE_TAG_START = '{{'; 158 const VARIABLE_TAG_END = '}}'; 159 const COMMENT_TAG_START = '{#'; 160 const COMMENT_TAG_END = '#}'; 161 const SINGLE_BRACE_START = '{'; 162 const SINGLE_BRACE_END = '}'; 163 164 // "��ǥ������Ȥ��줿������ƥ��ڡ�������� // "���"'������ˤϡ�\"\'�Ȥ��롣 165 // �ľ�����ɽ���ǽФ褫�ä������ޤ����ä��� 166 private function smart_split($text) { 167 $epos = strlen($text); 168 $ret = array(); 169 $mode = 'n'; // 'n': not quoted, 'd': in ", 'q': in ' 170 for ($spos = 0; $spos < $epos; $spos++) { 171 $a = $text[$spos]; 172 switch ($a) { 173 case '\\': 174 switch ($mode) { 175 case 'd': 176 if ($text[$spos + 1] == '"') { 177 $buf .= '"'; 178 $spos += 1; 179 } else if ($text[$spos + 1] == '\\') { 180 $buf .= '\\'; 181 $spos += 1; 182 } else { 183 $buf .= $a; 184 } 185 break; 186 case 'q': 187 if ($text[$spos + 1] == "'") { 188 $buf .= "'"; 189 $spos += 1; 190 } else if ($text[$spos + 1] == '\\') { 191 $buf .= '\\'; 192 $spos += 1; 193 } else { 194 $buf .= $a; 195 } 196 break; 197 default: 198 $buf .= '\\'; 199 } 200 break; 201 case "'": 202 switch ($mode) { 203 case 'd': 204 $buf .= "'"; 205 break; 206 case 'q': 207 array_push($ret, $buf); 208 $mode = 'n'; 209 $buf = ''; 210 break; 211 default: 212 if ($buf != '') { 213 array_push($ret, $buf); 214 } 215 $mode = 'q'; 216 $buf = ''; 217 break; 218 } 219 break; 220 case '"': 221 switch ($mode) { 222 case 'd': 223 array_push($ret, $buf); 224 $mode = 'n'; 225 $buf = ''; 226 break; 227 case 'q': 228 $buf .= '"'; 229 break; 230 default: 231 if ($buf != '') { 232 array_push($ret, $buf); 233 } 234 $mode = 'd'; 235 $buf = ''; 236 break; 237 } 238 break; 239 case ' ': 240 switch ($mode) { 241 case 'd': 242 case 'q': 243 $buf .= ' '; 244 break; 245 default: 246 if ($buf != '') { 247 array_push($ret, $buf); 248 $buf = ''; 249 } 250 break; 251 } 252 break; 253 default: 254 $buf .= $a; 255 break; 256 } 257 } 258 if ($mode == 'n' && $buf != '') { 259 array_push($ret, $buf); 260 } 261 return $ret; 116 262 } 117 263 … … 119 265 private function find_closetag($t, &$spos, $closetag) { 120 266 if (($epos = strpos($t, $closetag, $spos)) === FALSE) { 121 $this->errorStr = "������������Ƥʤ��褦�Ǥ�($closetag�����Ĥ�������" 267 $this->errorStr = "������������Ƥʤ��褦�Ǥ�($closetag�����Ĥ�������"; 122 268 return FALSE; 123 269 } … … 128 274 // extends����˽ʤ��Ȥ����ʤ� 129 275 private function parse_block(&$spos) { 130 $spos += 2 131 if (($epos = find_closetag($this->template, $spos, self::BLOCK_TAG_END)) === FALSE) { 276 $spos += 2; 277 if (($epos = $this->find_closetag($this->template, $spos, self::BLOCK_TAG_END)) 278 === FALSE) { 132 279 return FALSE; 133 280 } 134 $in = trim(substr($this->template, $spos, $epos)); 281 $in = $this->smart_split(substr($this->template, $spos, $epos - 2)); 282 echo 'inblock: '. $in[0] .'\n'; 135 283 switch ($in[0]) { 136 284 case 'extends': 137 285 // FIXME: �롼�ץ���å� 138 286 $node = new GTExtendsNode(nodelist, parent_name, parent_name_expr); 287 break; 139 288 case 'include': 140 289 // FIXME: �롼�ץ���å� 141 290 $node = new GTIncludeNode(template_name); 291 break; 142 292 case 'block': // endblock 143 $node = new GTBlockNode(name, nodelist, parent=None); 293 $node = new GTBlockNode(name, nodelist, parent); 294 break; 144 295 case 'for': // endfor 145 296 $node = new GTForNode(loopvar, sequence, reversed, nodelist_loop); 297 break; 146 298 case 'cycle': 147 299 $node = new GTCycleNode(cyclevars); 148 300 // TODO: implement 301 break; 149 302 case 'if': // else, endif 150 303 $node = new GTIfNode(bool_exprs, nodelist_true, nodelist_false, link_type); 304 break; 151 305 case 'debug': 152 306 $node = new GTDebugNode(); 307 break; 153 308 case 'now': 154 $node = new GTNowNode(format_string); 309 var_dump($in); 310 if (count($in) != 2) { 311 $this->errorStr = 'now�Ͻ����ɬ��Ǥ�'; 312 return FALSE; 313 } 314 $node = new GTNowNode($in[1]); 315 break; 316 default: 317 $node = new GTUnknownNode(); 318 break; 155 319 } 156 320 $spos = $epos + 2; … … 165 329 // {{ }}�������� 166 330 private function parse_variable(&$spos) { 167 $spos += 2 331 $spos += 2; 168 332 if (($epos = find_closetag($this->template, $spos, self::VARIABLE_TAG_END)) === FALSE) { 169 333 return FALSE; … … 177 341 // {# #}�������� 178 342 private function parse_comment(&$spos) { 179 $spos += 2 343 $spos += 2; 180 344 if (($epos = find_closetag($this->template, $spos, self::COMMENT_TAG_END)) === FALSE) { 181 345 return FALSE; … … 183 347 $spos = $epos + 2; // #}�Τ��� } 184 348 185 public function parse ($templatePath) {186 if (($t = $file_get_contents($templatePath)) === FALSE) {349 public function parse_from_file($templatePath) { 350 if (($t = file_get_contents($templatePath)) === FALSE) { 187 351 $this->errorStr = '�ե����뤬�����ޤ���; 188 352 return FALSE; 189 353 } 190 $pos = 0;191 192 354 $this->template = $t; 193 194 // �����γ����Ĥ��� while (($pos = strpos($t, self::SINGLE_BRACE_START, $pos)) !== FALSE) { 195 switch (substr($t, pos, 2) { 196 case BLOCK_TAG_START: 197 if (parse_block($pos) === FALSE) { 355 return $this->_parse(0, strlen($t)); 356 } 357 358 public function parse($templateStr) { 359 $this->template = $templateStr; 360 return $this->_parse(0, strlen($templateStr)); 361 } 362 363 private function _parse($spos, $epos) { 364 $nl = new GTNodeList(); 365 while ($spos < $epos) { 366 // �����γ����Ĥ��� $nspos = strpos($this->template, self::SINGLE_BRACE_START, $spos); 367 if ($nspos === FALSE) { 368 $nspos = $epos; 369 } 370 if ($spos < $nspos) { 371 // �����ʳ�����extNode�Ȥ����� 372 $nl->push(new GTTextNode(substr($this->template, $spos, $nspos - $spos))); 373 } 374 switch (substr($this->template, $nspos, 2)) { 375 case self::BLOCK_TAG_START: 376 if (($node = $this->parse_block($nspos)) === FALSE) { 198 377 unset($this->template); 199 378 return FALSE; 200 379 } 201 break; 202 case VARIABLE_TAG_START: 203 if (parse_variable($pos) === FALSE) { 380 $nl->push($node); 381 break; 382 case self::VARIABLE_TAG_START: 383 if (($node = $this->parse_variable($nspos)) === FALSE) { 204 384 unset($this->template); 205 385 return FALSE; 206 386 } 207 break; 208 case COMMENT_TAG_START: 209 if (parse_comment($pos) === FALSE) { 387 $nl->push($node); 388 break; 389 case self::COMMENT_TAG_START: 390 if (($node = $this->parse_comment($nspos)) === FALSE) { 210 391 unset($this->template); 211 392 return FALSE; 212 393 } 394 $nl->push($node); 213 395 break; 214 396 default: 215 397 // ñ�ʤ��ɤߤȤФ� 216 $ pos += 1;398 $nspos += 1; 217 399 } 218 } 219 } 400 $spos = $nspos; 401 } 402 return $nl; 403 } 404 220 405 } 221 406 ?>
![(please configure the [header_logo] section in trac.ini)](/share/chrome/site/your_project_logo.png)