
 // Scaner.cpp
 // (c) Сеpгей Гоцуляк, ВВТ-307
 // 22.11.1999 - 10.01.2000

 // Сканер для программ на МИЛАНЕ. Аналогичен сканеру под FoxPro.

 #include <conio.h>
 #include <stdio.h>
 #include <string.h>
 #include <process.h>
 #include <dos.h>
 #include<ctype.h>
 #include<stdlib.h>

 FILE *file1,*file2;

/***************************КОНСТАНТЫ***********************************/
	  enum{BEGIN=1,DO,ELSE,END,FI,IF,OD,OUTPUT,READ,THEN,WHILE,
			 TZ,OPSR,OPTS,OPTU,OPPR,OPEN,CLOSE,IDENT,CONST};
/**************************ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ************************/

int n;           //  номер очередной лексемы
int stekres[50]; //  стек результатов вычислений
int steki[50];   //  стек идентификаторов
int stekmul[50]; //  стек для операций типа умножения
int steksum[50]; //  стек для операций типа сложения
int stekrel[50]; //  стек для операций отношения
int arrident[20];//  стек текущих значений идентификаторов
int topres;      //  вершина стека stekres
int topi;        //  вершина стека steki
int topmul;      //  вершина стека stekmul
int topsum;      //  вершина стека steksum
int toprel;      //  вершина стека stekrel
int coderr;      //  числовой код ошибки
int ilex;
int q;
int icon;
int maxq;
int id;
int lexn[500];
int lexz[500];
char ident[20][10];
char cons[20][10];
char sim;
char *prog;
char *txterr[5];

/***********************ПРОТОТИПЫ ФУНКЦИЙ*******************************/

int val(char *);
int inlist(int,int,int,int);
int stek(int,int*,int&,int&);
int tabid(char *);
int kluch(char *);
int tabconst(char *);
void l_prog();
void s_prog();
void e_prog();
void b_prog();
void t_prog();
void p_prog();
void skaner(char *);
void bukva();
void cifra();
char* file_str(char *);

/**********************************************************************/

