#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>

struct struc1{
char elem;
struct struc1 *next; };
struct struc1 *st = NULL;

struct struc2{
char *elem;
int id;
struct struc2 *next; };
struct struc2 *li = NULL;

struct struc3{
double elem;
struct struc3 *next; };
struct struc3 *stack = NULL;


void push_to_line(char *p, int b){
struct struc2 *k;
k=li;
if (k==NULL){
k=(struct struc2*)malloc(sizeof(struct struc2));
k->next=NULL;
k->elem=(char*)malloc(sizeof(char)*(strlen(p)+1));
strcpy(k->elem, p);
k->id=b;
li=k;       }
else{
while (k->next!=NULL) k=k->next;
k->next=(struct struc2*)malloc(sizeof(struct struc2));
k->next->next=NULL;
k->next->elem=(char*)malloc(sizeof(char)*(strlen(p)+1));
k->next->id=b;
strcpy(k->next->elem, p);
    }                            }

void push_to_char_stack(char p){
struct struc1 *k;
k=(struct struc1*)malloc(sizeof(struct struc1));
k->next=st;
k->elem=p;
st=k;                          }

void push_to_double_stack(double a){
struct struc3 *k;
k=(struct struc3*)malloc(sizeof(struct struc3));
k->next=stack;
k->elem=a;
stack=k;                           }

double pop_from_double_stack(){
struct struc3* k;
double a;
k=stack;
if (k!=NULL) {
a=k->elem;
stack=stack->next;
free(k);     }   return a;    }

char pop_from_char_stack(){
struct struc1 *k;
char p;
k=st;
p=0;
if (k!=NULL) {
p=k->elem;
st=st->next;
free(k);     }  return p; }


