简体   繁体   English

在三元字符串中处理一元非运算符的调车码算法

[英]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.具体来说,字符串中只有三个操作数 T、F、U 和三个运算符 AND、NOT、OR 和括号。 Not has higher precedence than AND, OR and AND OR have same precedence. Not 的优先级高于 AND,OR 和 AND OR 具有相同的优先级。 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).弹出堆栈的各种循环之间的相似性应该建议简化,这通常在运算符优先级解析器中实现(Shunting Yard 就是一个例子)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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