I'm tasked to create an intrepreter for c#
basically I want to split this string:
"multiply (add 5 5) 5"
into an array of string:
["multiply", "(add 5 5)", "5"]
if I'm using string.Split based on delimiter of space: " ", the result will be:
["multiply", "(add", "5", "5)", "5"]
which is not what I'm expecting
Is this achievable in C#?
Edit: I also need to support nested expression:
"multiply (add (add 2 5) 5) 5"
For example above, needs to become:
["multiply", "(add (add 2 5) 5)", 5]
For the very basic use cases you have provided, you could achieve the 'interpretation' by looping through your source string, keeping track of which nested level you are currently in (if any), and using a StringBuilder
to build your interpreted parts character by character.
You could implement a method containing the following logic:
StringBuilder
object, which will hold the part of the source string you are currently interpretingStringBuilder
object, return it and clear the StringBuilder
object to prepare for the next part to be interpreted. Continue to the next character in the source string (i.e. skip the subsequent steps for the current character).'('
). If it is, it means that you are entering the next nested level. Update your nested level counter to reflect that.')'
). If it is, update your nested level counter to reflect that.StringBuilder
object.StringBuilder
object as a string. (Unless your source string ends with a space character, the StringBuilder
object will at this point contain the final interpreted part.)Here is a possible implementation:
private static IEnumerable<string> GetInterpretation(string source)
{
var delimiter = ' ';
var innerDelimiter = (Opening: '(', Closing: ')');
StringBuilder currentPart = new StringBuilder();
var innerLevel = 0;
Func<bool> isInnerPart = () => innerLevel > 0;
foreach (var ch in source)
{
if (ch == delimiter && !isInnerPart())
{
yield return currentPart.ToString();
currentPart.Clear();
continue;
}
if (ch == innerDelimiter.Opening)
{
innerLevel++;
}
else if (ch == innerDelimiter.Closing)
{
innerLevel--;
}
currentPart.Append(ch);
}
if (currentPart.Length > 0)
{
yield return currentPart.ToString();
}
}
If your input string variable is named source
, you can use the method as follows:
var interpretation = GetInterpretation(source).ToArray();
For the given inputs, the resulting output is:
var source = "multiply (add 5 5) 5";
multiply
(add 5 5)
5
var source = "multiply (add (add 2 5) 5) 5";
multiply
(add (add 2 5) 5)
5
Example fiddle here.
Note: As stated, this logic and implementation is naive and can be used for the described simple use case.
It assumes:
"ABC DEF (GHI) JKL MNO"
will be interpreted as "ABC", "DEF", "(GHI)", "JKL", "MNO"
( )
) that are on the top 'nesting level' are always preceded and succeeded by a space"ABC DEF(GHI)JKL MNO"
will hence be interpreted as "ABC", "DEF(GHI)JKL", "MNO"