Как очистить и упростить этот код? - PullRequest
1 голос
/ 04 мая 2010

Подумав о об этом вопросе и ответив на него, я хотел бы больше учиться этому.

Итак, я написал функцию, которая будет вычислять длину данной функции. Данный php-файл должен начинаться с начала нужной функции. Пример: если функция находится в большом php-файле с большим количеством функций, например

/* lots of functions */
function f_interesting($arg) {
    /* function */
}
/* lots of other functions */

тогда $ part3 моей функции потребуется начать так (после запуска { интересной функции):

    /* function */
}
/* lots of other functions */

Теперь это не проблема, но я хотел бы знать, есть ли более чистые или более простые способы сделать это. Вот моя функция: (Я уже убрал много команд тестирования echo) (Идея, стоящая за этим, объясняется здесь )

function f_analysis ($part3) {
    if(isset($part3)) {
        $char_array = str_split($part3); //get array of chars
        $end_key = false; //length of function
        $depth = 0; //How much of unclosed '{'
        $in_sstr = false; //is next char inside in ''-String?
        $in_dstr = false; //is nect char inside an ""-String?
        $in_sl_comment = false; //inside an //-comment?
        $in_ml_comment = false; //inside an /* */-comment?
        $may_comment = false; //was the last char an '/' which can start a comment?
        $may_ml_comment_end = false; //was the last char an '*' which may end a /**/-comment?
        foreach($char_array as $key=>$char) {
            if($in_sstr) {
                if ($char == "'") {
                    $in_sstr = false;
                }
            }
            else if($in_dstr) {
                if($char == '"') {
                    $in_dstr = false;
                }
            }
            else if($in_sl_comment) {
                if($char == "\n") {
                    $in_sl_comment = false;
                }
            }
            else if($in_ml_comment) {
                if($may_ml_comment_end) {
                    $may_ml_comment_end = false;
                    if($char == '/') {
                        $in_ml_comment = false;
                    }
                }
                if($char == '*') {
                    $may_ml_comment_end = true;
                }
            }
            else if ($may_comment) {
                if($char == '/') {
                    $in_sl_comment = true;
                }
                else if($char == '*') {
                    $in_ml_comment = true;
                }
                $may_comment = false;
            }
            else {
                switch ($char) {
                    case '{':
                        $depth++;
                        break;
                    case '}':
                        $depth--;
                        break;
                    case '/':
                        $may_comment = true;
                        break;
                    case '"':
                        $in_dstr = true;
                        break;
                    case "'":
                        $in_sstr = true;
                        break;
                }
            }

            if($depth < 0) {
                $last_key = $key;
                break;
            }
        }
    } else echo '<br>$part3 of f_analysis not set!';
    return ($last_key===false) ? false : $last_key+1; //will be false or the length of the function
}

Ответы [ 2 ]

1 голос
/ 04 мая 2010

Токенайзер ( Пример ) - Узнайте, любите.

0 голосов
/ 04 мая 2010

Возможно, вы могли бы немного уменьшить количество переменных состояния, но, честно говоря ... да, это будет грязный код. Я, вероятно, избавился бы от $may_ml_comment_end и заглянул бы к следующему символу, например, когда натолкнулся на звездочку. Вам нужно будет переписать ваш цикл foreach в обычный цикл for, чтобы сделать это без создания большего беспорядка.

PS: Я не вижу, чтобы вы обрабатывали символ побега. Без вышеуказанного подхода это привело бы к другой булевой переменной.

Другая проблема с вашим текущим кодом состоит в том, что символы, следующие сразу за /, не интерпретируются так, как должны. Однако вряд ли

echo 5/'2';  // NB: no space in between

действует в PHP и нарушит работу вашего парсера.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...