#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define MAX 1000

void init();
void push(int); //スタックの先頭（頂点）に要素 x を追加します
int pop(); //スタックの先頭（頂点）から要素を取り出します
int isEmpty(); //スタックが空かどうかを調べます
int isFull(); //スタックが満杯かどうかを調べます

int top, S[MAX];

/*initialize 関数は top を 0 とすることでスタックを空にします。
このとき配列（メモリ）の中に要素は残ったままですが、
以降の push 操作によって上書きされます。isEmpty 関数は top が 0 かどうかを
調べスタックが空かどうかを判定します。*/
void init(){
  top = 0;
}

/*push 関数では top を1 つ増やし、その場所に x を追加します。
ただし、スタックが満杯の場合はなんらかのエラー処理を行います。*/
void push(x){
  if(isFull() == 1){
    fprintf(stderr,"erorr!\n");
    exit(8);
  }
  else {
    S[++top] = x;
  }
}

/*pop 関数では、top が指す要素、つまりスタックの頂点の要素を返しつつ、
top の値を１つ減らすことで、頂点の要素を削除します。
ただし、スタックが空の場合はなんらかのエラー処理を行います。*/
int pop(){
  if(isEmpty() == 0){
    fprintf(stderr,"error!\n");
    exit(8);
  }
  top--;
  return S[top+1];
}

int isEmpty(){
  if(top == 0) return 0;
  else return 1;
}

/*isFull 関数はスタックが満杯かどうかを判定します。
例えば、配列が 0 オリジンで容量が MAX で定義されている場合は、
top が MAX-1 以上のときにスタックが満杯の状態になります。*/
int isFull(){
  if(top >= MAX-1) return 1;
  else return 0;
}


int main(){
  int x, y;
  top = 0;
  char s[100];

  while(scanf("%s",s) != EOF){
    if(s[0] == '+'){
      x = pop();
      y = pop();
      push(x + y);
    }
    else if(s[0] == '-'){
      y = pop();
      x = pop();
      push(x - y);
    }
    else if(s[0] == '*'){
      x = pop();
      y = pop();
      push(x * y);
    }
    else push(atoi(s));
  }
  printf("%d\n",pop());

  return 0;
}