int stek(int oper,int *stek,int &top,int &element)
{
 coderr=0;
 int vozvrat=1;
 switch(oper)
 {
  case 0:
   top=0;
   for(int i=0;i<50;i++)
   stek[i]=0;
   break;
  case 1:
   if(top>=50)
   {coderr=3;vozvrat=0;}
   else
   {top++;stek[top]=element;}
   break;
  case -1:
   if(top<=0)
   {coderr=4;vozvrat=0;}
   else
   {element=stek[top];top--;}
   break;
  default : coderr=5;vozvrat=0;
 }
 return vozvrat;
}
char * file_str(char *name)
{
 int i=0;
 char *str;
 char s;
 FILE *f;
 if((f=fopen(name,"rb"))==NULL)
 {
  //printf("Ошибка при открытиие файла на чтение");
  exit(201);
 }
 s=getc(f);
 while(s!=EOF)
 {
  i++;
  s=getc(f);
 }
 str=new char[i+1];
 fseek(f,0,0);
 s=getc(f);
 i=0;
 while(s!=EOF)
 {
  if((int)s==13||(int)s==9||(int)s==26||(int)s==10||(int)s==8)
  s=' ';
  str[i]=s;i++;
  s=getc(f);
 }
 str[i]='\0';
 fclose(f);
 return str;
}
/****************************************************************************/
void skaner()
{
 prog=file_str("Phase01.tmp");
 id=-1;
 icon=-1;
 coderr=0;
 q=-1;
 n=-1;
 for(int ii=0;ii<20;ii++)
 {
		 ident[ii][9]='\0';
		 cons[ii][9]='\0';
 }
 maxq=strlen(prog);
 while(1)
 {
  q++;
  if(q==maxq)
  break;
  if(n==500)
  {
	coderr=1;
	break;
  }
  sim=prog[q];
  if(sim==' ')
  continue;
  if(isalpha(sim))
  {
	bukva();
	continue;
  }
  if(isdigit(sim))
  {
	cifra();
	continue;
  }
  if(sim==';')
  {
	n++;
	lexn[n]=12;
	lexz[n]=0;
	continue;
  }
  if(sim=='=')
  {
	n++;
	lexn[n]=13;
	lexz[n]=0;
	continue;
  }
  if(sim=='>')
  if(prog[q+1]=='=')
  {
	n++;
	lexn[n]=13;
	lexz[n]=4;
	q++;
	continue;
  }
  else
  {
	n++;
	lexn[n]=13;
	lexz[n]=2;
	continue;
  }
  if(sim=='<')
  {
	switch(prog[q+1])
	{
	 case '>':
	 n++;
	 lexn[n]=13;
	 lexz[n]=1;
	 q++;
	 break;
	 case '=':
	 n++;
	 lexn[n]=13;
	 lexz[n]=5;
	 q++;
	 break;
	 default:
	 n++;
	 lexn[n]=13;
	 lexz[n]=3;
	}
	continue;
  }
  if(sim=='+')
  {
	n++;
	lexn[n]=14;
	lexz[n]=0;
	continue;
  }
  if(sim=='-')
  {
	n++;
	lexn[n]=14;
	lexz[n]=1;
	continue;
  }
  if(sim=='*')
  {
	n++;
	lexn[n]=15;
	lexz[n]=0;
	continue;
  }
  if(sim=='/')
  {
	n++;
	lexn[n]=15;
	lexz[n]=1;
	continue;
  }
  if(sim==':'&&prog[q+1]=='=')
  {
	n++;
	lexn[n]=16;
	lexz[n]=0;
	q++;
	continue;
  }
  if(sim=='(')
  {
	n++;
	lexn[n]=17;
	lexz[n]=0;
	continue;
  }
  if(sim==')')
  {
	n++;
	lexn[n]=18;
	lexz[n]=0;
	continue;
  }
  coderr=2;
  break;
 }
 if(coderr)
 {
  //gotoxy(3,24);
  //textcolor
  //cprintf("ОШИБКА: %s\nПОЗИЦИЯ: %d символ = %s\nНажмите любую клавишу...\n",txterr[coderr],q,sim);
  //getch();
  exit(1);
 }
 return ;
}
/****************************************************************************/
int kluch(char * v)
{
 char * klslov[12];
 int k,i;
 klslov[1]="begin";
 klslov[2]="do" ;
 klslov[3]="else";
 klslov[4]="end";
 klslov[5]="fi";
 klslov[6]="if";
 klslov[7]="od";
 klslov[8]="output";
 klslov[9]="read";
 klslov[10]="then";
 klslov[11]="while";
 k=0;
 for(i=1;i<=11;i++)
 if(!strcmp(v,klslov[i]))
 {
  k=i;
  break;
 }
 return k;
}
/****************************************************************************/
int tabid(char * v)
{
 int k,i;
 k=-1;
 if(id!=-1)
 for(i=0;i<=id;i++)
 if(!strcmp(v,ident[i]))
 {
  k=i;
  break;
 }
 return k;
}

