Littel example how work compiler

Delphi & Pascal (česká wiki)
Přejít na: navigace, hledání
Category: Programs in C, C++

Program: Compiler.c
File exe: Compiler.exe
need: Klavesy.hStruct.h
Example: Prog.c

Littel example how work compiler. It's a easy compiler. You only locate syntax error, don't translate to bin code. IDE is know from common work with C compiler.
// COMPILER.C                Copyright (c) TrSek alias Zdeno Sekerak 
// Program je pokusom o vlastny compiler s podobnou syntaxou         
// ako ma Pascal.                                                    
//                                                                   
// Datum:22.04.96                               http://www.trsek.com 
 
#define maxx 78
#define maxz 21
#include "klavesy.h"
#include <stdio.h>
#include <conio.h>
#include <dos.h>
#include <bios.h>
#include <string.h>
#include <dir.h>
#include <errno.h>
#include <alloc.h>
 
#define maxx 78
#define maxy 21
#define maxs 128
#define maxznak 128
#define maxsyn 14
#define maxerr 30
#define maxkl 17
#define maxpocs 256
 
#include "struct.h"
 
char klslov[maxkl+1][maxsyn] =
 { {"DECL"} , {"INTEGER"} , {"START"} , {"WHILE"} , {"ENDWHILE"} , {"INTEGERREAD"} ,
   {"INTEGERWRITE"} ,  {"STOP"} , {" "} , {";"} , {":="} ,
   {"("} , {")"} , {"<"} , {">"} , {"+"} , {":"} };
 
void okno (int, int, int, int, int, int );
					/* Definuj okno posledne dve su farby */
					/* podklad, pismo */
void editor ( void );			/* Uvodna obrazovka */
void tprintf( char text[]);		/* Specialny prvy riadok */
void farba(int x,int y);		/* nastavi naraz farbu pisma aj podkladu */
void posunx ( int );			/* Posun text v smere osi x */
void posuny ( int );			/* Posun text v smere osi y */
void deletuj ( int, int );		/* Zmaz znak z poziciou */
void novyr ( int );			/* Novy riadok */
int  posledny ( int );			/* Posledny znak v riadku */
void strana ( int, int );		/* Vykresli stranu */
void help ( void );			/* No comment */
void save ( char meno[] );		/* Uloz subor pod menom */
int  vypis_sub( char mena[][13], int dlzok ); /* Vypis suborov do okna */
int  load ( void );			/* Najdi subor */
int  from_disk( char subor[]);          /* Precitaj subor z disku */
void run ( void );			/* Spusti program */
void outwin ( void );			/* Pozri OUTPUT obrazovku */
void compile ( void );			/* Skompiluj program */
void option ( void );			/* Opsns */
def_riadok *zaradr( def_riadok *pointer, char text[] );
					/* Zaradi text do pola */
def_riadok *vyhodr( def_riadok *pointer );
					/* Vyhodi text z pola */
int  otazka ( char text[], char pr[], char dr[], char tr[] );
					/* Otazka , pr-prva volba, dr-druha volba */
int kluc_slova ( def_syntax * (* syntax) );
					/* Doplni klucove slova */
int patri ( char s[] , int x , int *v_rade , void *prvys , int caka );
					/* Porovnava dve retazce */
int  podmienka ( char s[] , int x , def_syntax  *prvys);
int aritmetika ( char s[] , int x , void *prvys);
					/* Je to aritmetika ??? Nie !!!*/
int premenne (int *x, char s[], def_syntax *syntax);
					/* doplni premenne do syntax */
