-1

I need to parse math formula with condition at run time in C#. For example

string code = "1+ 1 + 1*1 * ((5+4==8)?2:0 )";
int value = int.parse(code);  // value should be 2

I was able to parse math formula without any ternary operator. Im having problem with the ternary operator: string code = "1+ 1 + 1*1 * ((5+4==8)?2:0 )";

Any help would be appreciated

  • IMHO it would help if you showed what you are currently using to parse the string eg. RegEx, simple split and for loop, a library, a lexar or what not, so we can give a for your case ideal solution - just showing `int.Parse(code)` isn't good enough – Rand Random Mar 01 '21 at 09:00
  • I real recommend starting with [ask], and [mre]. As there is no usefull code in your question. nor any constructive element. I will also recommend reading https://medium.com/@toptensoftware/writing-a-simple-math-expression-engine-in-c-d414de18d4ce that explain how a basic math parser work. – Drag and Drop Mar 01 '21 at 09:00
  • @TimSchmelter - DataTable.Compute doesn't seem to support the ternary operator - https://dotnetfiddle.net/xLdpVz – Rand Random Mar 01 '21 at 09:04
  • `DataTable.Compute` only know the following operator: AND, OR, NOT, <, >, <=, >=, <>, =, IN, LIKE. And rewriting the expression seems out of scope. If it's about Compute math expression we should have at least 2 duplicate. One big bucket of link to external/built in tool from Excel to ncalc. And one about token with the algorythm tag – Drag and Drop Mar 01 '21 at 09:07
  • https://stackoverflow.com/questions/2859111/c-sharp-math-calculator, , https://stackoverflow.com/questions/234217/is-it-possible-to-compile-and-execute-new-code-at-runtime-in-net , https://stackoverflow.com/questions/2607798/converting-string-expression-to-integer-value-using-c-sharp , https://stackoverflow.com/questions/1437964/best-and-shortest-way-to-evaluate-mathematical-expressions , https://stackoverflow.com/questions/333737/evaluating-string-342-yield-int-18 , https://stackoverflow.com/questions/3972854/parse-math-expression – Drag and Drop Mar 01 '21 at 09:10
  • You don't need a [so] answer, you need a whole compiler – Charlieface Mar 01 '21 at 09:36
  • @Charlieface - yeah no, just imagine this as an homework and you go tell the teacher "Sorry, can't be done, because what if someone wrote this or that, I would need a whole compiler for this homework.", sorry but that misses the whole point of the homework, no teacher would expect a simple calculator to work with every possible input and it being 100% fail proof, it is just a common homework to learn about basics, how to split a string, how to parse characters, how to write if/switch, how to do "simple" math and so on, and not how to write the most robust code human eye has ever seen – Rand Random Mar 01 '21 at 10:01
  • (cont) so as I stated previously it would be better to know how OP is already parsing the string, to give OP the simplest way to solve this problem with ternary operator even if it will only work for simple cases - chances are high that OP doesn't need to parse nesting tenary operators, method calls, anything different than comparing integer values, and everything c# compiler would have to offer – Rand Random Mar 01 '21 at 10:02
  • Does this answer your question? [Is there a string math evaluator in .NET?](https://stackoverflow.com/questions/355062/is-there-a-string-math-evaluator-in-net) – JonasH Mar 01 '21 at 10:58
  • https://idownvotedbecau.se/beingunresponsive – Rand Random Mar 01 '21 at 13:18
  • @RandRandom Precisely my point: OP already has some sort of compiler/parser which we know nothing about. If OP said: "My parser already does abc things, I don't care about xyz things" then maybe we could help, but the question as it stands is far too broad – Charlieface Mar 01 '21 at 13:49

1 Answers1

-1

@Rand Random, @Charlieface

First of all, if you come across a question in a language you don't know, I recommend you to skip it. Do not create invalid claims!

int.parse(); is used to convert a string integer to an integer value.

But clearly in this case this line =>

int value = int.parse(code);  // value should be 2

case's an error, (because code is not an integer)

And to do what I was asking u don't need a compiler. I actually did it without it!!

    using static System.Math;
    using Project = System.IO;
    using System.Linq;
    using System.Collections.Generic;
    using System.Text.RegularExpressions; 
    class YesICanWithoutACompiler
                {
                    static void Main(string[] args)
                    {
        
                        string code = "1+ 1 + 1*1 * (((((((3!=63))?(2==4?5:1):7))==8)?2:(4==6?7:3) ))";
        
                        string formula = getFormular(code);   // outputs: 1+ 1 + 1*1 * (3)
        
                        Console.WriteLine("yes I can!: " + new System.Data.DataTable().Compute(formula, ""));
                        Console.ReadLine();
        
                    }
                    static int IndexOfAny(string source, string[] items, int startat = 0)
                    {
                        List<int> indexes = new List<int>();
                        for (int f = 0; f < items.Length; f++)
                        {
                            int loo = source.IndexOf(items[f], startat);
                            if (loo != -1)
                            {
                                indexes.Add(loo);
                            }
                        }
        
                        if (indexes.Count > 0)
                        {
                            return indexes.Min();
                        }
                        else
                        {
                            return -1;
                        }
        
        
                    }
        
        
                    static bool conditoin(int x, string mark, int y)
                    {
                        switch (mark)
                        {
                            case "!=":
                                return (x != y);
                            case "==": return (x == y);
                            case ">=": return (x >= y);
                            case "<=": return (x <= y);
                            default: return false;
                        }
        
                    }
        
                    static string getFormular(string code)
                    {
                        int ind = IndexOfAny(code, new string[] { "==", ">=", "<=", "!=" });
        
                        while (ind != -1)
                        {
        
        
        
                            int condition1 = int.Parse(string.Join("", code.Substring(0, ind).Reverse().SkipWhile(c => !char.IsDigit(c)).TakeWhile(d => char.IsDigit(d))));
                            string conditioin = code.Substring(ind, 2);
        
                            int condition2 = int.Parse(string.Join("", code.Substring(ind + 2).TakeWhile(d => char.IsDigit(d))));
        
        
                            string arvo = "";
                            if (conditoin(condition1, conditioin, condition2))
                            {
                                arvo = code.Substring(1 + code.IndexOf("?", ind + 2)).Trim();
        
                                if (arvo.StartsWith("("))
                                {
        
        
                                    int ndent = 1;
                                    int h = 0;
                                    while (h < arvo.Length && ndent != 0)
                                    {
                                        h++;
        
        
                                        if (arvo[h] == ')') ndent--;
                                        if (arvo[h] == '(') ndent++;
                                    }
        
                                    arvo = arvo.Substring(0, h + 1);
        
        
                                }
                                else
                                {
                                    arvo = string.Join("", arvo.TakeWhile(s => s != ':'));
        
                                }
        
        
        
                            }
                            else
                            {
        
                                arvo = code.Substring(1 + code.IndexOf(":", ind + 2)).Trim();
        
                                if (arvo.StartsWith("("))
                                {
        
        
                                    int ndent = 1;
                                    int h = 0;
                                    while (h < arvo.Length && ndent != 0)
                                    {
                                        h++;
        
        
                                        if (arvo[h] == ')') ndent--;
                                        if (arvo[h] == '(') ndent++;
                                    }
        
                                    arvo = arvo.Substring(0, h + 1);
        
                                }
                                else
                                {
                                    arvo = string.Join("", arvo.TakeWhile(s => s != ')'));
        
                                }
        
        
        
        
        
        
        
        
                            }
        
                            int f = code.IndexOf("?", ind);
                            int indent = 0;
                            while (f > 0 && indent != -1)
                            {
                                f--;
                                if (code[f] == ')') indent++;
                                if (code[f] == '(') indent--;
                            }
        
                            int t = f;
                            indent = 1;
        
                            while (t < code.Length && indent != 0)
                            {
                                t++;
                                if (code[t] == ')') indent--;
                                if (code[t] == '(') indent++;
                            }
        
                            code = code.Remove(f, (t - f) + 1).Insert(f, arvo);
        
                            ind = IndexOfAny(code, new string[] { "==", ">=", "<=", "!=" });
        
                        }
                        return code;
                    }

 }