code: def _expression(expression):
      # type: (QuilParser.ExpressionContext) -> Any
      
      if isinstance(expression, QuilParser.ParenthesisExpContext):
          return _expression(expression.expression())
      elif isinstance(expression, QuilParser.PowerExpContext):
          if expression.POWER():
              return _binary_exp(expression, operator.pow)
      elif isinstance(expression, QuilParser.MulDivExpContext):
          if expression.TIMES():
              return _binary_exp(expression, operator.mul)
          elif expression.DIVIDE():
              return _binary_exp(expression, operator.truediv)
      elif isinstance(expression, QuilParser.AddSubExpContext):
          if expression.PLUS():
              return _binary_exp(expression, operator.add)
          elif expression.MINUS():
              return _binary_exp(expression, operator.sub)
      elif isinstance(expression, QuilParser.SignedExpContext):
          if expression.sign().PLUS():
              return _expression(expression.expression())
          elif expression.sign().MINUS():
              return -1 * _expression(expression.expression())
      elif isinstance(expression, QuilParser.FunctionExpContext):
          return _apply_function(expression.function(), _expression(expression.expression()))
      elif isinstance(expression, QuilParser.AddrExpContext):
          return _addr(expression.addr())
      elif isinstance(expression, QuilParser.NumberExpContext):
          return _number(expression.number())
      elif isinstance(expression, QuilParser.VariableExpContext):
          return _variable(expression.variable())
  
      raise RuntimeError("Unexpected expression type:" + expression.getText())
docs: NB: Order of operations is already dealt with by the grammar. Here we can simply match on the type.