Spec-Zone.ru › Perl 5.28

perlreapi

СОДЕРЖАНИЕ

  • ИМЯ
  • ОПИСАНИЕ
  • Обработчики
    • comp
    • exec
    • intuit
    • checkstr
    • free
    • Обработчики захваченных групп по номеру
      • numbered_buff_FETCH
      • numbered_buff_STORE
      • numbered_buff_LENGTH
    • Обработчики захваченных групп по имени
      • named_buff
      • named_buff_iter
    • qr_package
    • dupe
    • op_comp
  • Структура REGEXP
    • engine
    • mother_re
    • extflags
    • minlen minlenret
    • gofs
    • substrs
    • nparens, lastparen, и lastcloseparen
    • intflags
    • pprivate
    • offs
    • precomp prelen
    • paren_names
    • substrs
    • subbeg sublen saved_copy suboffset subcoffset
    • wrapped wraplen
    • seen_evals
    • refcnt
  • ИСТОРИЯ
  • АВТОРЫ
  • ЛИЦЕНЗИЯ

ИМЯ

perlreapi - Perl интерфейс плагина для регулярных выражений

ОПИСАНИЕ

Начиная с Perl 5.9.5 появился новый интерфейс для подключения и использования движков регулярных выражений, отличных от стандартного.

Каждый движок должен предоставлять доступ к структуре констант следующего формата:

