简体   繁体   中英

Shunting yard algorithm with handling unary NOT operator in Ternary string

I am currently writing a Infix to Prefix transfer of a Ternary logic string. In specific, there are only three operands T,F,U and three operators AND, NOT, OR and brackets in the string. Not has higher precedence than AND, OR and AND OR have same precedence. Here's my code changing from original shunting yard algorithm but the translation is not correct for some input

string Infix_To_Prefix(string expression){
    string prefix_expression = "";
    stack<char> char_stack;
    unordered_map<char,int> Precendence;
    Precendence['~'] = 2;
    Precendence['|'] = 1;
    Precendence['&'] = 1;

    for(int i=0;i<expression.size();i++)
    {
        char token = expression[i];
        if(isOperator(token))
        {
            while(!char_stack.empty() and isOperator(char_stack.top()))
            {
                if(Precendence[token] < Precendence[char_stack.top()])
                {
                    prefix_expression+=char_stack.top();
                    char_stack.pop();
                    continue;
                }
                break;
            }
            char_stack.push(token);
        }

        else if(token == '(')
        {
            char_stack.push(token);
        }
        else if(token == ')')
        {
            while(!char_stack.empty() and char_stack.top() != '(')
            {
                prefix_expression+=char_stack.top();
                char_stack.pop();
            }
            char_stack.pop();
        }
        else if(isOperand(token))
        {
            prefix_expression+=token;
        }

    }
    while(!char_stack.empty())
    {
        prefix_expression+=char_stack.top();;
        char_stack.pop();
    }
    return prefix_expression;
}

In your code, you check the precedence:

if(Precendence[token] < Precendence[char_stack.top()])
{
    prefix_expression+=char_stack.top();
    char_stack.pop();
    continue;
}

In the program you cited in a comment, which is certainly not the original Shunting Yard implementation, the code is

if ((isAssociative(token, LEFT_ASSOC) && 
        cmpPrecedence(token, stack.peek()) <= 0) || 
    (isAssociative(token, RIGHT_ASSOC) && 
        cmpPrecedence(token, stack.peek()) < 0)) 
{
    out.add(stack.pop());   
    continue;
}

So your test is the same as what the provided code does in the case of right-associative operators, and that is what your code does. If you want your operators to be left-associative, you would need to change the < to <= , as in the code you are adapting.

However, that won't work in the case of unary operators, because unary operators need to be right-associative, at least in the simplistic view normally shown in implementations of the shunting yard algorithm.

It would be more accurate to say that a unary operator should always be pushed onto the stack regardless of the precedence of the operator which precedes it; since it does not take a right-hand operator, it is not competing with the preceding operator, only with the following one. So a unary operator as an incoming token must have higher precedence than any operator on the stack, although a unary operator on the stack may or may not have higher precedence than incoming operator tokens. If the unary operator is the highest-precedence operator, then making it right-associative will have that effect. So I think it is cleaner to special-case unary operators, as you already do with parentheses:

for (char token: expression)  {
  if (token == '(' || token == '~')
    char_stack.push(token);
  else if (isOperator(token)) {
    while (!char_stack.empty()
           and isOperator(char_stack.top())
           and Precendence[token] < Precendence[char_stack.top()]) {
        prefix_expression+=char_stack.top();
        char_stack.pop();
    }
    char_stack.push(token);
  }
  else if(token == ')') {
    while(!char_stack.empty() and char_stack.top() != '(') {
      prefix_expression+=char_stack.top();
      char_stack.pop();
    }
    char_stack.pop();
  }
  else if(isOperand(token))
    prefix_expression+=token;
}

The similarity between the various loops which pop the stacks should suggest a simplification, which is usually implemented in operator-precedence parsers (of which the Shunting Yard is an example).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM