!sawlookahead &&
(OP(first) == STAR &&
REGNODE_TYPE(OP(REGNODE_AFTER(first))) == REG_ANY) &&
- !(RExC_rx->intflags & PREGf_ANCH) && !pRExC_state->code_blocks)
+ !(RExC_rx->intflags & PREGf_ANCH) && !(RExC_seen & REG_PESSIMIZE_SEEN))
{
/* turn .* into ^.* with an implied $*=1 */
const int type =
}
if (sawplus && !sawminmod && !sawlookahead
&& (!sawopen || !RExC_sawback)
- && !pRExC_state->code_blocks) /* May examine pos and $& */
+ && !(RExC_seen & REG_PESSIMIZE_SEEN)) /* May examine pos and $& */
/* x+ must match at the 1st pos of run of x's */
RExC_rx->intflags |= PREGf_SKIP;
}
if (RExC_seen & REG_GPOS_SEEN)
RExC_rx->intflags |= PREGf_GPOS_SEEN;
+
+ if (RExC_seen & REG_PESSIMIZE_SEEN)
+ RExC_rx->intflags |= PREGf_PESSIMIZE_SEEN;
+
if (RExC_seen & REG_LOOKBEHIND_SEEN)
RExC_rx->extflags |= RXf_NO_INPLACE_SUBST; /* inplace might break the
lookbehind */
if (pRExC_state->code_blocks)
RExC_rx->extflags |= RXf_EVAL_SEEN;
- if (RExC_seen & REG_VERBARG_SEEN)
- {
+
+ if (RExC_seen & REG_VERBARG_SEEN) {
RExC_rx->intflags |= PREGf_VERBARG_SEEN;
RExC_rx->extflags |= RXf_NO_INPLACE_SUBST; /* don't understand this! Yves */
}
+
if (RExC_seen & REG_CUTGROUP_SEEN)
RExC_rx->intflags |= PREGf_CUTGROUP_SEEN;
+
if (pm_flags & PMf_USE_RE_EVAL)
RExC_rx->intflags |= PREGf_USE_RE_EVAL;
+
if (RExC_paren_names)
RXp_PAREN_NAMES(RExC_rx) = MUTABLE_HV(SvREFCNT_inc(RExC_paren_names));
else
I32 num; /* numeric backreferences */
SV * max_open; /* Max number of unclosed parens */
I32 was_in_lookaround = RExC_in_lookaround;
+ I32 fake_eval = 0; /* matches paren */
/* The difference between the following variables can be seen with *
* the broken pattern /(?:foo/ where segment_parse_start will point *
goto parse_rest;
}
else if ( *RExC_parse == '*') { /* (*VERB:ARG), (*construct:...) */
+ if (RExC_parse[1] == '{') {
+ fake_eval = '{';
+ goto handle_qmark;
+ }
+ else
+ if ( RExC_parse[1] == '*' && RExC_parse[2] == '{' ) {
+ fake_eval = '?';
+ goto handle_qmark;
+ }
+
char *start_verb = RExC_parse + 1;
STRLEN verb_len;
char *start_arg = NULL;
return ret;
}
else if (*RExC_parse == '?') { /* (?...) */
- bool is_logical = 0;
+ handle_qmark:
+ ; /* make sure the label has a statement associated with it*/
+ bool is_logical = 0, is_optimistic = 0;
const char * const seqstart = RExC_parse;
const char * endptr;
const char non_existent_group_msg[]
}
RExC_parse_inc_by(1); /* past the '?' */
- paren = *RExC_parse; /* might be a trailing NUL, if not
- well-formed */
+ if (!fake_eval) {
+ paren = *RExC_parse; /* might be a trailing NUL, if not
+ well-formed */
+ is_optimistic = 0;
+ } else {
+ is_optimistic = 1;
+ paren = fake_eval;
+ }
RExC_parse_inc();
if (RExC_parse > RExC_end) {
paren = '\0';
}
pRExC_state->code_index++;
nextchar(pRExC_state);
+ if (!is_optimistic)
+ RExC_seen |= REG_PESSIMIZE_SEEN;
if (is_logical) {
regnode_offset eval;
ret = reg_node(pRExC_state, LOGICAL);
+ FLAGS(REGNODE_p(ret)) = 2;
eval = reg2Lanode(pRExC_state, EVAL,
n,
* return value */
RExC_flags & RXf_PMf_COMPILETIME
);
- FLAGS(REGNODE_p(ret)) = 2;
+ FLAGS(REGNODE_p(eval)) = is_optimistic * EVAL_OPTIMISTIC_FLAG;
if (! REGTAIL(pRExC_state, ret, eval)) {
REQUIRE_BRANCHJ(flagp, 0);
}
return ret;
}
ret = reg2Lanode(pRExC_state, EVAL, n, 0);
+ FLAGS(REGNODE_p(ret)) = is_optimistic * EVAL_OPTIMISTIC_FLAG;
+
return ret;
}
case '(': /* (?(?{...})...) and (?(?=...)...) */
|| RExC_parse[1] == '<'
|| RExC_parse[1] == '{'))
|| ( RExC_parse[0] == '*' /* (?(*...)) */
- && ( memBEGINs(RExC_parse + 1,
+ && ( RExC_parse[1] == '{'
+ || ( memBEGINs(RExC_parse + 1,
(Size_t) (RExC_end - (RExC_parse + 1)),
"pla:")
|| memBEGINs(RExC_parse + 1,
"negative_lookahead:")
|| memBEGINs(RExC_parse + 1,
(Size_t) (RExC_end - (RExC_parse + 1)),
- "negative_lookbehind:"))))
+ "negative_lookbehind:")))))
) { /* Lookahead or eval. */
I32 flag;
regnode_offset tail;
ret = chain;
}
if (c == 1) {
- *flagp |= flags&SIMPLE;
+ *flagp |= flags & SIMPLE;
}
-
return ret;
}
if (RExC_use_BRANCHJ) {
reginsert(pRExC_state, LONGJMP, ret, depth+1);
reginsert(pRExC_state, NOTHING, ret, depth+1);
- NEXT_OFF(REGNODE_p(ret)) = 3; /* Go over LONGJMP. */
+ REGNODE_STEP_OVER(ret,tregnode_NOTHING,tregnode_LONGJMP);
}
reginsert(pRExC_state, CURLYX, ret, depth+1);
-
if (RExC_use_BRANCHJ)
- NEXT_OFF(REGNODE_p(ret)) = 3; /* Go over NOTHING to
- LONGJMP. */
+ /* Go over NOTHING to LONGJMP. */
+ REGNODE_STEP_OVER(ret,tregnode_CURLYX,tregnode_NOTHING);
+
if (! REGTAIL(pRExC_state, ret, reg_node(pRExC_state,
NOTHING)))
{
/* Finish up the CURLY/CURLYX case */
FLAGS(REGNODE_p(ret)) = 0;
- ARG1_SET(REGNODE_p(ret), (U16)min);
- ARG2_SET(REGNODE_p(ret), (U16)max);
+ ARG1_SET(REGNODE_p(ret), min);
+ ARG2_SET(REGNODE_p(ret), max);
done_main_op:
PERL_ARGS_ASSERT_REGINSERT;
PERL_UNUSED_CONTEXT;
PERL_UNUSED_ARG(depth);
-/* (REGNODE_TYPE((U8)op) == CURLY ? EXTRA_STEP_2ARGS : 0); */
DEBUG_PARSE_FMT("inst"," - %s", REGNODE_NAME(op));
assert(!RExC_study_started); /* I believe we should never use reginsert once we have started
studying. If this is wrong then we need to adjust RExC_recurse
if (srx->logical_to_parno) {
NewCopy(srx->logical_to_parno,
drx->logical_to_parno,
- srx->nparens, I32);
+ srx->nparens+1, I32);
NewCopy(srx->parno_to_logical,
drx->parno_to_logical,
- srx->nparens, I32);
+ srx->nparens+1, I32);
NewCopy(srx->parno_to_logical_next,
drx->parno_to_logical_next,
- srx->nparens, I32);
+ srx->nparens+1, I32);
} else {
drx->logical_to_parno = NULL;
drx->parno_to_logical = NULL;
if (r->logical_to_parno) {
/* we use total_parens for all three just for symmetry */
- ret->logical_to_parno = (I32*)SAVEPVN((char*)(r->logical_to_parno), r->nparens * sizeof(I32));
- ret->parno_to_logical = (I32*)SAVEPVN((char*)(r->parno_to_logical), r->nparens * sizeof(I32));
- ret->parno_to_logical_next = (I32*)SAVEPVN((char*)(r->parno_to_logical_next), r->nparens * sizeof(I32));
+ ret->logical_to_parno = (I32*)SAVEPVN((char*)(r->logical_to_parno), (1+r->nparens) * sizeof(I32));
+ ret->parno_to_logical = (I32*)SAVEPVN((char*)(r->parno_to_logical), (1+r->nparens) * sizeof(I32));
+ ret->parno_to_logical_next = (I32*)SAVEPVN((char*)(r->parno_to_logical_next), (1+r->nparens) * sizeof(I32));
} else {
ret->logical_to_parno = NULL;
ret->parno_to_logical = NULL;