Umiestnenie súboru www.TrSek.com/c/compiler.c
// 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);
}

Copyrigth by Zdeno Sekerak 2007, http://www.trsek.com