int comp,pocr;				/* pocet riadkov suboru */
char subor[maxs];			/* Meno suboru */
void *prvy,*teraz;			/* Pameta pointer na prvy riadok */
 
 
// main tu to vsetko zacne
void main(int arg, char *args[])
{
int key,i;
int x=1,y=1,xr=1,yr=1;
unsigned insert=0,ulozene=0;
 
 editor();
 prvy=NULL; pocr=0; comp=0;
 
 if (arg>0) {
    strcpy(subor,args[1]);
    from_disk(subor);
    strana(1,1);
 }
 
 gotoxy(x,y);
 do {
  key=getch();
  if (key==BACKSPACE) {}	// nereaguje
 
  if (key==0)
  {
     key=getch();
     switch (key)
     {
     case LEFT:  x=x-1;
		 if (x<1) {
		    xr--;x=1;
		    if (xr<1) xr=1;
			 else strana(xr,yr);
		 }
	  break;
     case RIGHT: x=x+1;
		 if (x>maxx) {
		    xr++;x=maxx-3;
		    if ((xr+x)>maxznak)
		       xr=maxznak-x;
 
		    strana(xr,yr);
		 }
	  break;
     case UP:    y=y-1;
		 if (y<1) {
		    y=1;
		    yr--;
		    if (yr<1) yr=1;
		    strana(xr,yr);
		 }
	  break;
     case DOWN:  y=y+1;
		 if (y>maxy) {
		    y=maxy;
		    yr=yr+1;
 
		    if ((yr+y)>pocr) {
		       yr=pocr-maxy-y-1;
		       if (yr<1) yr=1;
		    }
		    strana(xr,yr);
		 }
	  break;
     case ENTER: x=1;y=y+1;novyr(y);posunx(0);
	  break;
     case DEL:   deletuj(x,y);
	  break;
     case INSERT:insert=!insert;
	  break;
     case HOME:  x=1;
	  break;
     case END:   x=posledny(yr+y-1);
		 xr=1;
		 if (x>maxx) {
		    xr=x-maxx;
		    x=maxx-3;
		    strana(xr,yr);
		 }
	  break;
     case PGDN:  yr=yr+maxy;
		 if ((yr+y)>pocr) {
		    for (i=pocr;i<=(yr+y);i++) novyr(i);
		    yr=pocr-20;
		 }
		 strana(xr,yr);
	  break;
     case PGUP:  yr=yr-maxy;
		 if (yr<1) yr=1;
		 strana(xr,yr);
	  break;
     case F1:    help();
	  break;
     case F2:    save(subor);
	  break;
     case F3:    load();
		 window(2,3,79,23);
		 clrscr();
		 strana(1,1);
	  break;
     case F4:    save("");
	  break;
     case F5:    if (!comp) compile();
		 run();
	  break;
     case F6:    outwin();
	  break;
     case F7:
	  break;
     case F8:    option();
	  break;
     case F9:    compile();
	  break;
     case F10:   if (!ulozene) {
		   if (otazka("Ulozit prave editovany subor ?"," ^Ano "," ^Nie ","")==1)
		      save(subor);
		   else
		      key=0;
		 }
 
		 if (key==0)
		    if (otazka("        Chces skoncit ?       "," ^Ano "," ^Nie ","")==1)
		       key=F10;
	  break;
     default: break;
     }
    gotoxy(x,y);
  }
 } while (key!=F10);
 
 clrscr();
}
 
 
// zobrazi okno v ktorom sa budeme pohybovat
void okno (int x1, int y1, int x2, int y2, int col1, int col2 )
{
int x,y;
 
 window(x1,y1,x1+x2,y1+y2);
 farba(col2,col1);
 clrscr();
 
 gotoxy(1,y2);cprintf("Č");
 gotoxy(x2+1,y2);cprintf("ź");
 gotoxy(1,1);insline();
 gotoxy(1,1);cprintf("É");
 gotoxy(x2+1,1);cprintf("ť");
 
 for (x=2;x<=x2;x++) {
   gotoxy(x,1);cprintf("Í");
   gotoxy(x,y2+1);cprintf("Í");
 }
 
 for (y=2;y<=y2;y++) {
   gotoxy(1,y);cprintf("ş");
   gotoxy(x2+1,y);cprintf("ş");
 }
 
 window(x1+1,y1+1,x1+x2-1,y1+y2-1);
}
 
 
// nakresli prostredie editora
void editor( void )
{
 okno(1,2,79,22,BLUE,YELLOW);
 window(1,1,80,25);
 gotoxy(1,1);
 textbackground(LIGHTGRAY);
 tprintf("^F^1Help ^F^2Save ^F^3LOAD ^F^4SAVE_AS ^F^5RUN ^F^6OUTWIN ^F^7STEP ^F^8OPTION ^F^9COMPILE ^F^1^0EXIT");
 window(2,3,79,24);
}
 
 
// vypise text s tym ze pismena zacinajuce ^ vyfarby inou farbou
void tprintf( char text[])
{
int i;
 
 textcolor(DARKGRAY);
 for (i=0; i<strlen(text); i++)
 {
   if (text[i]!='^') {
      if (text[i-1]=='^') textcolor(RED);
		     else textcolor(BLACK);
      cprintf("%c",text[i]);
   }
 }
 textcolor(YELLOW);
}
 
 
// nastavi naraz farbu pisma aj podkladu
void farba(int x,int y)
{
 textcolor(x);
 textbackground(y);
}
 
 
void posunx ( int  xp )
{
 xp=xp;
}
 
