// Подпрограмма compil и сопутствующие ей модули. Переводит строку математичес-
// ких выражений во внутреннее представление, пригодное для исполнения
// подпрограммой   . Содержимое файла compl.c
//
// (c) Boland 1994

int determ(char *a,int p)
{
  char *ap,ch;
  ap=a+p; ch=*ap;
  if(ch=='x') return 0;
  if(isdigit(ch)) return 1;
  if( (ch=='+')||(ch=='-')||(ch=='*')||(ch=='/')||(ch=='^')||
      (ch=='(')||(ch==')')||
      (!strncmp(ap,"sqr",3))||(!strncmp(ap,"abs",3))||(!strncmp(ap,"exp",3))||
      (!strncmp(ap,"ln",2))||(!strncmp(ap,"sin",3))||(!strncmp(ap,"cos",3))||
      (!strncmp(ap,"tg",2)) ) return 2;
    else errorlevel=7;
  return -1;
}

int pri(int i)
{
  switch(i)
  {
    case 16: case 17: case 18: case 19: case 20: case 21: case 22:
	      return 10;
    case 15:  return 9;
    case 13: case 14:
	      return 8;
    case 11: case 12:
	      return 7;
    case 23:  return 1;
    case 24:  return 0;
    default:  return -1;
  }
}

int var(char *a,int *i)
{
  int j;
  char c[2];
  c[0]=a[(*i)+1]; c[1]='\0';
  *i+=2;
  return atoi(c);
}

float numb(char *a,int *i)
{
  int j,n,k;
  char c[10];
  n=strlen(a+(*i));
  for(k=1;( (isdigit(a[(*i)+k])) || (a[(*i)+k]=='.')) && ((*i)+k<=n) ;k++);
  strncpy(c,a+(*i),k);
  *i+=k;
  return atof(c);
}

int oper(char *a,int *p)
{
  char *ap,ch;
  ap=a+(*p); ch=*ap;
  if((ch=='+')) { *p+=1; return 11; }
  if((ch=='-')) { *p+=1; return 12; }
  if((ch=='*')) { *p+=1; return 13; }
  if((ch=='/')) { *p+=1; return 14; }
  if((ch=='^')) { *p+=1; return 15; }
  if((ch=='(')) { *p+=1; return 24; }
  if((ch==')')) { *p+=1; return 23; }
  if(!strncmp(ap,"sqr",3)) { *p+=3; return 16; }
  if(!strncmp(ap,"abs",3)) { *p+=3; return 17; }
  if(!strncmp(ap,"exp",3)) { *p+=3; return 18; }
  if(!strncmp(ap,"ln",2)) { *p+=2; return 19; }
  if(!strncmp(ap,"sin",3)) { *p+=3; return 20; }
  if(!strncmp(ap,"cos",3)) { *p+=3; return 21; }
  if(!strncmp(ap,"tg",3)) { *p+=2; return 22; }
}


void compil(char funstr[80])
{
  int i,j,ptf,ptp,opst[100],ptop;

  errorlevel=0; ptp=ptf=0; ptop=-1;
  while(ptf<strlen(funstr))
  {
    i=determ(funstr,ptf);
    switch(i)
    {
      case 0:  j=var(funstr,&ptf);
	       pr[ptp++]=j;
	       break;
      case 1:  pr[ptp]=10; org[ptp++]=numb(funstr,&ptf); break;
      case 2:  j=oper(funstr,&ptf);
	       if(ptop<0)
		   opst[++ptop]=j;
		 else
		   {
		     if((pri(j)==0)||(pri(j)>pri(opst[ptop])))
			 opst[++ptop]=j;
		       else
			 {
			   if(j==23)
			       {
				 while( (opst[ptop]!=24) && (ptop>=0) )
				 {
				   if((opst[ptop]!=23)&&(opst[ptop]!=24))
				       {
					 pr[ptp++]=opst[ptop];
					 ptop--;
				       }
				     else ptop--;
				 }
				 if(ptop<0)
				     { errorlevel=7; return; }
				   else ptop--;
			       }
			     else
			       {
				 while((pri(opst[ptop])>=pri(j))&&(ptop>=0))
				 {
				   pr[ptp]=opst[ptop]; ptp++; ptop--;
				 }
				 opst[++ptop]=j;
			       }
			 }
		   }
	       break;

      default: errorlevel=7; return;
    }
  }
  while(ptop>=0) pr[ptp++]=opst[ptop--];
  pr[ptp]=99;
  return;
}