Program ktorý demoštruje ako funguje compiler

Delphi & Pascal (česká wiki)
Přejít na: navigace, hledání
Kategórie: Programy v C, C++

Program: Compiler.c
Soubor exe: Compiler.exe
Potřebné: Klavesy.hStruct.h
Příklady: Prog.c

Program ktorý demoštruje ako funguje compiler. Má IDE prostredie so všetkými potrebnými funkciami. Program vie odhaliť syntaktické chyby programu nevie kompilovať do exe tvaru. Zdrojový kód ktorý kompiluje je akási obdoba Pascalu.
// 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);
}