void posuny ( int yp )
{
 yp=yp;
}
 
void deletuj ( int xd, int yd )
{
 xd=xd;
 yd=yd;
}
 
void novyr ( int yr )
{
 yr=yr;
}
 
// najde posledny znak v retazci
int  posledny ( int yp )
{
int xp=1;
int y=1;
def_riadok *priadok;
 
 if (prvy==NULL) return(0);
 priadok=prvy;
 
 while(( priadok != NULL ) && (y<yp))
 {
   priadok=( * priadok).zani;
   y=y+1;
 }
 
 // je mimo text
 if (priadok == NULL )
    return(xp);
 
 // najde koniec riadku
 while ((( * priadok).znaky[xp]!='\0') && (xp<maxznak)) xp++;
 return(xp);
}
 
 
// zobrazi subor od x,y suradnic
void strana ( int xs, int ys )
{
int x,y;
def_riadok *priadok;
 
 textbackground(BLUE);
 priadok=prvy;
 
 // prechod na poziciu
 for (y=1; y<ys; y++)
   if (priadok!=NULL)
      priadok= (*priadok).zani;
 
 window(2,3,79,23);
 clrscr();
 
 //
 for (y=0; y<21 && priadok!=NULL; y++)
 {
   for (x=xs; x<xs+78 && x<strlen((*priadok).znaky) ;x++)
   {
     gotoxy(x-xs+1,y+1);
     cprintf("%c",(*priadok).znaky[x]);
   }
   priadok = (*priadok).zani;
 }
}
 
void help ( void )
{
}
 
 
// ulozi subor
void save ( char meno[] )
{
 meno=meno;
}
 
 
// vypise obsah adresara
// dlzok znamena od akeho suboru sa ma zacat
int vypis_sub(char mena[][13], int dlzok)
{
struct ffblk subory;
int yp=-1;
int i;
 
 errno=0;
 findfirst("*.*",&subory,FA_ARCH|FA_DIREC|FA_RDONLY|FA_HIDDEN);
 
 // najprv vsetky vyhlada
 while ((errno==0) && (yp<maxpocs))
 {
   strcpy(mena[++yp],subory.ff_name);
 
   // subory prekonvertujem na male pismena
   if ((subory.ff_attrib & FA_DIREC) == 0)
      for (i=0; i<strlen(mena[yp]); i++)
	if (mena[yp][i]!='.')
	   mena[yp][i]=mena[yp][i]+32;
 
   findnext(&subory);
 }
 
 // teraz ich vsetky vypisem
 for( i=0; i<dlzok && i<yp; i++ )
 {
   gotoxy(3,i+1);
   cprintf("%s",mena[i]);
 }
 
 return(yp);
}
 
 
// precita program zo suboru
int load ( void )
{
int dlzok=12;
int y=0, yr=0, yp=0;
char mena[maxpocs+1][13];
char key;
 
 yp=0; yp=yp; yr=0; yr=yr;	/* Potom ma zrus */
 okno(15,3,18,dlzok+1,LIGHTGRAY,DARKGRAY);
 yp=vypis_sub(mena,dlzok);
 
 farba(YELLOW,BLUE);
 gotoxy(3,1);
 cprintf("%s",mena[0]);
 
 y=0; key=32;
 do {
   key=getch();
 
   farba(DARKGRAY,LIGHTGRAY);
   gotoxy(3,y+1);
   cprintf("%s",mena[y+yr]);
 
   switch (key)
   {
      case 0: key=getch();
	switch (key)
	{
	   case UP:
		y=y-1;
		if (y<0)
		{
		  y=0;
		  yr=yr-1;
 
		  if (yr<0) yr=0;
		  else
		  {
		    gotoxy(1,1);
		    insline();
		  }
		}
		break;
 
	   case DOWN:
		y=y+1;
		if (y>yp) y=yp;
		if (y>(dlzok-1))
		{
		  y=dlzok-1;
		  yr=yr+1;
 
		  if ((yr+y)>yp) yr=yp-y;
		  else
		  {
		    gotoxy(1,1);
		    delline();
		  }
		}
		break;
	}
	break;
 
      case ENTER:
	   if ((mena[y+yr][0]=='.') || ((mena[y+yr][0]>='A') && (mena[y+yr][0]<='Z')))
	   {
	     chdir(mena[y+yr]);
	     clrscr();
	     yp=vypis_sub(mena,dlzok);
	     y=1; yr=0; key=32;
	   }
	   break;
   }
 
   farba(YELLOW,BLUE);
   gotoxy(3,y+1);
   cprintf("%s",mena[y+yr]);
 }
 while ((key!=ESC) && (key!=ENTER));
 
 if (key==ENTER) strcpy(subor,mena[y+yr]);
 if (key==ESC) return(0);
 
 // precitaj subor
 return( from_disk(subor));
}
 
 
// precita z disku
int from_disk( char subor[] )
{
FILE *fopen(),*f;
int y,err=0;
char text[maxznak];
 
 riadok=prvy; prvy=NULL;
 while ( riadok!=NULL) riadok=vyhodr(riadok);
 
 pocr=0;
 f=fopen(subor,"r");
 
 do {
  pocr++; y=0;
  text[y]=' ';
 
  do {
    err=fscanf(f,"%c",&text[++y]);
  } while ((text[y]!='\n') && (err==1) && (y<maxznak-2) && (text[y]!='\0'));
 
  text[y]='\0';text[y+1]='\n';
  riadok=zaradr(riadok,text);
  if (prvy==NULL) prvy=riadok;
 } while ((err==1) && (riadok!=NULL));
 
 fclose(f);
 
 if (riadok==NULL) {
    y=otazka("   Nemas dost pamete na editaciu suboru !!!   "," ^ENTER ","","");
    while ( riadok!=NULL) riadok=vyhodr(riadok);
    return(0);
 }
 
 return(1);
}
 
