Что я делаю не так с этим арифметическим парсером? - PullRequest
1 голос
/ 04 января 2012

Вот код для простого анализатора арифметических выражений, который я написал:

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));           
    }
}

Если нужна информация обо всем классе Parser, просто прокомментируйте, и я опубликую его. На данный момент вот вещи, которые я считаю актуальными:

    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;
        }
    }

Теперь проблема в том, что она не дает правильных результатов.

  • 2 + 2 * 2 возврат 8
  • 2 + 2 + 2 + 2 возврат 16
  • 2 + 2-2 возврат 0

... много странных результатов.

Также, пожалуйста, предложите улучшения и лучшие способы добиться того же.

Примечание: я пытаюсь написать простую арифметику Парсер рекурсивного спуска

1 Ответ

2 голосов
/ 04 января 2012

У меня нет решения, но, глядя на код - «ParseExpression» и «ParseFactorial» работают и возвращают num1, который является членом, доступным всем.Если взять последний пример 2 + 2-2, первая из выполняемых операций - 2-2 = 0, и это перезаписывает значение чтения firsr в num1, равное 2. И, следовательно, num1 = 0, прежде чем вы сможете завершитьоперация сложения и, следовательно, вы получаете 0.

Я проверил, что эта логика выдает результирующий вывод, предоставленный для 3 примеров.

Я нашел еще одну ошибку, ваш код никогда не читает последний символесли нет пробела или разделителя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...