Правый ассоциативный оператор в анализаторе математических выражений

Наконец, исходя из этот вопрос, остается проблема, что этот субпарсер...

private static void Factor(Scanner scanner, ref TermNode currentTree, ref Token currentToken)
{
    Exponent(scanner, ref currentTree, ref currentToken);

    while (currentToken is OperatorToken && ((OperatorToken)currentToken).OperatorChar == '^') // So long as the token is ^
    {
        TermNode node = new TermNode(currentTree, null, currentToken);
        currentTree = null;
        scanner.MoveNext();
        currentToken = scanner.Current;
        Exponent(scanner, ref currentTree, ref currentToken);
        node.RightChild = currentTree;
        currentTree = node;
    }
}

... неправильно обрабатывает экспоненциальный оператор ("^"). Это связано с тем, что оно правоассоциативное. Приведенный выше код обрабатывает его так, как если бы он был оставлен ассоциативным.

Например: Текст e^x^2 интерпретируется как (e^x)^2. Однако правильной «интерпретацией» будет e^(x^2).

Я уже пробовал что-то вроде этого:

if (/* The current token is ^ */)
{
    TermNode node = new TermNode(tree, null, currentToken);
    tree = null;
    scanner.MoveNext();
    currentToken = scanner.Current;
    Exponent(ref tree);
    node.RightChild = tree;
    tree = node;
}
while (/* The current token is ^  */)
{
    TermNode detachedExponent = tree.RightChild;
    TermNode oldTree = tree;
    Token token = currentToken;
    tree.RightChild = null;
    tree = null;
    scanner.MoveNext();
    currentToken = scanner.Current;
    Exponent(ref tree);
    oldTree.RightChild = new TermNode(distachedExponent, tree, token);
    tree = oldTree;
}

Что работает только для двух последовательных "^"-выражений. Не что-то вроде e^x^y^z (что было бы e^(x^(y^z)), а не e^((x^y)^z), как утверждает синтаксический анализатор... Что я упускаю?


person HerpDerpington    schedule 27.07.2015    source источник
comment
Какой у Вас вопрос?   -  person xxbbcc    schedule 27.07.2015
comment
Я предполагаю, как я могу заставить этот синтаксический анализатор правильно обрабатывать правоассоциативные операторы, такие как ^?.   -  person Jerry Federspiel    schedule 27.07.2015
comment
@JerryFederspiel Да, да, это так.   -  person HerpDerpington    schedule 27.07.2015
comment
Это просто. Сначала напишите BNF, который вы хотите принять. Затем закодируйте парсер рекурсивного спуска так, как я предложил. если оператор является правоассоциативным, грамматика будет указывать его таким образом, и ваш синтаксический анализатор будет работать соответствующим образом. Я показал вам, как в вашем предыдущем вопросе; Я оставляю это на ваше усмотрение.   -  person Ira Baxter    schedule 27.07.2015


Ответы (1)


Когда у вас есть a^b и вы видите ^c, вы вводите его в правую часть верхнего уровня ^, создавая a^(b^c), и оставляете себе результирующее полное выражение. Когда вы увидите ^d, вы снова вставите его в правую часть верхнего уровня ^, создав a^((b^c)^d). Вы должны вводить его не в RHS верхнего уровня ^, а в правое/самое внутреннее выражение ^. Для этого просто отслеживайте это выражение в отдельной переменной. Затем вместо изменения свойства RightChild выражения верхнего уровня измените свойство дочернего элемента.

person Community    schedule 27.07.2015