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) (...); При компиляции regexp поле engine устанавливается на указанную структуру, чтобы Perl мог найти необходимые функции.
Для установки нового обработчика regexp поле $^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 снимает метки taint со своих собственных переменных захвата в режиме taint (см. perlsec). Обратитесь к функции Perl_reg_numbered_buff_fetch в regcomp.c, чтобы узнать, как снять метку taint с переменных захвата, если вы хотите, чтобы ваш движок тоже это делал.
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 Functions" в 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, содержащую указатели на подпрограммы, которые необходимо использовать для выполнения сопоставления. Компилирующая процедура отвечает за заполнение этого поля перед возвращением объекта regexp.
Внутренне это устанавливается в 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
Это хеш-таблица, используемая внутри для отслеживания именованных групп захватов и их смещений. Ключами являются имена буферов, значениями — dualvars, где слот 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
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.32.0/perlreapi