int create_POLIZ(char *s){//---------------------------------------------------------------------------------------------------
int i=0, j, k=0;
char *p, *ptr, c, *t;
  
  void temp_push (void) {
if (c=='s') push_to_line(p,2);
if (c=='c') push_to_line(p,2);
if (c=='l') push_to_line(p,2);
if (c=='e') push_to_line(p,2);
if (c=='^') push_to_line(p,2);
if (c=='&') push_to_line(p,2);
if (c=='+') push_to_line(p,3);
if (c=='-') push_to_line(p,3);
if (c=='*') push_to_line(p,3);
if (c=='/') push_to_line(p,3);
}
  
while (i<strlen(s)) {
if (s[i]=='(') k++;
if (s[i]==')') k--;
if (k<0) return 0;
i++;                }
if (k!=0) return 0;
i=0;
while ((s[i]!='\0') && (s[i]!='\n')) {
if ((('A'<=s[i]) && (s[i]<='Z')) || (s[i]>='a') && (s[i]<='z') || (s[i]=='_')) {
j=i;
while (((s[i]>='A') && (s[i]<='Z')) || ((s[i]>='a') && (s[i]<='z')) || ((s[i]>='0') && (s[i]<='9')) || (s[i]=='_')) i++;
i--;
ptr=s+j;
p=(char*)malloc(sizeof(char)*(i-j+2));
p[0]='\0';
strncat(p, ptr, i-j+1);
if (strcmp(p,"sin") && strcmp(p,"cos") && strcmp(p,"ln") && strcmp(p,"exp")) {
push_to_line(p,1);
if ((s[i+1]!=')') && (s[i+1]!='+') && (s[i+1]!='-') && (s[i+1]!='*') && (s[i+1]!='/') && (s[i+1]!='\0') && (s[i+1]!='\n')) return 0;
}
else {
  while (st && ((st->elem=='s') || (st->elem=='c') || (st->elem=='l') || (st->elem=='e') || (st->elem=='^') || (st->elem=='&'))) {
 c=pop_from_char_stack();
 t=(char*)malloc(sizeof(char)*3);
 if (c=='s') strcpy(t,"sin"); if (c=='c') strcpy(t,"cos");
 if (c=='l') strcpy(t,"ln"); if (c=='e') strcpy(t,"exp");
 if (c=='^') strcpy(t,"^"); if (c=='&') strcpy(t,"&");
 push_to_line(t,2);
 free(t);
  }
  if (!strcmp(p,"sin")) push_to_char_stack('s');
  if (!strcmp(p,"cos")) push_to_char_stack('c');
  if (!strcmp(p,"ln")) push_to_char_stack('l');
  if (!strcmp(p,"exp")) push_to_char_stack('e');
  if (s[i+1]!='(') return 0;
  }
free(p);                                                                       }
 else {
p=(char*)malloc(sizeof(char)*2);
if ((s[i]=='+') || (s[i]=='-')) {
  if ((i>=1) && (s[i-1]=='(')) {
 while (st && ((st->elem=='s') || (st->elem=='c') || (st->elem=='l') || (st->elem=='e') || (st->elem=='^') || (st->elem=='&'))) {
c=pop_from_char_stack();
t=(char*)malloc(sizeof(char)*3);
if (c=='s') strcpy(t,"sin"); if (c=='c') strcpy(t,"cos");
if (c=='l') strcpy(t,"ln"); if (c=='e') strcpy(t,"exp");
if (c=='^') strcpy(t,"^"); if (c=='&') strcpy(t,"&");
push_to_line(t,2);
free(t);
 }
 if (s[i]=='+') push_to_char_stack('&');
 if (s[i]=='-') push_to_char_stack('^');
 if (((s[i+1]>'Z') && (s[i+1]<'a')) || (s[i+1]>'z') || ((s[i+1]<'A') && (s[i+1]>'9')) || (s[i+1]<'0')) return 0;
  }
  else {
 while ((st!=NULL) && (st->elem!='(')) {

c=pop_from_char_stack();
p[0]=c;
p[1]='\0';
temp_push ();
 }
 push_to_char_stack(s[i]);
 if ((s[i+1]=='+') || (s[i+1]=='-') || (s[i+1]=='*') || (s[i+1]=='/')) return 0;
  }
}
if ((s[i]=='*') || (s[i]=='/')) {
  while ((st!=NULL) && (st->elem!='(') && (st->elem!='+') && (st->elem!='-')) {
 c=pop_from_char_stack();
 p[0]=c;
 p[1]='\0';
 temp_push ();
  }
  push_to_char_stack(s[i]);
  if ((s[i+1]=='+') || (s[i+1]=='-') || (s[i+1]=='*') || (s[i+1]=='/')) return 0;
}
if (s[i]=='(') {
  push_to_char_stack('(');
}
if (s[i]==')') {
  while (st && (st->elem!='(')) {
 c=pop_from_char_stack();
 p[0]=c;
 p[1]='\0';
 temp_push ();
  }
  if ((!st) && (c!='(')) return 0;
  if (st->elem=='(') c=pop_from_char_stack();
  else return 0;
}
if ((s[i]>='0') && (s[i]<='9')) {
 j=i;
 while (((s[i]>='0') && (s[i]<='9')) || (s[i]=='.')) i++;
 i--;
 ptr=s+j;
 p=(char*)malloc(sizeof(char)*(i-j+2));
 p[0]='\0';
 strncat(p, ptr, i-j+1);
 push_to_line(p,4);
}
free(p);
 }
 i++;
  }
  p=(char*)malloc(sizeof(char)*2);
  while (st!=NULL) {
 if (st->elem=='(') return 0;
 c=pop_from_char_stack();
 p[0]=c;
 p[1]='\0';
 temp_push ();
  }
  free(p);
  return 1;
}


double count_POLIZ(){//---------------------------------------------------------------------------------------------------
  int i=0;
  double a,b,c;
  char *s, *u;
  
  char *ccanf(){
  char c, *p, *t;
  p=(char*)malloc(sizeof(char));
  p[0]='\0';
  t=(char*)malloc(sizeof(char)*2);
  do {
 c=getchar();
 if (c=='\n') c='\0';
 t[0]=c;
 t[1]='\0';
 if ((c!='\n') && (c!='\0')) {
p=(char*)realloc(p, sizeof(char)*(strlen(p)+strlen(t)+1));
strcat(p, t); }  }
  while ((c!='\0') && (c!='\n'));
  free(t);
  return p;    }

double atoii(char *s){
  int i=0;
  double a=0, b=0, c;
  if ((s[0]=='-') || (s[0]=='+')) i++;
  while ((s[i]!='.') && (s[i]!='\0') && (s[i]!='\n'))
 a=10*a+(s[i++]-'0');
  if (s[i]=='.') {
 i=strlen(s)-1;
 while (s[i]!='.')
b=b/10+(s[i--]-'0');
 b=b/10;         }
  c=a+b;
  if (s[0]=='-') c=-c;
  return c;          }

  struct struc2 *k;
  struct struc2 *l;
  k=li;
  while (k!=NULL) { 
 if (k->id==1) {
//s=k->elem;
s=(char*)malloc(sizeof(char)*(strlen(k->elem)+1));
strcpy(s,k->elem);
printf("Input %s=",s);
u=ccanf();
k->elem=(char*)realloc(k->elem, sizeof(char)*(strlen(u)+1));
strcpy(k->elem,u);
k->id=4;
l=k;
while (l!=NULL) {
  if ((l->id==1) && (!strcmp(l->elem,s))){
 l->elem=(char*)realloc(l->elem, sizeof(char)*(strlen(u)+1));
 strcpy(l->elem,u);
 l->id=4;}
  l=l->next;}}
 k=k->next;}
  k=li;
  while (k!=NULL) { if (k->id==4){
push_to_double_stack(atoii(k->elem));  }
 if (k->id==2){
if (!strcmp(k->elem,"s")) {
  b=pop_from_double_stack();
  c=sin(b);
  push_to_double_stack(c);}
if (!strcmp(k->elem,"c")) {
  b=pop_from_double_stack();
  c=cos(b);
  push_to_double_stack(c);}
if (!strcmp(k->elem,"l")) {
  b=pop_from_double_stack();
  if (b<=0) {
 printf("Error in operand\n");
 return 0;  }
  c=log(b);
  push_to_double_stack(c);}
if (!strcmp(k->elem,"e")) {
  b=pop_from_double_stack();
  c=exp(b);
  push_to_double_stack(c);}
if (!strcmp(k->elem,"^")) {
  b=pop_from_double_stack();
  b=-b;
  push_to_double_stack(b);} 
              }
 if (k->id==3) {
if (!strcmp(k->elem,"+")) {k->next;
  b=pop_from_double_stack();
  c=pop_from_double_stack();
  b=b+c;
  push_to_double_stack(b);}
if (!strcmp(k->elem,"-")) {
  b=pop_from_double_stack();
  c=pop_from_double_stack();
  c=c-b;
  push_to_double_stack(c);}
if (!strcmp(k->elem,"*")) {
  b=pop_from_double_stack();
  c=pop_from_double_stack();
  b=b*c;
  push_to_double_stack(b);}
if (!strcmp(k->elem,"/")) {
  b=pop_from_double_stack();
  c=pop_from_double_stack();
  c=c/b;
  push_to_double_stack(c);} 
               }
 k=k->next;  }
  a=pop_from_double_stack();
  
  if (stack!=NULL) {
 printf("stack error");
 return 0;         }
  else return a;  }


int main(int argc, char *argv[]){//---------------------------------------------------------------------------------------------------
  char *u;
  int s;
  double a;
  
  void print_POLIZ(){
  struct struc2 *k;
  k=li;
  while (k!=NULL) {
 printf("%s ",k->elem);
 k=k->next;       }
  printf("\n");     }
  u=(char*)malloc(sizeof(char)*(strlen(argv[1])+1));
  strcpy(u,argv[1]);
  s=create_POLIZ(u);
  print_POLIZ();
  if (s==1)         {
 a=count_POLIZ();
 printf("%lf\n",a); }
  else printf("error in input"); 
  return 0;
}