typedef struct regexp_engine {
    REGEXP* (*comp) (pTHX_
                     const SV * const pattern, const U32 flags);
    I32     (*exec) (pTHX_
                     REGEXP * const rx,
                     char* stringarg,
                     char* strend, char* strbeg,
                     SSize_t minend, SV* sv,
                     void* data, U32 flags);
    char*   (*intuit) (pTHX_
                       REGEXP * const rx, SV *sv,
                       const char * const strbeg,
                       char *strpos, char *strend, U32 flags,
                       struct re_scream_pos_data_s *data);
    SV*     (*checkstr) (pTHX_ REGEXP * const rx);
    void    (*free) (pTHX_ REGEXP * const rx);
    void    (*numbered_buff_FETCH) (pTHX_
                                    REGEXP * const rx,
                                    const I32 paren,
                                    SV * const sv);
    void    (*numbered_buff_STORE) (pTHX_
                                    REGEXP * const rx,
                                    const I32 paren,
                                    SV const * const value);
    I32     (*numbered_buff_LENGTH) (pTHX_
                                     REGEXP * const rx,
                                     const SV * const sv,
                                     const I32 paren);
    SV*     (*named_buff) (pTHX_
                           REGEXP * const rx,
                           SV * const key,
                           SV * const value,
                           U32 flags);
    SV*     (*named_buff_iter) (pTHX_
                                REGEXP * const rx,
                                const SV * const lastkey,
                                const U32 flags);
    SV*     (*qr_package)(pTHX_ REGEXP * const rx);
#ifdef USE_ITHREADS
    void*   (*dupe) (pTHX_ REGEXP * const rx, CLONE_PARAMS *param);
#endif
    REGEXP* (*op_comp) (...);

При компиляции регулярного выражения поле engine устанавливается в соответствующую структуру, чтобы Perl мог найти нужные процедуры для её использования.

Для установки нового обработчика регулярных выражений $^H{regcomp} устанавливается в целое число, которое (при соответствующем приведении типов) ссылается на одну из этих структур. При компиляции вызывается метод comp, и ожидается, что поле engine структуры regexp будет указывать на ту же самую структуру.

Символ pTHX_ в определении — это макрос, используемый Perl для поддержки многопоточности, чтобы передать дополнительный аргумент в процедуру, содержащую указатель на интерпретатор, выполняющий регулярное выражение. В многопоточной среде все процедуры получают дополнительный аргумент.

Обработчики

comp

REGEXP* comp(pTHX_ const SV * const pattern, const U32 flags);

Компилирует шаблон, хранящийся в pattern, с заданными flags и возвращает указатель на подготовленную структуру REGEXP, которая может выполнять сопоставление. См. "Структура REGEXP" ниже для объяснения отдельных полей в структуре REGEXP.

Параметр pattern — это скаляр, используемый в качестве шаблона. Предыдущие версии Perl передавали два char*, указывающие начало и конец строкового шаблона; следующий фрагмент можно использовать для получения старых параметров:

STRLEN plen;
char*  exp = SvPV(pattern, plen);
char* xend = exp + plen;

Поскольку в качестве шаблона может передаваться любой скаляр, можно реализовать движок, который работает с массивом ("ook" =~ [ qw/ eek hlagh / ]) или со строковой формой скомпилированного регулярного выражения ("ook" =~ qr/eek/). Собственный движок Perl всегда будет преобразовывать всё в строку, используя фрагмент выше, но это не значит, что другие движки должны делать так же.

Параметр flags — это битовое поле, которое указывает, с какими из msixpn флагов было скомпилировано регулярное выражение. Оно также содержит дополнительную информацию, например, если use locale используется.

Флаги eogc удаляются перед передачей в процедуру comp. Движок регулярных выражений не должен знать, установлены ли какие-либо из них, так как эти флаги должны влиять только на то, как Perl работает с шаблоном и переменными соответствия, а не на то, как он компилируется и выполняется.

К моменту вызова обратного вызова comp некоторые из этих флагов уже подействовали (отмечено ниже, где это применимо). Однако большинство их эффектов происходит после выполнения обратного вызова comp, в процедурах, которые считывают поле rx->extflags, которое оно заполняет.

В общем случае флаги должны сохраняться в rx->extflags после компиляции, хотя движок регулярных выражений может добавить или удалить некоторые из них, чтобы вызвать или отключить некоторое специальное поведение в Perl. Флаги и любое специальное поведение, которое они вызывают, документированы ниже:

Модификаторы шаблонов:

/m - RXf_PMf_MULTILINE

Если это значение в rx->extflags, оно будет передано Perl_fbm_instr посредством pp_split, который будет обрабатывать строку-подлежащую как многострочную строку.

/s - RXf_PMf_SINGLELINE
/i - RXf_PMf_FOLD
/x - RXf_PMf_EXTENDED

Если он присутствует в регулярном выражении, "#" комментарии будут обрабатываться по-другому токенизатором в некоторых случаях.

TODO: Документировать эти случаи.

/p - RXf_PMf_KEEPCOPY

TODO: Документировать это

Набор символов

Правила набора символов определяются перечислением, которое содержится в этом поле. Это всё ещё экспериментально и может измениться, но текущий интерфейс возвращает правила с помощью встроенной функции get_regex_charset(const U32 flags). Единственное в настоящее время документированное значение, возвращаемое ею, это REGEX_LOCALE_CHARSET, которое устанавливается, если use locale используется. Если он присутствует в rx->extflags, split будет использовать зависимое от локали определение пробела, когда RXf_SKIPWHITE или RXf_WHITE установлены. Пробел ASCII определён как в isSPACE, и внутренними макросами is_utf8_space в UTF-8 и isSPACE_LC в use locale.

Дополнительные флаги:

RXf_SPLIT

Этот флаг был удалён в perl 5.18.0. split ' ' теперь обрабатывается специально только в анализаторе. RXf_SPLIT всё ещё определён, поэтому вы можете проверить его. Вот как это работало раньше:

Если split вызывается как split ' ' или без аргументов (что фактически означает split(' ', $_), см. split), Perl установит этот флаг. Движок регулярных выражений затем может проверить его и установить флаги SKIPWHITE и WHITE. Для этого движок Perl делает:

if (flags & RXf_SPLIT && r->prelen == 1 && r->precomp[0] == ' ')
    r->extflags |= (RXf_SKIPWHITE|RXf_WHITE);

Эти флаги могут быть установлены во время компиляции для включения оптимизаций в операторе split.

RXf_SKIPWHITE

Этот флаг был удалён в perl 5.18.0. Он всё ещё определён, поэтому вы можете его установить, но это не повлияет на результат. Вот как это работало раньше:

Если флаг присутствует в rx->extflags, split удалит пробелы из начала строки-подлежащей до её обработки. Что считается пробелом, зависит от того, является ли строка-подлежащая строкой UTF-8 и установлено ли флаг RXf_PMf_LOCALE.

Если RXf_WHITE установлен в дополнение к этому флагу, split будет вести себя как split " " в движке Perl.

RXf_START_ONLY

Указывает оператору split разделять целевую строку по символам перевода строки (\n) без вызова движка регулярных выражений.

Движок Perl устанавливает это, если шаблон — это /^/ (plen == 1 && *exp == '^'), даже в /^/s; см. split. Конечно, другой движок регулярных выражений может использовать те же оптимизации с другим синтаксисом.

RXf_WHITE

Указывает оператору split разделять целевую строку по пробелам без вызова движка регулярных выражений. Определение пробела зависит от того, является ли целевая строка UTF-8 строкой и установлен ли RXf_PMf_LOCALE.

Движок Perl устанавливает этот флаг, если шаблон — \s+.

RXf_NULL

Указывает оператору split разделять целевую строку по символам. Определение символа зависит от того, является ли целевая строка UTF-8 строкой.

Движок Perl устанавливает этот флаг для пустых шаблонов, эта оптимизация делает split // намного быстрее, чем это было бы в противном случае. Это даже быстрее, чем unpack.

RXf_NO_INPLACE_SUBST

Добавлен в perl 5.18.0, этот флаг указывает, что регулярное выражение может выполнить операцию, которая помешает выполнению замены на месте. Например, оно может содержать обратный просмотр или присваивать значения не-магическим переменным (таким как $REGMARK и $REGERROR) во время сопоставления. s/// пропустит некоторые оптимизации, если он установлен.

exec

I32 exec(pTHX_ REGEXP * const rx,
         char *stringarg, char* strend, char* strbeg,
         SSize_t minend, SV* sv,
         void* data, U32 flags);

Выполнить регулярное выражение. Аргументы:

rx

Регулярное выражение для выполнения.

sv

Это SV, который должен быть сопоставлен. Обратите внимание, что фактический массив символов для сопоставления предоставляется аргументами, описанными ниже; SV используется только для определения UTF8, pos() и т. д.

strbeg

Указатель на физическое начало строки.

strend

Указатель на символ, следующий за физическим концом строки (т. е. \0, если таковой имеется).

stringarg

Указатель на позицию в строке, с которой должно начаться сопоставление; она может не совпадать с strbeg (например, на более поздней итерации /.../g).

minend

Минимальная длина строки (измеряется в байтах с stringarg), которая должна совпадать; если движок достигнет конца сопоставления, но не достигнет этой позиции в строке, он должен завершиться неудачей.

data

Данные оптимизации; могут быть изменены.

flags

Флаги оптимизации; могут быть изменены.

intuit

char* intuit(pTHX_
            REGEXP * const rx,
            SV *sv,
            const char * const strbeg,
            char *strpos,
            char *strend,
            const U32 flags,
            struct re_scream_pos_data_s *data);

Найдите начальную позицию, где следует попытаться выполнить сопоставление по регулярному выражению, или, возможно, если движок регулярных выражений не должен запускаться, потому что шаблон не может быть сопоставлен. Это вызывается, соответственно, ядром, в зависимости от значений extflags члена структуры regexp.

Аргументы:

rx:     the regex to match against
sv:     the SV being matched: only used for utf8 flag; the string
        itself is accessed via the pointers below. Note that on
        something like an overloaded SV, SvPOK(sv) may be false
        and the string pointers may point to something unrelated to
        the SV itself.
strbeg: real beginning of string
strpos: the point in the string at which to begin matching
strend: pointer to the byte following the last char of the string
flags   currently unused; set to 0
data:   currently unused; set to NULL

checkstr

SV* checkstr(pTHX_ REGEXP * const rx);

Возвращает SV, содержащий строку, которая должна присутствовать в шаблоне. Используется split для оптимизации сопоставлений.

free

void free(pTHX_ REGEXP * const rx);

Вызывается Perl, когда он освобождает шаблон регулярного выражения, чтобы движок мог освободить любые ресурсы, на которые указывает член pprivate структуры regexp. Это отвечает только за освобождение частных данных; Perl позаботится об освобождении всего остального, содержащегося в структуре regexp.

Числовые обработчики обратного вызова захвата

Вызывается для получения/установки значения $`, $', $& и их именованных эквивалентов, ${^PREMATCH}, ${^POSTMATCH} и ${^MATCH}, а также пронумерованных групп захвата ($1, $2, ...).

Параметр paren будет 1 для $1, 2 для $2 и так далее, и иметь эти символические значения для специальных переменных:

${^PREMATCH}  RX_BUFF_IDX_CARET_PREMATCH
${^POSTMATCH} RX_BUFF_IDX_CARET_POSTMATCH
${^MATCH}     RX_BUFF_IDX_CARET_FULLMATCH
$`            RX_BUFF_IDX_PREMATCH
$'            RX_BUFF_IDX_POSTMATCH
$&            RX_BUFF_IDX_FULLMATCH

Обратите внимание, что в Perl 5.17.3 и более ранних версиях последние три константы также использовались для вариантов с символом ^ переменных.

Имена выбраны по аналогии с именами методов Tie::Scalar с дополнительным обратным вызовом LENGTH для повышения эффективности. Однако именованные переменные захвата в настоящее время не привязаны внутри, а реализованы с помощью магии.

numbered_buff_FETCH

void numbered_buff_FETCH(pTHX_ REGEXP * const rx, const I32 paren,
                         SV * const sv);

Извлечение указанной пронумерованной группы захвата. sv должен быть установлен на скаляр, который нужно вернуть; скаляр передается в качестве аргумента, а не возвращается из функции, потому что когда она вызывается, Perl уже имеет скаляр для хранения значения; создание другого скаляра было бы избыточным. Скаляр может быть установлен с помощью sv_setsv, sv_setpvn и т. д., см. perlapi.

В этом обратном вызове Perl удаляет отметки о загрязнении собственных переменных захвата в режиме загрязнения (см. perlsec). См. функцию Perl_reg_numbered_buff_fetch в regcomp.c, как можно удалить отметки о загрязнении переменных захвата, если вы хотите, чтобы ваш движок тоже это делал.

numbered_buff_STORE

void    (*numbered_buff_STORE) (pTHX_
                                REGEXP * const rx,
                                const I32 paren,
                                SV const * const value);

Установить значение пронумерованной переменной захвата. value — это скаляр, который будет использоваться в качестве нового значения. Движок должен убедиться, что это используется как новое значение (или отклонить его).

Пример:

if ("ook" =~ /(o*)/) {
    # 'paren' will be '1' and 'value' will be 'ee'
    $1 =~ tr/o/e/;
}

Собственный движок Perl выдаст ошибку при любой попытке изменить переменные захвата. Для этого в другом движке используйте следующий обратный вызов (скопированный из Perl_reg_numbered_buff_store):

void
Example_reg_numbered_buff_store(pTHX_
                                REGEXP * const rx,
                                const I32 paren,
                                SV const * const value)
{
    PERL_UNUSED_ARG(rx);
    PERL_UNUSED_ARG(paren);
    PERL_UNUSED_ARG(value);

    if (!PL_localizing)
        Perl_croak(aTHX_ PL_no_modify);
}

На самом деле, Perl не всегда выдаст ошибку в операторе, который выглядит так, как будто он изменяет пронумерованную переменную захвата. Это происходит потому, что обратный вызов STORE не будет вызван, если Perl сможет определить, что ему не нужно изменять значение. Именно так ведут себя привязанные переменные в той же ситуации:

package CaptureVar;
use parent 'Tie::Scalar';

sub TIESCALAR { bless [] }
sub FETCH { undef }
sub STORE { die "This doesn't get called" }

package main;

tie my $sv => "CaptureVar";
$sv =~ y/a/b/;

Поскольку $sv является undef при применении к нему оператора y///, транслитерация фактически не выполняется, и программа не die. Это отличается от поведения версий 5.8 и более ранних, так как переменные захвата были переменными READONLY; теперь они просто погибнут при присваивании в стандартном движке.

numbered_buff_LENGTH

I32 numbered_buff_LENGTH (pTHX_
                          REGEXP * const rx,
                          const SV * const sv,
                          const I32 paren);

Получить length переменной захвата. Для этого есть специальный обратный вызов, чтобы Perl не должен был выполнять FETCH и вызывать length на результате, так как длина (в случае Perl) известна по смещению, хранящемуся в rx->offs, это намного эффективнее:

I32 s1  = rx->offs[paren].start;
I32 s2  = rx->offs[paren].end;
I32 len = t1 - s1;

В случае UTF-8 это немного сложнее, см. что делает Perl_reg_numbered_buff_length с is_utf8_string_loclen.

Обратные вызовы именованного захвата

Вызывается для получения/установки значения %+ и %-, а также некоторыми вспомогательными функциями в re.

Есть два обратных вызова: named_buff вызывается во всех случаях, когда FETCH, STORE, DELETE, CLEAR, EXISTS и SCALAR Tie::Hash обратные вызовы изменяют %+ и %- и named_buff_iter в тех же случаях, что и FIRSTKEY и NEXTKEY.

Параметр flags может использоваться для определения того, на какие операции эти обратные вызовы должны реагировать. В настоящее время определены следующие флаги:

Какая операция Tie::Hash выполняется на уровне Perl для %+ или %+, если таковая имеется:

RXapif_FETCH
RXapif_STORE
RXapif_DELETE
RXapif_CLEAR
RXapif_EXISTS
RXapif_SCALAR
RXapif_FIRSTKEY
RXapif_NEXTKEY

Если %+ или %- изменяется, если таковая имеется.

RXapif_ONE /* %+ */
RXapif_ALL /* %- */

Если это вызывается как re::regname, re::regnames или re::regnames_count, если таковые имеются. Первые два будут объединены с RXapif_ONE или RXapif_ALL.

RXapif_REGNAME
RXapif_REGNAMES
RXapif_REGNAMES_COUNT

Внутренне %+ и %- реализованы с помощью реального интерфейса привязки через Tie::Hash::NamedCapture. Методы в этом пакете будут вызывать эти функции обратно. Однако использование Tie::Hash::NamedCapture для этой цели может измениться в будущих выпусках. Например, это может быть реализовано с помощью магии (потребуется расширение mgvtbl).

named_buff

SV*     (*named_buff) (pTHX_ REGEXP * const rx, SV * const key,
                       SV * const value, U32 flags);

named_buff_iter

SV*     (*named_buff_iter) (pTHX_
                            REGEXP * const rx,
                            const SV * const lastkey,
                            const U32 flags);

qr_package

SV* qr_package(pTHX_ REGEXP * const rx);

Пакет, в который благословляется магический объект qr// (как видно в ref qr//). Рекомендуется, чтобы движки меняли это на имя своего пакета для идентификации независимо от того, реализуют ли они методы на объекте.

Пакет, возвращаемый этим методом, также должен иметь внутренний пакет Regexp в своем @ISA. qr//->isa("Regexp") всегда должно быть истинным независимо от используемого движка.

Пример реализации:

SV*
Example_qr_package(pTHX_ REGEXP * const rx)
{
    PERL_UNUSED_ARG(rx);
    return newSVpvs("re::engine::Example");
}

Любые вызовы методов на объекте, созданном с помощью qr// , будут перенаправлены в пакет как обычный объект.

use re::engine::Example;
my $re = qr//;
$re->meth; # dispatched to re::engine::Example::meth()

Для извлечения объекта REGEXP из скаляра в функции XS используйте макрос SvRX, см. "Функции REGEXP" в perlapi.

void meth(SV * rv)
PPCODE:
    REGEXP * re = SvRX(sv);

dupe

void* dupe(pTHX_ REGEXP * const rx, CLONE_PARAMS *param);

В многопоточных сборках регулярное выражение может потребоваться дублировать, чтобы шаблон можно было использовать в нескольких потоках. Эта процедура должна обрабатывать дублирование любых частных данных, на которые указывает член pprivate структуры regexp. Она будет вызвана с предварительно созданной новой структурой regexp в качестве аргумента, член pprivate будет указывать на старую структуру частных данных, и именно эта процедура отвечает за создание копии и возврат указателя на нее (Perl затем использует ее для перезаписи поля, переданного в эту процедуру).

Это позволяет движку дублировать свои частные данные, но также, если необходимо, изменять конечную структуру, если это действительно необходимо.

В однопоточных сборках это поле не существует.

op_comp

Это закрыто для ядра Perl и может быть изменено. Должно быть нулевым.

Структура REGEXP

Структура REGEXP определена в regexp.h. Все движки регулярных выражений должны иметь возможность правильно создать такую структуру в своей процедуре "comp".

Структура REGEXP содержит все данные, которые Perl нуждается, чтобы правильно работать с регулярным выражением. Она включает данные об оптимизациях, которые Perl может использовать, чтобы определить, должен ли фактически использоваться движок регулярных выражений, и различные другие контрольные данные, которые необходимы для правильного выполнения шаблонов в различных контекстах, таких как если шаблон якорен какой-либо частью, или какие флаги использовались во время компиляции, или если программа содержит специальные конструкции, о которых Perl должен знать.

Кроме того, она содержит два поля, предназначенные для частного использования движка регулярных выражений, который скомпилировал шаблон. Это члены intflags и pprivate. pprivate — указатель на произвольную структуру, использование и управление которой возлагается на компилирующий движок. Perl никогда не будет изменять ни одно из этих значений.

typedef struct regexp {
    /* what engine created this regexp? */
    const struct regexp_engine* engine;

    /* what re is this a lightweight copy of? */
    struct regexp* mother_re;

    /* Information about the match that the Perl core uses to manage
     * things */
    U32 extflags;   /* Flags used both externally and internally */
    I32 minlen;     /* mininum possible number of chars in */
                       string to match */
    I32 minlenret;  /* mininum possible number of chars in $& */
    U32 gofs;       /* chars left of pos that we search from */

    /* substring data about strings that must appear
       in the final match, used for optimisations */
    struct reg_substr_data *substrs;

    U32 nparens;  /* number of capture groups */

    /* private engine specific data */
    U32 intflags;   /* Engine Specific Internal flags */
    void *pprivate; /* Data private to the regex engine which 
                       created this object. */

    /* Data about the last/current match. These are modified during
     * matching*/
    U32 lastparen;            /* highest close paren matched ($+) */
    U32 lastcloseparen;       /* last close paren matched ($^N) */
    regexp_paren_pair *offs;  /* Array of offsets for (@-) and
                                 (@+) */

    char *subbeg;  /* saved or original string so \digit works
                      forever. */
    SV_SAVED_COPY  /* If non-NULL, SV which is COW from original */
    I32 sublen;    /* Length of string pointed by subbeg */
    I32 suboffset;  /* byte offset of subbeg from logical start of
                       str */
    I32 subcoffset; /* suboffset equiv, but in chars (for @-/@+) */

    /* Information about the match that isn't often used */
    I32 prelen;           /* length of precomp */
    const char *precomp;  /* pre-compilation regular expression */

    char *wrapped;  /* wrapped version of the pattern */
    I32 wraplen;    /* length of wrapped */

    I32 seen_evals;   /* number of eval groups in the pattern - for
                         security checks */
    HV *paren_names;  /* Optional hash of paren names */

    /* Refcount of this regexp */
    I32 refcnt;             /* Refcount of this regexp */
} regexp;

Поля обсуждаются подробнее ниже:

engine

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

Внутренне это устанавливается в NULL, если движок не задан в $^H{regcomp}, собственный набор обратных вызовов Perl можно получить из структуры, на которую указывает RE_ENGINE_PTR.

mother_re

TODO, см. http://www.mail-archive.com/perl5-changes@perl.org/msg17328.html

extflags

Perl использует это, чтобы увидеть, с какими флагами было скомпилировано регулярное выражение. Обычно это устанавливается в значение параметра флагов обратным вызовом comp. Смотрите документацию к comp для допустимых флагов.

minlen minlenret

Минимальная длина строки (в символах), необходимая для соответствия шаблону. Это используется для сужения области поиска, не рассматривая соответствия ближе к концу строки, чем это позволяет соответствие. Например, нет смысла даже запускать движок регулярных выражений, если minlen равен 10, а строка имеет длину всего 5 символов. Шаблон не может соответствовать.

minlenret — это минимальная длина (в символах) строки, которая будет найдена в $& после соответствия.

Разница между minlen и minlenret видна в следующем шаблоне:

/ns(?=\d)/

где minlen будет равно 3, но minlenret будет равно только 2, так как \d требуется для соответствия, но фактически не включена в сопоставленную часть. Это различие особенно важно, так как логика подстановки использует minlenret для определения возможности выполнения подстановок на месте (что может значительно ускорить процесс).

gofs

Смещение влево от pos() для начала соответствия.

substrs

Данные о подстроках, которые должны присутствовать в конечном соответствии. В настоящее время это используется только внутренним движком Perl, но в будущем может использоваться для оптимизаций во всех движках.

nparens, lastparen, и lastcloseparen

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

intflags

Внутренняя копия движка флагов, с которыми был скомпилирован шаблон. Обычно это совпадает с extflags, если только движок не изменил какой-либо из них.

pprivate

Указатель void*, указывающий на структуру данных, определённую движком. Движок Perl использует структуру regexp_internal (см. "Базовые структуры" в perlreguts), но пользовательский движок должен использовать что-то другое.

offs

Структура regexp_paren_pair, которая определяет смещения в строке, к которой применяется соответствие, соответствующие $& и $1, $2 и т. д. группам захвата, структура regexp_paren_pair определена следующим образом:

typedef struct regexp_paren_pair {
    I32 start;
    I32 end;
} regexp_paren_pair;

Если ->offs[num].start или ->offs[num].end равны -1, то эта группа захвата не соответствовала. ->offs[0].start/end представляет $& (или ${^MATCH} в /p) и ->offs[paren].end соответствует $$paren, где $paren = 1>.

precomp prelen

Используется для оптимизации. precomp содержит копию скомпилированного шаблона, а prelen — его длину. Когда требуется скомпилировать новый шаблон (например, внутри цикла), внутренний оператор regcomp проверяет, совпадают ли последний скомпилированный шаблон REGEXP и его precomp и prelen с новым шаблоном, и если да, то использует старый шаблон вместо компиляции нового.

Соответствующий фрагмент из Perl_pp_regcomp:

if (!re || !re->precomp || re->prelen != (I32)len ||
    memNE(re->precomp, t, len))
/* Compile a new pattern */

paren_names

Это хэш, используемый во внутренней части для отслеживания именованных групп захвата и их смещений. Ключи — имена буферов, значения — dualvars, где слот IV содержит количество буферов с заданным именем, а pv — встроенный массив I32. Значения также могут быть размещены независимо в массиве данных в случаях использования именованных обратных ссылок.

substrs

Содержит информацию о самой длинной строке, которая должна появляться на фиксированном смещении от начала шаблона, и самой длинной строке, которая должна появляться на плавающем смещении от начала шаблона. Используется для поиска с помощью алгоритма Бойера-Мура для определения целесообразности использования движка регулярных выражений, а при необходимости — поиска в строке.

subbeg sublen saved_copy suboffset subcoffset

Используется на этапе выполнения для управления шаблонами поиска и замены и для предоставления текста для $&, $1 и т. д. subbeg указывает на буфер (оригинальную строку или её копию в случае RX_MATCH_COPIED(rx)), а sublen — длина буфера. Индексы начала и конца RX_OFFS индексируют в этот буфер.

При наличии флага REXEC_COPY_STR, но с добавлением флагов REXEC_COPY_SKIP_PRE или REXEC_COPY_SKIP_POST, движок может выбрать не копировать весь буфер (хотя он должен это сделать при наличии RXf_PMf_KEEPCOPY или соответствующих бит, установленных в PL_sawampersand). В этом случае он может установить suboffset для указания количества байтов от логического начала буфера до физического начала (т. е. subbeg). Он также должен установить subcoffset, количество символов в смещении. Последнее необходимо для поддержки @- и @+, которые работают с символами, а не с байтами.

wrapped wraplen

Содержит строку, к которой qr// строково преобразуется. Например, движок Perl сохраняет (?^:eek) в случае qr/eek/.

При использовании пользовательского движка, который не поддерживает конструкцию (?:) для встроенных модификаторов, лучше всего, чтобы qr// преобразовывался в заданный шаблон. Обратите внимание, что это создаст нежелательные шаблоны в таких случаях, как:

my $x = qr/a|b/;  # "a|b"
my $y = qr/c/i;   # "c"
my $z = qr/$x$y/; # "a|bc"

Для решения этой проблемы нет другого способа, кроме как заставить пользовательский движок понимать конструкцию, подобную (?:).

seen_evals

Хранит количество групп eval в шаблоне. Это используется для безопасности при встраивании скомпилированных регулярных выражений в более крупные шаблоны с qr//.

refcnt

Количество раз, когда структура используется. Когда это значение падает до 0, регулярное выражение автоматически освобождается вызовом pregfree. Это значение должно быть установлено в 1 в процедуре "comp" каждого движка.

ИСТОРИЯ

Первоначально часть perlreguts.

АВТОРЫ

Изначально написан Yves Orton, расширен Ævar Arnfjörð Bjarmason.

ЛИЦЕНЗИЯ

Copyright 2006 Yves Orton и 2007 Ævar Arnfjörð Bjarmason.

Эта программа — свободное программное обеспечение; вы можете распространять и/или изменять её на тех же условиях, что и Perl сам по себе.

© 1993–2020 Larry Wall and others
Licensed under the GNU General Public License version 1 or later, or the Artistic License.
The Perl logo is a trademark of the Perl Foundation.
https://perldoc.perl.org/5.28.3/perlreapi

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API