perlreapi
СОДЕРЖАНИЕ
ИМЯ
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
Эти поля используются для отслеживания: количества групп захвата в скобках в шаблоне; какой скобке соответствует самое последнее закрытие (см. "$+" в perlvar); и какой была последняя закрывающая скобка (см. "$^N" в perlvar).
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
Это хэш, используемый для отслеживания именованных групп захвата и их смещений. Ключами являются имена буферов, а значениями — двойные переменные, где IV-слот хранит количество буферов с данным именем, а pv — вложенный массив I32. Значения также могут быть содержаться независимо в массиве данных в случаях, когда используются именованные обратные ссылки.
substrs
Содержит информацию о самой длинной строке, которая должна появляться на фиксированном смещении от начала шаблона, и самой длинной строке, которая должна появляться на плавающем смещении от начала шаблона. Используется для поиска Fast-Boyer-Moore в строке, чтобы определить, стоит ли вообще использовать движок регулярных выражений, и если да, то где в строке его искать.
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" каждого движка.
HISTORY
Изначально часть perlreguts.
AUTHORS
Первоначально написано Yves Orton, расширено Ævar Arnfjörð Bjarmason.
LICENSE
Авторское право 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.30.3/perlreapi