/****************************************************************************/
int tabconst(char * v)
{
 int k,i;
 k=-1;
 if(icon!=-1)
 for(i=0;i<=icon;i++)
 if(!strcmp(v,cons[i]))
 {
  k=i;
  break;
 }
 return k;
}
/****************************************************************************/
void bukva()
{
 int i=0;
 char * slovo;
 slovo="";
 while(q<=maxq&&(isalpha(prog[q])||isdigit(prog[q])))
 {
  slovo[i]=prog[q];
  q++;
  i++;
 }
 slovo[i]='\0';
 q--;
 if(kluch(slovo))
 {
  n++;
  lexn[n]=kluch(slovo);
  lexz[n]=0;
 }
 else
 if(tabid(slovo)!=-1)
 {
  n++;
  lexn[n]=19;
  lexz[n]=tabid(slovo);
 }
 else
 {
  id++;
  if(id>20)
  {
	//printf("ОШИБКА: Переполнение массива идентификаторов\nНажмите любую клавишу...");
	//getch();
	exit(1);
  }
  strcpy(ident[id],slovo);
  n++;
  lexn[n]=19;
  lexz[n]=id;
 }
 return;
}
/****************************************************************************/
void cifra()
{
 int i=0;
 char *slovo="";
 while(q<=maxq&&isdigit(prog[q]))
 {
  slovo[i]=prog[q];
  q++;
  i++;
 }
 slovo[i]='\0';
 q--;
 if(tabconst(slovo)!=-1)
 {
  n++;
  lexn[n]=20;
  lexz[n]=tabconst(slovo);
 }
 else
 {
  icon++;
  if(icon>20)
  {
	//printf("ОШИБКА: Переполнение массива констант\nНажмите любую клавишу...");
	//getch();
	exit(1);
  }
  strcpy(cons[icon],slovo);
  n++;
  lexn[n]=20;
  lexz[n]=tabconst(slovo);
 }
 return;
}
/****************************************************************************/
void prohod()
{
 int r,s,topdo,topif;
 int stekif[51],stekdo[51];
 r=0;
 s=0;
 topdo=0;
 topif=0;
 ilex=n;
 for(n=0;n<=ilex;n++)
 switch(lexn[n])
 {
  case 11 :
  if(!stek(1,stekdo,topdo,n))
  {
	coderr=3;
	return;
  }
  break;
  case 2 :
  if(!stek(1,stekdo,topdo,n))
  {
	coderr=3;
	return;
  }
  break;
  case 7 :
  if(!stek(-1,stekdo,topdo,s))
  {
	coderr=4;
	return;
  }
  if(!stek(-1,stekdo,topdo,r))
  {
	coderr=4;
	return;
  }
  lexz[s]=n+1;
  lexz[n]=r+1;
  break;
  case 10 :
  if(!stek(1,stekif,topif,n))
  {
	coderr=3;
	return;
  }
  break;
  case 3 :
  if(!stek(-1,stekif,topif,r))
  {
	coderr=4;
	return;
  }
  lexz[r]=n+1;
  if(!stek(1,stekif,topif,n))
  {
	coderr=3;
	return;
  }
  break;
  case 5 :
  if(!stek(-1,stekif,topif,r))
  {
	coderr=4;
	return;
  }
  lexz[r]=n+1;
  break;
 }
 return;
}
/****************************************************************************/
/*void main(int arg,char *argv[])
{
 int i;
 char * tr;
 clrscr();
 if(arg<2) return;
 skaner(argv[1]);
 prohod();
 interp();
} */

 /************************************************************************/

 int main()
 {

	 //window(11,7,69,17);
	 textcolor(RED);
	 printf("\n\n");
	 cprintf(" Фаза02: ");
	 textcolor(YELLOW);
	 cprintf("Сканеp ");
	 textcolor(LIGHTBLUE);
	 printf("\n");
	 cprintf("    - Распознавание лексем ...");
	 skaner();

	 printf("\n    - Расстановка ссылок ...");
	 prohod();
	 file2=fopen("Phase02.tmp","wb");
	 if(file2==NULL)
		 exit(203);
	 fprintf(file2,"%d\n",ilex+1);
	 for(int i=0;i<500;i++)
		 fprintf(file2,"%d,%d\n",lexn[i],lexz[i]);
	 fprintf(file2,"%d\n",id+1);
	 //for(i=0;i<20;i++)
	 //	 fprintf(file2,"%s",ident[i]);
	 fprintf(file2,"%d\n",icon+1);
	 for(i=0;i<20;i++)
		 fprintf(file2,"%s\n",cons[i]);
	 fclose(file2);
	 exit(0);
	 return 0;
 }