代码之家  ›  专栏  ›  技术社区  ›  Christian

PHP常量字符串参数标记

  •  2
  • Christian  · 技术社区  · 14 年前

    在我们将要使用的系统中,有一个称为“uses”的函数。如果您熟悉pascal,那么uses子句将告诉您的程序它有哪些依赖项(类似于C和PHP包含的依赖项)。 此函数用于进一步控制除include(_once)或require(_once)之外的文件包含。

    作为测试过程的一部分,我需要为静态加载的文件编写一个依赖可视化工具。

    静态加载示例: uses('core/core.php','core/security.php');

    动态加载示例: uses('exts/database.'.$driver.'.php');

    我需要过滤掉动态负载情况,因为代码是静态测试的,而不是运行时测试的。

    这是我现在使用的代码:

    $inuses=false;   // whether currently in uses function or not
    $uses=array();   // holds dependencies (line=>file)
    $tknbuf=array(); // last token
    foreach(token_get_all(file_get_contents($file)) as $token){
        // detect uses function
        if(!$inuses && is_array($token) && $token[0]==T_STRING && $token[1]=='uses')$inuses=true;
        // detect uses argument (dependency file)
        if($inuses && is_array($token) && $token[0]==T_CONSTANT_ENCAPSED_STRING)$tknbuf=$token;
        // detect the end of uses function
        if($inuses && is_string($token) && $token==')'){
            $inuses=false;
            isset($uses[$tknbuf[2]])
                ? $uses[$tknbuf[2]][]=$tknbuf[1]
                : $uses[$tknbuf[2]]=array($tknbuf[1]);
        }
        // a new argument (dependency) is found
        if($inuses && is_string($token) && $token==',')
            isset($uses[$tknbuf[2]])
                ? $uses[$tknbuf[2]][]=$tknbuf[1]
                : $uses[$tknbuf[2]]=array($tknbuf[1]);
    }
    

    注意:知道我正在使用状态引擎来检测参数可能会有帮助。

    我的问题?因为函数中有各种各样的参数,所以很难把它弄对。 也许我没有用正确的方法,但是,我很确定 token_get_all 在这种情况下是最好的。所以也许问题出在我的状态引擎上,它真的没那么好。 我可能错过了一条简单的出路,以为我可以从中得到一些同行的评价。

    编辑: 我采取了解释我这次要做什么的方法,但并不是我想要什么。 简单地说,我需要一个参数数组传递给一个名为“uses”的函数。问题是我对参数有点特别;我只需要一个直字符串数组,根本不需要动态代码(常量、变量、函数调用…)。

    2 回复  |  直到 14 年前
        1
  •  1
  •   Matthew    14 年前

    使用正则表达式:

    <?php
    preg_match_all('/uses\s*\((.+)\s*\)/',
      file_get_contents('uses.php'), $matches, PREG_SET_ORDER);
    
    foreach ($matches as $set) {
      list($full, $match) = $set;
    
      echo "$full\n";
    
      // try to remove function arguments
      $new = $match;
      do {
        $match = $new;
        $new = preg_replace('/\([^()]*\)/', '', $match);
      } while ($new != $match);
    
      // iterate over each of the uses() args
      foreach (explode(',', $match) as $arg) {
        $arg = trim($arg);
        if (($arg[0] == "'" || $arg[0] == '"') && substr($arg,-1) == $arg[0])
        echo "  ".substr($arg,1,-1)."\n";
      }
    }
    ?>
    

    反对:

    uses('bar.php', 'test.php', $foo->bar());
    uses(bar('test.php'), 'file.php');
    uses(bar(foo('a','b','c')), zed());
    

    产量:

    uses('bar.php', 'test.php', $foo->bar())
      bar.php
      test.php
    uses(bar('test.php'), 'file.php')
      file.php
    uses(bar(foo('a','b','c')), zed())
    

    显然它有局限性和假设,但是如果您知道如何调用代码,它就足够了。

        2
  •  1
  •   Christian    14 年前

    好的,我开始工作了。只是对状态引擎进行了一些小的修复。简而言之,参数标记是缓冲的,而不是直接放入uses数组中。接下来,在每个“,”或“)”处检查标记是否有效,并将其添加到uses数组中。

    $inuses=false;   // whether currently in uses function or not
    $uses=array();   // holds dependencies (line=>file)
    $tknbuf=array(); // last token
    $tknbad=false;   // whether last token is good or not
    foreach(token_get_all(file_get_contents($file)) as $token){
        // detect uses function
        if(!$inuses && is_array($token) && $token[0]==T_STRING && $token[1]=='uses')$inuses=true;
        // token found, put it in buffer
        if($inuses && is_array($token) && $token[0]==T_CONSTANT_ENCAPSED_STRING)$tknbuf=$token;
        // end-of-function found check buffer and throw into $uses
        if($inuses && is_string($token) && $token==')'){
            $inuses=false;
            if(count($tknbuf)==3 && !$tknbad)isset($GLOBALS['uses'][$file][$tknbuf[2]])
                    ? $GLOBALS['uses'][$file][$tknbuf[2]][]=$tknbuf[1]
                    : $GLOBALS['uses'][$file][$tknbuf[2]]=array($tknbuf[1]);
            $tknbuf=array(); $tknbad=false;
        }
        // end-of-argument check token and add to $uses
        if($inuses && is_string($token) && $token==','){
            if(count($tknbuf)==3 && !$tknbad)isset($GLOBALS['uses'][$file][$tknbuf[2]])
                ? $GLOBALS['uses'][$file][$tknbuf[2]][]=$tknbuf[1]
                : $GLOBALS['uses'][$file][$tknbuf[2]]=array($tknbuf[1]);
            $tknbuf=array(); $tknbad=false;
        }
        // if current token is not an a simple string, flag all tokens as bad
        if($inuses && is_array($token) && $token[0]!=T_CONSTANT_ENCAPSED_STRING)$tknbad=true;
    }
    

    编辑:事实上它仍然是错误的(尽管是另一个问题)。但我的新想法应该很好地实现。

    推荐文章