【问题标题】:Why does my shunting yard implementation mix operator order?为什么我的调车场实施混合运营商订单?
【发布时间】:2022-01-21 17:02:09
【问题描述】:

我一直在尝试实现the shunting yard algorithm,但是我的解析器的输出不正确。

let mut stack: Vec<String> = vec![];
let mut op_stack: Vec<String> = vec![];

for current in sub_tree {
    if current.tok_type == TokenType::NUMBER || current.tok_type == TokenType::NEGNUMBER {
        self.parse();
        stack.push(current.content.clone());
    }
    if current.tok_type == TokenType::SUBBIN
        || current.tok_type == TokenType::PLUSBIN
        || current.tok_type == TokenType::DIVBIN
        || current.tok_type == TokenType::MULBIN
    {
        while op_stack.len() > 0 && op_stack.last().unwrap().to_string() != "(" {
            if op_prec(&op_stack.last().unwrap().to_string()) > op_prec(&current.content)
                || (op_prec(&op_stack.last().unwrap().to_string()) == op_prec(&current.content)
                    && op_asso(&current.content) == "left")
            {
                stack.push(op_stack.pop().unwrap().to_string());
            } else {
                break;
            }
        }
        op_stack.push(current.content.to_string())
    }
}

我正在解析的原始方程:1 + 2 * 3

我希望得到以下输出:1 2 3 * +

相反,我得到了这个:1 2 3 + *

我认为我在 while 循环中的某个地方出错了,但我真的不知道。我尝试按照维基百科文章中的示例进行操作。

【问题讨论】:

  • 预期输出应该是123*+ 而不是12*3+?另外,我们需要知道op_stack的内容在最后一个令牌3被推送到stack之后是如何处理的。
  • @Joe_Jingyu 你说得对,预期的输出是123*+。之后我对op stack 所做的唯一事情是将op_stack 的其余部分合并回stack
  • 要将op_stack的剩余部分合并回栈中,是否按照栈后进先出的方式合并,也就是说先合并*,再合并+ 为这个案子?
  • @Joe_Jingyu 我应该怎么做?我只是将整个 op_stack 连接到堆栈向量的末尾。

标签: parsing rust postfix-notation shunting-yard


【解决方案1】:

比较你的代码

   if current.tok_type == TokenType::SUBBIN
        || current.tok_type == TokenType::PLUSBIN
        || current.tok_type == TokenType::DIVBIN
        || current.tok_type == TokenType::MULBIN
    {
        while op_stack.len() > 0 && op_stack.last().unwrap().to_string() != "(" {
            if op_prec(&op_stack.last().unwrap().to_string()) > op_prec(&current.content)
                || (op_prec(&op_stack.last().unwrap().to_string()) == op_prec(&current.content)
                    && op_asso(&current.content) == "left")
            {
                stack.push(op_stack.pop().unwrap().to_string());
            } else {
                break;
            }
        }
        op_stack.push(current.content.to_string())
    }

使用维基百科代码https://en.wikipedia.org/wiki/Shunting-yard_algorithm

- an operator o1:
    while (
        there is an operator o2 other than the left parenthesis at the top
        of the operator stack, and (o2 has greater precedence than o1
        or they have the same precedence and o1 is left-associative)
    ):
        pop o2 from the operator stack into the output queue
    push o1 onto the operator stack

看起来它们在功能上是相同的。

所以我怀疑问题不在于代码,而在于优先级表。如果你有 + 和 * 的优先顺序错误,那么你会得到这种行为。这很容易混淆,因为某些来源具有从更紧密绑定到失败者的优先权,而有些则相反。比较Wikipedia order of operationsOperator Precedence in Java,使用前者。

【讨论】:

    猜你喜欢
    • 2022-04-02
    • 1970-01-01
    • 2015-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多