Richard Richard - 3 months ago 11
Perl Question

Renamespacing c++ header with perl - multiline issues

I am trying to enclose the namespace of a c++ header-only library in a custom namespace to avoid symbol name collisions with customer code.

Here is the perl script i wrote. It should enclose the def namespace in the abc namespace.

#!/usr/bin/perl

while (<>) {
s/namespace\s+def\s*
( # group 1 - braced string with balanced number of lbraces and rbraces
\{
( # group 2 - String without braces or recursion to group 1
[^\{\}]* # some string that does not contain braces
| (?1) # recursion of group1
)*
\}
)
/namespace abc {\nnamespace def \1\n}/gcsx;
print;
}


and here is the testfile i am using:

namespace def {}
namespace def { abc }
namespace def { { } }
namespace def { { abcd } }
namespace def {
abc
}
namespace def { // some comment
do_something();
}
namespace def {
do_something();
while (still_not_crashed()) {
do_even_more();
}
}


however running the script on the file only yields

namespace abc {
namespace def {}
}
namespace abc {
namespace def { abc }
}
namespace abc {
namespace def { { } }
}
namespace abc {
namespace def { { abcd } }
}
namespace def {
abc
}
namespace def { // some comment
do_something();
}
namespace def {
do_something();
while (still_not_crashed()) {
do_even_more();
}
}


The one line namespace work just fine but as soon as the pattern that should be matched contains a newline it stops working eventhough i added the s-modifier to my regex.

What am i doing wrong?

Answer

You have to read the whole file in a string then do the substitution on this string:

#!/usr/bin/perl
use Modern::Perl;

undef$/;
$_ = <DATA>;
    s/namespace\s+def\s*
    ( # group 1 - braced string with balanced number of lbraces and rbraces
        \{
        ( # group 2 - String without braces or recursion to group 1
            [^\{\}]* # some string that does not contain braces
            | (?1) # recursion of group1
        )*
        \}
    )
    /namespace abc {\nnamespace def $1\n}/gsx;
    print;


__DATA__
namespace def {}
namespace def { abc }
namespace def { { } }
namespace def { { abcd } }
namespace def {
    abc
}
namespace def { // some comment
    do_something();
}
namespace def {
    do_something();
    while (still_not_crashed()) {
        do_even_more();
    }
}

Output:

namespace abc {
namespace def {}
}
namespace abc {
namespace def { abc }
}
namespace abc {
namespace def { { } }
}
namespace abc {
namespace def { { abcd } }
}
namespace abc {
namespace def {
    abc
}
}
namespace abc {
namespace def { // some comment
    do_something();
}
}
namespace abc {
namespace def {
    do_something();
    while (still_not_crashed()) {
        do_even_more();
    }
}
Comments