regex 正则表达式将所有旧的强制转换样式更改为c++文件中的static_cast样式

hpcdzsge  于 2023-01-10  发布在  其他
关注(0)|答案(3)|浏览(171)

我是一个正则表达式的新手,我尝试写一个C#应用程序,将所有旧的C++文件转换为static_cast风格。
例如:

(void)memcpy(&a[0],(void * )hihi, (UBYTE) V_SIZE);
(void) memcpy((VOID*)abc, (const VOID*) dafa, (uint8)NUMBER_SIZE);
(void )memcpy(
        (void *)p,
        &abc, (uint8)DATE_SIZE);

我想他们都应该

static_cast<void>(memcpy(&a[0], static_cast<void * >(hihi), static_cast<UBYTE>( V_SIZE)));
static_cast<void> memcpy(static_cast<VOID*>(abc), static_cast<const VOID*> (hihi), static_cast<uint8>(NUMBER_SIZE));
static_cast<void >memcpy(
        static_cast<void *>(p),
        &abc, static_cast<uint8>(DATE_SIZE));

我也在调查和尝试这一个

List<string> castTypeList = new List<string>
{"void", "void *", "UBYTE", "uint8", "VOID*", "uint8" };

// Fix qacpp-4.7.0-3080 This expression uses old style casts
// Only apply for cpp source file (.cpp)
if ((Path.GetExtension(sourceFile) == ".cpp"))
{
    foreach (string e in castTypeList)
    {
        File.WriteAllText(sourceFile, Regex.Replace(
            File.ReadAllText(sourceFile),
            @"\(" + e + @"\)([^):;\r\n},]*)",
            "static_cast<" + e + @">($1)"));
    }
}

结果看起来不错,但并不完美,有些字符串无法匹配和替换(你可以看到下图)。有没有更好的解决方案或更好的想法来处理它?

pobjuy32

pobjuy321#

您可以使用以下模式进行匹配和替换,直到找不到匹配项:

(?i)\(\s*((?:const\s+)?(?:u?(?:byte|int)\d*|void)(?:\s*\*)?)\s*\)\s*(\w+(?:\((?>[^()]+|(?<c>)\(|(?<-c>)\))*\))?)

请参见regex demo
在C#中,您可以使用

var text = @"(void)memcpy(&a[0],(void * )hihi, (UBYTE) V_SIZE);\n(void) memcpy((VOID*)abc, (const VOID*) dafa, (uint8)NUMBER_SIZE);\n(void )memcpy(\n        (void *)p,\n        &abc, (uint8)DATE_SIZE)";
var pattern = @"(?i)\(\s*((?:const\s+)?(?:u?(?:byte|int)\d*|void)(?:\s*\*)?)\s*\)\s*(\w+(?:\((?>[^()]+|(?<c>)\(|(?<-c>)\))*\))?)";
var tmp = string.Empty;
do
{
    tmp = text;
    text = Regex.Replace(text, pattern, "static_cast<$1>($2)");
}
while (text != tmp);
Console.WriteLine(text);

参见C# demo。输出:

static_cast<void>(memcpy(&a[0],static_cast<void *>(hihi), static_cast<UBYTE>(V_SIZE)));
static_cast<void>(memcpy(static_cast<VOID*>(abc), static_cast<const VOID*>(dafa), static_cast<uint8>(NUMBER_SIZE)));
static_cast<void>(memcpy(
        static_cast<void *>(p),
        &abc, static_cast<uint8>(DATE_SIZE)));
q3qa4bjr

q3qa4bjr2#

我终于自己找到了解决办法。

List<string> part_one_CastTypeList = new List<string>
{"void", "void "};

List<string> part_two_CastTypeList = new List<string>
{"void * ", "UBYTE", "VOID*", "const VOID*", "uint8", "void *"};

