Question Parsing a string in reverse for computing commands

OgreVorbis

Member
Joined
Mar 24, 2023
Messages
5
Location
New England
Programming Experience
5-10
I'm sick right now and my head is a little foggy. I'm trying to parse a string containing mathematical "commands" for a calculator. I already have a parser to do simple math operations, but now I want to add stuff like sqrt{}, sin{}, cos{}, etc.
So what I am trying to accomplish with this code is to parse the single line string, calculate all the answers for each of the commands and replace that part of the string with the answer. That way I can then send the resulting string into the old parser that can handle the basics.

I believe I could use abstract syntax tree, or stack, or something, BUT I'd rather keep it simple. I discovered that I should be able to get the desired result by simply searching the string backwards (from the end), executing every command with its param (they only have one for now), and then replacing that part of the calculation string with the answer (plus overwriting the command itself).

If you think I should do it a different way, please let me know!

This code doesn't work, but it should show you what I'm trying to do:
C#:
using System;
using System.Collections.Generic;
using System.Linq;
                    
public class Program
{
    public struct token
    {
        public int cmdNumber;
        public int startPos;
        public int realStartPos;
        public int length;
    }
    
    public static string ParseExpression(string exp)
    {
        string modifiedExp = exp;
        List<token> theCmds = new List<token>();
        string[] commands = new string[] {"sqrt{", "sin{", "cos{", "date{"};
        int l1 = -1, l2 = exp.Length;
        int i = 0;
        token happy;
        
        foreach (string cmd in commands)
        {
            happy = new token();
            l1 = exp.LastIndexOf(cmd, l2);
            if (l1 != -1)
            {
                l2 = l1;
                happy.cmdNumber = i;
                happy.startPos = l1 + cmd.Length;
                happy.realStartPos = l1;
                happy.length = exp.IndexOf("}", l1) - happy.startPos;
            }
            theCmds.Add(happy);
            i++;
        }
        
        foreach (token t in theCmds)
        {
            string result = "";
            string toEvaluate = exp.Substring(t.startPos, t.length);
            
            //if (toEvaluate == "")
            //    continue;
            switch (t.cmdNumber)
            {
                case 0:
                    // evaluate the expression here
                    // stores in string result
                    result = Math.Sqrt(Convert.ToDouble(toEvaluate)).ToString();
                    break;
                case 1:
                    // again, just a different command
                    break;
            }
            modifiedExp.Remove(t.realStartPos, t.length).Insert(t.realStartPos, result); //not sure if works/best way
            
            // it should replace all the commands with the results (return value) of each command
            // so now I'm left with a much simpler expression that can be parsed in a simple math parser
        }
        
        return modifiedExp;
    }
    
    public static void Main()
    {
        string expression = "sqrt{1024}*sqrt{sqrt{64}+64}";
        string firstParse = ParseExpression(expression);
        Console.WriteLine(firstParse);
        // SecondParser(firstParse);
    }
}
 
If you already have an infix to postfix converter (because you said that you already know how to evaluate an expression), then adding support for additional math functions should be no different from handling a unary operator. For example if you had:
C#:
4 + -5

Instead of making it into postfix of
C#:
4 -5 +
You should be making this into postfix of:
C#:
4 5 negate +

So similarly when you have:
C#:
10 * sin(45)
You would end up with a postfex of:
C#:
10 45 sine *
 
Back
Top Bottom