仓库源文

之前 模拟生态时 碰到个 python转换木兰的问题,因为影响运算结果且常碰到,打算将其修正。

先用原始木兰可执行文件,对 a=2*(1+3) -p 转为python 以及 -s 转为木兰,括号都未保留,变为 a=2*1+3,看来此问题一直都在。

木兰/功用/py语法树.pya=2*(1+3) 的语法树输出,如下:

Module(
  body=[Assign(
      targets=[Name(
          id='a'
          ctx=Store()
          lineno=1
          col_offset=0
        )]
      value=BinOp(
        left=Num(
          n=2
          lineno=1
          col_offset=2
        )
        op=Mult()
        right=BinOp(
          left=Num(
            n=1
            lineno=1
            col_offset=5
          )
          op=Add()
          right=Num(
            n=3
            lineno=1
            col_offset=7
          )
          lineno=1
          col_offset=5
        )
        lineno=1
        col_offset=2
      )
      lineno=1
      col_offset=0
    )]
)

用原始的 ulang -a 以及重现版的 木兰 -树 输出语法树相同,看来解析为语法树这步无误,应该是生成的问题。

语法树里是 BinOp,于是找到 visit_BinOp,对照 visit_BoolOp 一样首尾加上括号:

    def visit_BinOp(self, 节点):
        self.编写('(')
        self.visit(节点.left)
        self.编写(' %s ' % 二元操作符[type(节点.op)])
        self.visit(节点.right)
        self.编写(')')

测试发现会加很多不必要的括号如:数列[(位置 + 1)],于是判断一下左右节点类型:

    def visit_BinOp(self, 节点):

        if isinstance(节点.left, BinOp):
            self.编写('(')
            self.visit(节点.left)
            self.编写(')')
        else:
            self.visit(节点.left)
        self.编写(' %s ' % 二元操作符[type(节点.op)])
        if isinstance(节点.right, BinOp):
            self.编写('(')
            self.visit(节点.right)
            self.编写(')')
        else:
            self.visit(节点.right)

上面的情况是不加括号了,不过还是有些比如:2 + 3 - 4 * 5 => (2 + 3) - (4 * 5)

之后可以根据优先级判断是否需要,但至少结果无误了,在之前的生态例程测试也通过。

先到这里。详见 此提交