zoukankan      html  css  js  c++  java
  • 写一个属于自己的模板引擎(3)

    接上(2)

    检测所有模版引擎的语句,发现错误和不对的就产生错误!
    成员变量:

    1. private $template//用来保存模版的内容
    2. private $IF_LINE_NUM//用来保存IF所在的行数
    3. private $ENDIF_LINE_NUM//用来保存ENDIF所在的行数
    4. private $FOREACH_LINE_NUM//用来保存FOREACH所在的行数
    5. private $ENDFOREACH_LINE_NUM//用来保存ENDFOREACH所在的行数
    6. private $ERRORS//用来保存错误信息


    构造函数:

    1. public function __construct($file_name NULL) {
    2.         if(isset($file_name) && trim($file_name) != '') {
    3.                 $this->set_file($file_name);
    4.         }
    5. }
    set_file()方法主要是用来打开模版文件和读取文件内容的:
    1. public function set_file($file_name) {
    2.         $file_name TPL_DIR.$file_name;
    3.         if(file_exists($file_name)) {
    4.                 $fp fopen($file_name'r') OR exit('错误:不能打开模板文件');
    5.                 if(($fs filesize($file_name)) > 0)
    6.                 $this->template fread($fp$fs);
    7.                 fclose($fp);
    8.                 return true;
    9.         }
    10.         exit('错误:模板文件不存在');
    11. }
    然后就是到最重要的start方法:
    1. function start($display FALSE) {
    2.         if(strpos($this->template'{#}') !== false) {
    3.                 if(!preg_match("/\{#\}[^({#})]*\{#\}/"$this->template)) {
    4.                         exit('错误:{#}没有关闭');
    5.                 }
    6.         }
    7.         $this->template explode("\n"$this->template);
    8.                 
    9.         $line_number 1;
    10.         foreach($this->template as $line) {
    11.                 if(trim($line) != '') {
    12.                         if(preg_match("/\{\s*if/"$line)) {
    13.                                 $this->IF_LINE_NUM[] = $line_number;
    14.                         }
    15.                         if(preg_match("/\{\s*\/if\s*\}/"$line)) {
    16.                                 $this->ENDIF_LINE_NUM[] = $line_number;
    17.                         }
    18.                         
    19.                                 if(preg_match("/\{\s*\\$[0-9a-zA-Z_]+\->foreach\(\s*[0-9a-zA-Z_]+\s*,\s*[0-9a-zA-Z_]+\s*\)\s*\}/"$line)) {
    20.                                 $this->FOREACH_LINE_NUM[] = $line_number;
    21.                         }
    22.                                 
    23.                         if(preg_match("/\{\s*\/foreach\s*\}/"$line)) {
    24.                                 $this->ENDFOREACH_LINE_NUM[] = $line_number;
    25.                         }
    26.                                 
    27.                         if(strpos($line"{include") !== false) {
    28.                                 if(!preg_match("/\{include \"[^}]*\"\}/"$line)) {
    29.                                         $this->ERRORS[] = '错误:INCLUDE语法使用错误,在行<font color="red">'.$line_number.'</font>';
    30.                                 }
    31.                         }
    32.                 }
    33.                 $line_number++;
    34.         }
    35.         $this->check_if();
    36.         $this->check_foreach();
    37.         if(count($this->ERRORS) > 0) {
    38.                 echo '<div style="border:1px solid #f60;padding:10px;500px;font-size:12px;color:#800;">';
    39.                 foreach($this->ERRORS as $e) {
    40.                         echo $e'<br/>';
    41.                 }
    42.                 echo '</div>';
    43.         } else {
    44.                 if($display)
    45.                         echo $this->highlight_html(implode('',$this->template));
    46.                 echo '<div style="border:1px solid #f60;padding:10px;200px;font-size:12px;text-align:center;color:#800;">恭喜:模版没有错误</div>';
    47.         }
    48. }

    这个方法有点复杂,所以我会一步步说明的:
    (1)
    1. if(strpos($this->template'{#}') !== false) {
    2.         if(!preg_match("/\{#\}[^({#})]*\{#\}/"$this->template)) {
    3.                 exit('错误:{#}没有关闭');
    4.         }
    5. }


    这个语句的用途是检测是否关闭了注释语句,如果没有关闭就强行退出检测!这个检测很简单,就是如果存在{#}但是不存在{#}……{#}就表示没有关闭注释语句。
    (2)
    1. $this->template explode("\n"$this->template);

    这个语句是用来把模版内容按换行来分割成数组。
    (3)
    1. $line_number 1;
    2.         foreach($this->template as $line) {
    这里是循环数组。
    (4)
    1. if(preg_match("/\{\s*if/"$line)) {
    2.         $this->IF_LINE_NUM[] = $line_number;
    3. }
    上面是匹配{if}语句的,并保存行数到IF_LINE_NUM变量中;
    1. if(preg_match("/\{\s*\/if\s*\}/"$line)) {
    2.         $this->ENDIF_LINE_NUM[] = $line_number;
    3. }

    上面是匹配{/if}的,并保存行数到ENDIF _LINE_NUM变量中;
    如此类推:
    1. if(preg_match("/\{\s*\\$[0-9a-zA-Z_]+\->foreach\(\s*[0-9a-zA-Z_]+\s*,\s*[0-9a-zA-Z_]+\s*\)\s*\}/"$line)) {
    2.         $this->FOREACH_LINE_NUM[] = $line_number;
    3. }                                
    4. if(preg_match("/\{\s*\/foreach\s*\}/"$line)) {
    5.         $this->ENDFOREACH_LINE_NUM[] = $line_number;
    6. }

    (5)
    1. if(strpos($line"{include") !== false) {
    2.         if(!preg_match("/\{include \"[^}]*\"\}/"$line)) {
    3.                 $this->ERRORS[] = '错误:INCLUDE语法使用错误,在行<font color="red">'.$line_number.'</font>';
    4.                 }
    5. }

    上面是检测include语法是否正确(是否符合{include “……”})。
    (6)
    1. $this->check_if();
    2. $this->check_foreach();

    调用上面的两个方法;这两个方法是用来检测if和foreach是否嵌套合理和是否关闭了。
    check_if()方法:
    1. private function check_if() {
    2.                 $ifs count($this->IF_LINE_NUM);
    3.                 for($i $i $ifs $i++) {
    4.                         if(isset($this->ENDIF_LINE_NUM[$i])) {
    5.                                 if($this->IF_LINE_NUM[$i] > $this->ENDIF_LINE_NUM[$i]) {
    6.                                         $this->ERRORS[] = '错误:在没有IF的情况下使用END IF,在行<font color="red">'.$this->ENDIF_LINE_NUM[$i].'</font>';
    7.                                 }
    8.                         } else {
    9.                                 $this->ERRORS[] = '错误:IF没有关闭,在行<font color="red">'.$this->IF_LINE_NUM[$i].'</font>';
    10.                         }
    11.                 }
    12.                 if(count($this->IF_LINE_NUM) == && count($this->ENDIF_LINE_NUM) > 0) {
    13.                         foreach($this->ENDIF_LINE_NUM as $line_number) {
    14.                                 $this->ERRORS[] = '错误:在没有IF的情况下使用END IF,在行<font color="red">'.$line_number.'</font>';
    15.                         }
    16.                 }
    17.         }

    从上面的代码可以看出,我们主要是根据IF和ENDIF的函数和数量来判断是否嵌套正确和关闭的!假如EndIF的行数位置比IF要高,就说明没有IF就使用ENDIF了!加入ENDIF和IF的数量不一样,就说明IF没有关闭!!
    Check_foreach()方法:
    1. private function check_foreach() {
    2.                 $foreachs count($this->FOREACH_LINE_NUM);
    3.                 for($i $i $foreachs $i++) {
    4.                         if(isset($this->ENDFOREACH_LINE_NUM[$i])) {
    5.                                 if($this->FOREACH_LINE_NUM[$i] > $this->ENDFOREACH_LINE_NUM[$i]) {
    6.                                         $this->ERRORS[] = '错误:在没有FOREACH的情况下使用END FOREACH,在行<font color="red">'.$this->ENDFOREACH_LINE_NUM[$i].'</font>';
    7.                                 }
    8.                         } else {
    9.                                 $this->ERRORS[] = '错误:FOREACH没有关闭,在行<font color="red">'.$this->FOREACH_LINE_NUM[$i].'</font>';
    10.                         }
    11.                 }
    12.                 if(count($this->FOREACH_LINE_NUM) == && count($this->ENDFOREACH_LINE_NUM) > 0) {
    13.                         foreach($this->ENDFOREACH_LINE_NUM as $line_number) {
    14.                                 $this->ERRORS[] = '错误:在没有FOREACH的情况下使用END FOREACH,在行<font color="red">'.$line_number.'</font>';
    15.                         }
    16.                 }
    17.         }

    Check_forech()方法的原来个check_if()方法一样!!

    (7)
    1. if(count($this->ERRORS) > 0) {
    2.                 echo '<div style="border:1px solid #f60;padding:10px;500px;font-size:12px;color:#800;">';
    3.                 foreach($this->ERRORS as $e) {
    4.                         echo $e'<br/>';
    5.                 }
    6.                 echo '</div>';
    7.         }
    这里是显示错误的!!
    最后就是highlight_html()方法:
    1. private function highlight_html($code)        {
    2.                 $code  str_replace('<''<'$code);
    3.                 $code  str_replace('>''>'$code);
    4.                 $code  =  preg_replace('/([a-zA-Z_]+)=/',  '<font color="#FF0000">$1=</font>',  $code);
    5.                 $code  =  preg_replace('/(<[\/a-zA-Z0-9&;]+)/',  '<font color="#0000FF">$1</font>',  $code);
    6.                 $code  =  str_replace('<!--',  '<font color="#008080"><!--',  $code);
    7.                 $code  =  str_replace('-->',  '--></font>',  $code);
    8.                 $code  =  preg_replace('/[\r\n]+/',  "\n",  $code);
    9.                 $code  nl2br($code);
    10.                 return $code;
    11.         }


    这个方法主要是用来高亮HTML标签的!!在上面那个start()方法中会使用的这个方法!
    至此,我们的模版引擎就完成了!

    Show show全相:
    1. <?php
    2. /**
    3. *
    4. * @author :PHP毛毛虫
    5. * @copyright :2008-12-24圣诞节
    6. *
    7. */
    8. class StupidDebuger {
    9.         private $template;
    10.         private $IF_LINE_NUM;
    11.         private $ENDIF_LINE_NUM;
    12.         private $FOREACH_LINE_NUM;
    13.         private $ENDFOREACH_LINE_NUM;
    14.         private $ERRORS;
    15.         
    16.         public function __construct($file_name NULL) {
    17.                 if(isset($file_name) && trim($file_name) != '') {
    18.                         $this->set_file($file_name);
    19.                 }
    20.         }
    21.         
    22.         public function set_file($file_name) {
    23.                 $file_name TPL_DIR.$file_name;
    24.                 if(file_exists($file_name)) {
    25.                         $fp fopen($file_name'r') OR exit('错误:不能打开模板文件');
    26.                         if(($fs filesize($file_name)) > 0)
    27.                         $this->template fread($fp$fs);
    28.                         fclose($fp);
    29.                         return true;
    30.                 }
    31.                 exit('错误:模板文件不存在');
    32.         }
    33.         
    34.         function start($display FALSE) {
    35.                 if(strpos($this->template'{#}') !== false) {
    36.                         if(!preg_match("/\{#\}[^({#})]*\{#\}/"$this->template)) {
    37.                                 exit('错误:{#}没有关闭');
    38.                         }
    39.                 }
    40.                 $this->template explode("\n"$this->template);
    41.                 
    42.                 $line_number 1;
    43.                 foreach($this->template as $line) {
    44.                         if(trim($line) != '') {
    45.                                 if(preg_match("/\{\s*if/"$line)) {
    46.                                         $this->IF_LINE_NUM[] = $line_number;
    47.                                 }
    48.                                 if(preg_match("/\{\s*\/if\s*\}/"$line)) {
    49.                                         $this->ENDIF_LINE_NUM[] = $line_number;
    50.                                 }
    51.                         
    52.                                 if(preg_match("/\{\s*\\$[0-9a-zA-Z_]+\->foreach\(\s*[0-9a-zA-Z_]+\s*,\s*[0-9a-zA-Z_]+\s*\)\s*\}/"$line)) {
    53.                                         $this->FOREACH_LINE_NUM[] = $line_number;
    54.                                 }
    55.                                 
    56.                                 if(preg_match("/\{\s*\/foreach\s*\}/"$line)) {
    57.                                         $this->ENDFOREACH_LINE_NUM[] = $line_number;
    58.                                 }
    59.                                 
    60.                                 if(strpos($line"{include") !== false) {
    61.                                         if(!preg_match("/\{include \"[^}]*\"\}/"$line)) {
    62.                                                 $this->ERRORS[] = '错误:INCLUDE语法使用错误,在行<font color="red">'.$line_number.'</font>';
    63.                                         }
    64.                                 }
    65.                         }
    66.                         $line_number++;
    67.                 }
    68.                 $this->check_if();
    69.                 $this->check_foreach();
    70.                 if(count($this->ERRORS) > 0) {
    71.                         echo '<div style="border:1px solid #f60;padding:10px;500px;font-size:12px;color:#800;">';
    72.                         foreach($this->ERRORS as $e) {
    73.                                 echo $e'<br/>';
    74.                         }
    75.                         echo '</div>';
    76.                 } else {
    77.                         if($display)
    78.                                 echo $this->highlight_html(implode('',$this->template));
    79.                         echo '<div style="border:1px solid #f60;padding:10px;200px;font-size:12px;text-align:center;color:#800;">恭喜:模版没有错误</div>';
    80.                 }
    81.         }
    82.         
    83.         private function check_if() {
    84.                 $ifs count($this->IF_LINE_NUM);
    85.                 for($i $i $ifs $i++) {
    86.                         if(isset($this->ENDIF_LINE_NUM[$i])) {
    87.                                 if($this->IF_LINE_NUM[$i] > $this->ENDIF_LINE_NUM[$i]) {
    88.                                         $this->ERRORS[] = '错误:在没有IF的情况下使用END IF,在行<font color="red">'.$this->ENDIF_LINE_NUM[$i].'</font>';
    89.                                 }
    90.                         } else {
    91.                                 $this->ERRORS[] = '错误:IF没有关闭,在行<font color="red">'.$this->IF_LINE_NUM[$i].'</font>';
    92.                         }
    93.                 }
    94.                 if(count($this->IF_LINE_NUM) == && count($this->ENDIF_LINE_NUM) > 0) {
    95.                         foreach($this->ENDIF_LINE_NUM as $line_number) {
    96.                                 $this->ERRORS[] = '错误:在没有IF的情况下使用END IF,在行<font color="red">'.$line_number.'</font>';
    97.                         }
    98.                 }
    99.         }
    100.         
    101.         private function check_foreach() {
    102.                 $foreachs count($this->FOREACH_LINE_NUM);
    103.                 for($i $i $foreachs $i++) {
    104.                         if(isset($this->ENDFOREACH_LINE_NUM[$i])) {
    105.                                 if($this->FOREACH_LINE_NUM[$i] > $this->ENDFOREACH_LINE_NUM[$i]) {
    106.                                         $this->ERRORS[] = '错误:在没有FOREACH的情况下使用END FOREACH,在行<font color="red">'.$this->ENDFOREACH_LINE_NUM[$i].'</font>';
    107.                                 }
    108.                         } else {
    109.                                 $this->ERRORS[] = '错误:FOREACH没有关闭,在行<font color="red">'.$this->FOREACH_LINE_NUM[$i].'</font>';
    110.                         }
    111.                 }
    112.                 if(count($this->FOREACH_LINE_NUM) == && count($this->ENDFOREACH_LINE_NUM) > 0) {
    113.                         foreach($this->ENDFOREACH_LINE_NUM as $line_number) {
    114.                                 $this->ERRORS[] = '错误:在没有FOREACH的情况下使用END FOREACH,在行<font color="red">'.$line_number.'</font>';
    115.                         }
    116.                 }
    117.         }
    118.         
    119.         private function highlight_html($code)        {
    120.                 $code  str_replace('<''<'$code);
    121.                 $code  str_replace('>''>'$code);
    122.                 $code  =  preg_replace('/([a-zA-Z_]+)=/',  '<font color="#FF0000">$1=</font>',  $code);
    123.                 $code  =  preg_replace('/(<[\/a-zA-Z0-9&;]+)/',  '<font color="#0000FF">$1</font>',  $code);
    124.                 $code  =  str_replace('<!--',  '<font color="#008080"><!--',  $code);
    125.                 $code  =  str_replace('-->',  '--></font>',  $code);
    126.                 $code  =  preg_replace('/[\r\n]+/',  "\n",  $code);
    127.                 $code  nl2br($code);
    128.                 return $code;
    129.         }
    130. }
  • 相关阅读:
    JZ-C-36
    JZ-C-35
    JZ-C-34
    JZ-C-33
    JZ-C-32
    JZ-C-31
    JZ-C-30
    JZ-C-29
    JZ-C-28
    JZ-C-27
  • 原文地址:https://www.cnblogs.com/kuyuecs/p/1390633.html
Copyright © 2011-2022 走看看