void run ( void )
{
}
 
void outwin ( void )
{
}
 
int patri ( char s[] , int x , int *v_rade , void * prvys , int caka )
{
def_syntax *syntax;
int i,x1;
 
 syntax=prvys;
 i=0;*v_rade=0;
 
 if (caka!=-1)
    while (*v_rade<caka) {
      *v_rade=*v_rade+1;
      syntax=(*syntax).zani;
    }
 
 while ( (s[x+i]==' ') && (s[x+i]!='\0')) i++;
 x1=x+i;i=0;
 
 if (x1>=strlen(s)) {
    *v_rade=-1;
    return(x1);
 }
 
 if (caka==-1)
    while ( (i<strlen((*syntax).znaky) ) && ( (*syntax).zani!=NULL) )
    {
      i=0;
      *v_rade=*v_rade+1;
      if (*v_rade!=1)
	 syntax=(*syntax).zani;
 
      while ( (i<strlen((*syntax).znaky)) && ((*syntax).znaky[i]==s[x1+i])) i=i+1;
      if ((s[x1+i]!=' ') && (s[x1+i]!='\0') && (*v_rade<8)) i=0;
    } else {
      while ((i<strlen((*syntax).znaky)) && ((*syntax).znaky[i]==s[x1+i])) i=i+1;
    }
 
 if (i==strlen((*syntax).znaky)) {
    while ( (s[x1+i]==' ') && (s[x1+i]!='\0')) i++;
    return(x1+i-1);
 }
 else {
    *v_rade=0; return(x1);
 }
}
 
int aritmetika ( char s[] , int x , void *prvys )
{
def_syntax *syntax;
 
 syntax=prvys;
 x=x;s=s;
 return(0);
}
 
 
// odskusane funguje OK
int premenne (int *x, char s[], def_syntax *syntax)
{
int i;
char prem[10];
 
 i=0;
 while ((s[*x+i]!=';') && (strlen(s)>*x+i) )
 {
   while (s[*x+i]==' ') i++;
   *x=*x+i; i=0;
   while ( (s[*x+i]>='A') && (s[*x+i]<='z') ) { prem[i]=s[*x+i];i++; }
   prem[i]='\0';
   syntax=zarads(syntax,prem);
   while ( (s[*x+i]==',') || (s[*x+i]==' ') ) i++;
 }
 
 *x=*x+i;
 if (s[*x]==';') return(0);
	    else return(1);
}
 
int podmienka ( char s[] , int x , def_syntax *prvys )
{
def_syntax *syntax;
 
 syntax=prvys;
 x=x;s=s;
 return(0);
}
 
