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 очищает свои собственные переменные захвата в режиме taint (см. 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 и может меняться. Должно быть null.
Структура 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, см. коммит 28d8d7f41a.
extflags
Это будет использоваться Perl для определения флагов, с которыми было скомпилировано регулярное выражение. Обычно устанавливается в значение параметра flags обратным вызовом 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
Содержит информацию о самой длинной строке, которая должна появляться на фиксированном смещении от начала шаблона, и самой длинной строке, которая должна появляться на плавающем смещении от начала шаблона. Используется для поиска с помощью алгоритма Бойера-Мура для определения целесообразности использования движка регулярных выражений и, если это целесообразно, места поиска в строке.
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–2021 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.34.0/perlreapi