Peter
Peter

Reputation: 249

regex for nested mark-up/functions

I am creating a program where I offer a few functions that can be entered by the user. Let's say I have a function to convert a string to upper-case with the function $upper(string) and a function $lower(string). The user can enter those in a text box while using placeholders to insert content (e.g. %T for the title of a song). Using both placeholders and functions, the user can enter a complete naming pattern.

Functions can be nested and I want to execute the inner-most function first. Now I am looking for a Regex to identify it. In english, I am looking for a function (and its value) that does not contain another function.

During my tests, I use hyphens instead of brackets and no $-sign. This is a lot easier to read. So the functions during testing are lower-sometext-.

This is my guess so far:

(lower|upper)-(?!((lower|upper)-.*-))-

I read it as follows:

But that won't even accept lower-sometext-. I am trying different things for more than 2 hours but I can't figure it out...

Upvotes: 2

Views: 88

Answers (1)

Jan
Jan

Reputation: 2168

Use a different approach: Instead of looking for the inner-most function first, start with the outermost function - and resolve its value recursively.

So for the string upper(lower(sometext)) you first "handle" the upper. But before you actually apply ToUpper() you call the same function on its value - in this case lower(sometext). Then you do the same thing again: apply ToLower() to the result of your execute function for the value - in this case only sometext. Since it does not contain a function, the execute method will return sometext and end the recursion.

I have created a function in C#

public string execute(string text)
{
    string pattern = @"(lower|upper)\((.*)\)";
    Match m = Regex.Match(text, pattern);
    if (m.Success)
    {
        switch (m.Groups[1].Value)
        {
            case "lower":
                return execute(m.Groups[2].Value).ToLower();
            case "upper":
                return execute(m.Groups[2].Value).ToUpper();
            default:
                return null;
        }
    }
    else
        return text;
}

And you can just call the function with your string:

string result = "upper(lower(sometext))";

Again: The important part is inside the switch: BEFORE you call ToLower() or ToUpper() you call the execute method for the value. The result of this function will ALWAYS be a literal and never contain a function. Also, it scales really well.

Upvotes: 1

Related Questions