ApprenticeHacker
ApprenticeHacker

Reputation: 22011

What am I doing wrong with this Arithmetic Parser?

Here is the code for a simple arithmetic expression parser I wrote:

class ArithmeticExpressionParser<T> : Parser<T> where T : IConvertible
{
    dynamic num1, num2;
    public override T Parse(string expr)
    {
        base.Parse(expr);
        ParseExpression();
        return num1;
    }

    T ParseExpression()
    {
        if(PeekNextToken())
            num1 = ParseFactorial();

        if (Token == '+')
        {
            GetNextToken();
            num2 = ParseExpression();
            num1 += num2;
        }

        else if (Token == '-')
        {
            GetNextToken();
            num2 = ParseExpression();

            num1 -= num2;
        }

        return num1;
    }

    T ParseFactorial()
    {
        if(PeekNextToken())
            num1 = ParseNumber();

        if (Token == '*')
        {
            GetNextToken();
            num2 = ParseFactorial();

            num1 *= num2;
        }

        else if (Token == '/')
        {
            GetNextToken();
            num2 = ParseFactorial();

            num1 /= num2;
        }

        else if (Token == '%')
        {
            GetNextToken();
            num2 = ParseFactorial();

            num1 %= num2;
        }

        return num1;
    }


    T ParseNumber()
    {
        string temp = String.Empty;

        while (char.IsDigit(Token))
        {
            temp += Token;
            GetNextToken();
        }

        return (T)Convert.ChangeType(temp, typeof(T));           
    }
}

If info is needed about the entire Parser class, just comment and I'll post it. For now, here are the things I think are relevant:

    protected char GetNextToken()
    {
        do
        {
            if(Count++ >= expression.Length-1) break;

        } while (char.IsWhiteSpace(expression[Count]));

        return expression[Count];
    }

    protected bool PeekNextToken()
    {
        if (Count + 1 < expression.Length)
            return true;
        else
            return false;
    }

    string expression;

    protected char Token
    {
        get
        {
            return expression[Count];
        }
    }

    int count;
    protected int Count
    {
        get { return count;  }
        set
        {
            if (value < expression.Length)
                count = value;
        }
    }

Now the Problem is, it doesn't give correct results.

...a lot of weird results.

Also, please suggest improvements, and better ways to achieve the same thing.

Note: I am trying to write a simple arithmetic Recursive Descent Parser

Upvotes: 1

Views: 106

Answers (1)

Deepak
Deepak

Reputation: 1141

I do not have the solution, but looking at the code - 'ParseExpression' and 'ParseFactorial' operate and return num1, which is member accesed by all. Taking your last example 2+2-2, the first of the operation which happens is 2-2 = 0, and this overwrites the the firsr read value into num1 which is equal to 2. And hence the num1 = 0 before you can complete the addition operation and hence you get 0.

I checked that this logic gives out the resultant output provided for 3 examples.

I did find one more bug, your code never reads the last character if there is no space or a delimiter.

Upvotes: 2

Related Questions