void compile ( void )
{
def_riadok *riadok;
def_syntax *posled;
def_error  *error;
void *prvys;
int  poc,x,y,caka,i,v_rade,oldi;
char chyba[maxerr];
 
 syntax=NULL;
 error =NULL;
 riadok=prvy;
 
 for (poc=0; poc<maxkl; poc++)
 {
    syntax=zarads(syntax,klslov[poc]);
    if (poc==0)
       prvys=syntax;
 }
 
 posled=syntax;
 syntax=prvys;
 v_rade=-1;
 caka=0;
 oldi=0;
 
 for (y=1;y<=pocr;y++)
 {
   x=1;
   if ((i=patri( (*riadok).znaky,x,&v_rade,prvys,caka)) >x)
      x=i;
   else {
      if (caka==-1) error=zarade(error,"Nepoznam",y);
	       else error=zarade(error,klslov[caka],y);
      v_rade=caka;
   }
 
   if ((caka==-1) && (v_rade>maxkl)) caka=10;
   if (v_rade==9) caka=-1;
   if (v_rade==10)
     if ((i=aritmetika( (*riadok).znaky,x,posled)) >x) { x=i;caka=9; }
	else error=zarade(error,klslov[caka],y);
 
   if (v_rade==11)
     if ((i=podmienka( (*riadok).znaky,x,posled)) >x) { x=i;caka=12; }
	else error=zarade(error,klslov[caka],y);
 
   if ((v_rade==6) || (v_rade==7))
      if ((i=patri( (*riadok).znaky,x,&v_rade,posled,caka))>x)  { x=i;caka=9; }
	 else error=zarade(error,klslov[caka],y);
 
   if (v_rade==3) caka=11;
   if (v_rade==2) caka=-1;
   if (v_rade==1) {
      i=premenne( &x,(*riadok).znaky,posled);
      if (i!=0) error=zarade(error,"Zle definovanie premennych.",y);
      i=oldi+1;
      caka=2;
   }
 
   if (v_rade==0) caka=1;
   if (x>=strlen( (*riadok).znaky)-1 ) { riadok=(*riadok).zani;oldi=-1; }
   if (i==oldi) y=pocr;
   oldi=i;
 }
 
 if (v_rade!=7)
    error=zarade(error,klslov[7],y);
 
 if (error==NULL)
    comp=1;
}
 
 
// nastavenia
void option ( void )
{
}
 
 
// polozi otazku a caka odpoved Ano/Nie
int  otazka ( char text[], char pr[], char dr[], char tr[])
{
int  vo=0,odx,i,x;
char pdt[3][10];
int  cpdt[3];
char ch;
 
 strcpy(pdt[0],pr);
 strcpy(pdt[1],dr);
 strcpy(pdt[2],tr);
 
 if ((strlen(text)/2)!=(1.00*strlen(text)/2))
    text=strcat(text," ");
 
 odx=(80-strlen(text))/2-4;
 okno(odx,10,strlen(text)+8,6,LIGHTGRAY,DARKGRAY);
 gotoxy(5,2);cprintf("%s",text);
 
 cpdt[0]=(strlen(text)-odx-strlen(pdt[0])+strlen(pdt[1])+strlen(pdt[2])+8)/2+4;
 cpdt[1]=cpdt[0]+strlen(pdt[0])+2;
 cpdt[2]=cpdt[0]+strlen(pdt[0])+strlen(pdt[1])+4;
 
 for (i=0;i<=2;i++) {
   gotoxy(cpdt[i],4);
   tprintf(pdt[i]);
 }
 
 textbackground(GREEN);
 gotoxy(cpdt[0],4);tprintf(pdt[0]);
 
 odx=0; vo=-1;
 do {
   ch=getch();
   textbackground(LIGHTGRAY);
   gotoxy(cpdt[odx],4);tprintf(pdt[odx]);
 
   switch (ch) {
     case 0:
	  ch=getch();
	  switch (ch) {
	     case LEFT : odx=odx-1; if (odx<0) odx=2;break;
	     case RIGHT: odx=odx+1; if (odx>2) odx=0;break;
	  }
 
	  if ((odx==2) && (strcmp(pdt[2],"")==0)) odx=0;
	  if ((odx==1) && (strcmp(pdt[1],"")==0)) odx=0;
	  break;
 
     case ESC: vo=0;     break;
     case ENTER: vo=odx+1; break;
 
     default :
       for (i=0;i<=2;i++)
	 for (x=1;x<=strlen(pdt[i]);x++)
	   if ((pdt[i-1][x]=='^') && (pdt[i][x]==ch)) vo=i;
     break;
   }
 
   textbackground(GREEN);
   gotoxy(cpdt[odx],4);tprintf(pdt[odx]);
 }
 while (vo==-1);
 
 return(vo);
}