Извлечь аргумент функции из исходного кода PHP - PullRequest
0 голосов
/ 21 марта 2011

Из сценария оболочки я хотел бы иметь возможность извлечь аргумент функции из исходного кода PHP, например:

->getUrl(<extract-me>, false)

, но с проблемой, что <extract-me> может быть любым, что позволяет PHPкак открывающая или закрывающая скобка, но и более сложные вещи ...

Спасибо

1 Ответ

2 голосов
/ 25 марта 2011

Поскольку ваш вопрос помечен как "perl", я предполагаю, что вы примете решение Perl.

Моей первой мыслью было использование модуля Text :: Balanced , в частности: extract_codeblock (который на самом деле предназначен для Perl, но Perl и PHP достаточно похожи для анализа, чтобы получить приемлемые результаты) но это было не так просто, как я надеялся: extract_codeblock только правильно вытащил выражение, если оно заключено в квадратные скобки (начинается с "{" или "(").

Что ж, с помощью этого модуля и написания моего собственного подкомпонента, объединяющего процедуры разбора токенов, я получил нечто, что внешне кажется работающим.

use Text::Balanced qw(extract_bracketed extract_quotelike);
sub extract_expression {
    local $_ = shift;
    my $parsed;
    while(1) {
        if(s&^(\s*)((?:(?!//|/\*|#)[^[{(\]),;'"'\s])+)&&) {
            # normal characters (no delimiters, quotes or brackets, or comments)
            $parsed .= "$1$2";
        } elsif(/^\s*(?=['"'])/) {
            # quotes
            (my $token, $_) = extract_quotelike($_, '\'"');
            defined $token or last;
            $parsed .= $token;
        } elsif(/^\s*(?=[\[\{\(])/) {
            # brackets
            (my $token, $_) = extract_bracketed($_, '[({\'"})]');
            defined $token or last;
            $parsed .= $token;
        } elsif(s&^\s*(?://|\#).*\n?&& || s&^\s*/\*.*?\*/&&s) {
            # comments
            # ignore
        } else {
            # not recognized
            # finished
            last;
        }
    }
    return $parsed, $_;
}

# demo
# complex line of PHP (borrowed from Drupal)
$_ = <<'PHP';
$translations[$lang] = $this->drupalCreateNode(array('type' => $source->type, 'language' => $lang, 'translation_source' => $source, 'status' => $source->status, 'promote' => $source->promote, 'uid' => $source->uid));
# etc
PHP

if(/->drupalCreateNode\(/) {
    my $offset = $+[0];   # position right after opening paren
    my($expression, $rest) = extract_expression(substr($_, $offset));
    if(defined $expression) {
        print <<"INFO";
parsed expression: $expression
rest: $rest
INFO
    } else {
        print "Failure to parse expression\n";
    }
}

Ну, я подумал ... комментарии в PHP отличаются от комментариев в Perl, и внешне я обработал комментарии PHP, но, к сожалению, процедура не рекурсивна и только комментарии за пределами любые заключены в скобки выражения должным образом игнорируются. Внутренние комментарии могут запутать синтаксический анализатор (extract_bracketed).

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