Reputation: 249
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:
upper
or lower
, upper
or lower
, a hyphen, a random number of random characters and a hyphenBut 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
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