Lazlo
Lazlo

Reputation: 8790

What would the correct regex be for this replacement?

This is half a question and half a fun quiz, because the regex will be ridiculously complicated and hard to create.

If I was to do it myself (because I actually need to use it), I would write a file parser rather than a regex, although I know it's possible to use regex in this case, and I thought there was perhaps some StackOverflow coders who liked challenge.

As a "reward", I'll leave the question open for 7 days, at which point a bounty of 150 reputation will be attributed to the person with the correct answer. I'm aware that the answerer might probably have >3K of reputation, but rep is rep nonetheless, I presume. :)

The regex will have to turn:

[DllImport(EngineDll)]
public static extern int Graphics(int width, int height, int depth = default(int), int hertz = 60, int flags = (int)(GraphicsBufferType.Back | GraphicsBufferType.Depth));

Into:

public static int Graphics(int width, int height, int depth = default(int), int hertz = 60, int flags = (int)(GraphicsBufferType.Back | GraphicsBufferType.Depth))
{
    if (Engine.ThreadSafe)
    {
        lock (typeof(Dll))
        {
            return Dll.Graphics(width, height, depth, hertz, flags);
        }
    }
    else
    {
        return Dll.Graphics(width, height, depth, hertz, flags);
    }
}

Since multiline is not needed at all, you can have it all in 1 line if you find it easier to parse:

public static int Graphics(int width, int height, int depth = default(int), int hertz = 60, int flags = (int)(GraphicsBufferType.Back | GraphicsBufferType.Depth)) { if (Engine.ThreadSafe) { lock (typeof(Dll)) { return Dll.Graphics(width, height, depth, hertz, flags); } } else { return Dll.Graphics(width, height, depth, hertz, flags); } }

Now if it wasn't obvious enough, what is variable is the return type, the method name, the parameter types, the parameter names, whether the parameters have default values and in that case, the default values. The function may be a void, in which case there should be no return statement.

On request: Second input-output:

[DllImport(EngineDll)]
public static extern void EndRender();

Output:

public static void EndRender()
{
    if (Engine.ThreadSafe)
    {
        lock (typeof(Dll))
        {
            Dll.EndRender();
        }
    }
    else
    {
        Dll.EndRender();
    }
}

Again, 1-liners accepted.

Good luck! :)

Note to all who might say I'm just lazy: Change question.

Upvotes: 1

Views: 192

Answers (2)

Anon.
Anon.

Reputation: 60013

You can't quite do this with true regular expressions, because you need to be able to handle balanced parentheses in the default values. That said, there are regex dialects with extensions that allow you to handle this sort of thing, so let's get the ball rolling:

s/[DllImport(EngineDll)]\npublic\ static\ extern\ #boilerplate
  (?<method> #capturing group for the method signature
  (?<return>\w+)\ #Method return type
  (?<name>\w+)\( #Method name
  (?<parameter>\w+\ #parameter type
   (?<parname>\w+)\ #parameter name
   (=\ (?&DEFAULTVALUEREGEX))? #optional default value
   (?{$params = $+{parname}}) #Ok, so this isn't even pretending to be a regex 
                              # anymore. If anyone has any better ideas...
  )(?:,\ #parameter seperator
   \w+\ (?<par>\w+)\ (=\ (?&DEFAULTVALUEREGEX))?
   (?{ $params .= ", " . $+{par}}))* # more parameters
   \)); # boilerplate
  /
  public static $+{method} { if (Engine.ThreadSafe) { lock (typeof(Dll)) { return Dll.$+{name}($params); } } else { return Dll.$+{name}($params); }}
  /x

I haven't included the definition of the DEFAULTVALUEREGEX because that basically requires you to parse anything that's a valid C# expression, which would be large enough to obscure the rest of the logic. Also it uses the (?{code}) construct, making it exceptionally dubious whether this even counts as a sort-of regular expression. Also I haven't tested it at all because I'm lazy like that, and it's really brittle (it'll break on a bunch of stuff that's still valid C#).

If anyone has any improvements, feel free to edit them in - that's why it's CWiki in the first place.

Upvotes: 1

Jonathan Leffler
Jonathan Leffler

Reputation: 754590

So, what's wrong with this?

s/.*/public static int Graphics(int width, int height, int depth = default(int), int hertz = 60, int flags = (int)(GraphicsBufferType.Back | GraphicsBufferType.Depth)) { if (Engine.ThreadSafe) { lock (typeof(Dll)) { return Dll.Graphics(width, height, depth, hertz, flags); } } else { return Dll.Graphics(width, height, depth, hertz, flags); } }/;

Since it (probably) wasn't what you had in mind, there has to be another transformation that the same regex also has to do - otherwise what I provided is quite adequate for the job.

Upvotes: 0

Related Questions