This is a live mirror of the Perl 5 development currently hosted at https://github.com/perl/perl5
make re_evals be seen by the toker/parser
authorDavid Mitchell <davem@iabyn.com>
Sat, 23 Jul 2011 20:29:02 +0000 (21:29 +0100)
committerDavid Mitchell <davem@iabyn.com>
Wed, 13 Jun 2012 12:25:48 +0000 (13:25 +0100)
commit9da1dd8f41c98df713957a658aa8fefcdf57163c
tree6e699deb4737149b04a9810c392ed0f7e082fb6b
parentecd2417115c94639d7dd7fb772dc8fc460b0ed57
make re_evals be seen by the toker/parser

This commit is a first step to making the handling of (/(?{...})/ more sane.
But see the big proviso at the end.

Currently a patten like /a(?{...})b/ is uninterpreted by the lexer and
parser, and is instead passed as-is to the regex compiler, which is
responsible for ensuring that the embedded perl code is extracted and
compiled. The only thing the quoted string code in the lexer currently
does is to skip nested matched {}'s, in order to get to end of the code
block and restart looking for interpolated variables, \Q etc.

This commit makes the lexer smarter.

Consider the following pattern:

    /FOO(?{BLOCK})BAR$var/

This is currently tokenised as

    op_match
    (
    op_const["FOO(?{BLOCK})BAR"]
    ,
    $
    "var"
    )

Instead, tokenise it as:

    op_match
    (
    op_const["FOO"]
    ,
    DO
    {
    BLOCK
    ;
    }
    ,
    op_const["(?{BLOCK})"]
    ,
    op_const["BAR"]
    ,
    $
    "var"
    )

This means that BLOCK is itself tokenised and parsed. We also insert
a const into the stream to include the original source text of BLOCK so
that it's available for stringifying qr's etc.

Note that by allowing the lexer/parser direct access to BLOCK, we can now
handle things like
    /(?{"{"})/

This mechanism is similar to the way something like

    "abc $a[foo(q(]))] def"

is currently parsed: the double-quoted string handler in the lexer stops
at $a[, the 'foo(q(]))' is treated as perl code, then at the end control is
passed back to the string handler to handle the ' def'.

This commit includes a new error message:

    Sequence (?{...}) not terminated with ')'

since when control is passed back to the quoted-string handler, it expects
to find the ')' as the next char. This new error mostly replaces the old

    Sequence (?{...}) not terminated or not {}-balanced in regex

Big proviso:

This commit updates toke.c to recognise the embedded code, but doesn't
then do anything with it. The parser will pass both a compiled do block
and a const for each embedded (?{..}), and Perl_pmruntime just throws
away the do block and keeps the constant text instead which is passed to
the regex compiler. So currently each code block gets compiled twice (!)
with two sets of warnings etc. The next stage will be to pass these do
blocks to the regex compiler.

This commit is based on a patch I had originally worked up about 6 years
ago and has been sitting bit-rotting ever since.
op.c
perl.h
pod/perldiag.pod
t/lib/strict/vars
t/op/blocks.t
t/re/re_tests
t/re/reg_mesg.t
t/run/fresh_perl.t
toke.c