if ((Path.GetExtension(sourceFile) == ".cpp"))
{
    foreach (string e in part_one_CastTypeList)
    {
        string castType = null;
        foreach (char c in e)
        {
            castType = castType + '[' + c + ']';
        }
        // Match multi pattern, variant is inside function (Applicable for void type)
        // i.e (void)memcpy((FLOAT)a, (void *) b, (uint8)c)
        // ==> static_cast<void>memcpy((FLOAT)a, (void *) b, (uint8)c)
        File.WriteAllText(sourceFile, Regex.Replace(
            File.ReadAllText(sourceFile),
            @"\(" + castType + @"\)([^;\r\n}]*)(\);)",
            "static_cast<" + e + @">($1)$2"));
    }
    foreach (string e in part_two_CastTypeList)
    {
        string castType = null;
        foreach(char c in e)
        {
            castType = castType + '[' + c + ']';
        }
        // Match single pattern, variant is not inside function (Not applicable for void type)
        // i.e (uint8)0x00,(uint16)0x01, (SW) 0x02
        // ==> static_cast<uint8>(0x00),static_cast<uint16>(0x01), static_cast<SW>(0x02),
        File.WriteAllText(sourceFile, Regex.Replace(
            File.ReadAllText(sourceFile),
            @"\(" + castType + @"\)([^:\/;)\r\n},]*)",
            "static_cast<" + e + @">($1)"));
    }
}

我将正则表达式分成两部分。第一部分(第一个for循环)将匹配函数的类型转换。在第一个for循环完成后,函数的所有类型转换都应该像下面这样替换

static_cast<void>(memcpy(&a[0],(void * )hihi, (UBYTE) V_SIZE));
static_cast<void>( memcpy((VOID*)abc, (const VOID*) dafa, (uint8)NUMBER_SIZE));
static_cast<void >(memcpy(
        (void *)p,
        &abc, (uint8)DATE_SIZE));

第2部分(第二个for循环)将匹配变量的类型转换,并替换所有其余部分,如下所示

static_cast<void>(memcpy(&a[0],static_cast<void * >(hihi), static_cast<UBYTE>( V_SIZE)));
static_cast<void>( memcpy(static_cast<VOID*>(abc), static_cast<const VOID*>( dafa), static_cast<uint8>(NUMBER_SIZE)));
static_cast<void >(memcpy(
        static_cast<void *>(p),
        &abc, static_cast<uint8>(DATE_SIZE)));

它不是完美的100%,但我尝试与许多源文件,它看起来不错,它可以匹配高达99%:))

hsvhsicv

hsvhsicv3#

可靠地匹配旧式类型转换对于正则表达式来说是不可能的,因为你不能确定什么是类型,什么不是。作为证明,考虑下面这个C++文件:

#include "somefile.h"

void f(sometype_t x) {
    g((something)*x);
    h((somethingelse)(x));
}

如果something是一个类型,那么它所在的行是一个类型转换,但如果它是一个变量,那么它就不是。同样,如果somethingelse是一个类型,那么它所在的行是一个类型转换,但如果它是一个函数,那么它就不是。https://en.wikipedia.org/wiki/Lexer_hack
要真正强调这一点,请考虑另一个C++文件:

void g(long);
void h(char *);

template<int N>
struct SomeStruct {
    typedef int *sometype_t;
    typedef short something;
    typedef char *somethingelse;
};

template<>
struct SomeStruct<42> {
    typedef int sometype_t;
    short something;
    char *somethingelse(sometype_t);
};

constexpr int a = 12300 + 45;
constexpr int b = 40 + 2;

struct Child1 : SomeStruct<a> {
    void f(sometype_t x) {
        g((something)*x);
        h((somethingelse)(x));
    }
};

struct Child2 : SomeStruct<b> {
    void f(sometype_t x) {
        g((something)*x);
        h((somethingelse)(x));
    }
};

现在应该很清楚,知道这些东西是否是强制转换的唯一方法是首先计算任意的constexpr表达式which are Turing-complete

相关问题