Реализация синтаксического блока. Применение конечного автомата, страница 4

            ExeOp();

   }else

   if(symbol>=BEGTBL && symbol<=ENDTBL){

            FPRT;NS;

            if (symbol == EQ) {

                FPRT1(ASGN); NS;

                Expr();

                if (symbol == SCOL){

                          FPRT; NS;

                }else ErrMes("Нет ; в операторе присваивания");

            } else ErrMes("Нет знака = в операторе присваивания");

            ExeOp();

   }

}

void ListIO(void){

   if(symbol>=BEGTBL && symbol<=ENDTBL){

            FPRT;NS;

            if (symbol == COMMA) {

                FPRT;NS;

                ListIO();

            }

   } 

}

void Expr(void){

}

А теперь более общий случай с дополнительными проверочными действиями

и с обработкой файлов .lex и .snt

//

#include <stdio.h>

#include <string.h>

. . .

enum Term {TTL=1,END,Int,REAL,Input,OUTPUT};

enum Delim {COMMA=10,SCOL,COLON,EQ,ASGN,LBR,RBR};

#define BEGTBL 31

#define ENDTBL 59

#define BEGLIT  60

#define ENDLIT  99

#define FPRT  fprintf(out,"%02d ",symbol);pos=sprintf(postr,"%02d ",symbol);postr+=pos

#define FPRT1(x)  fprintf(out,"%02d ",x);pos=sprintf(postr,"%02d ",x);postr+=pos

#define NS symbol=NextSymb()

. . .

void Snt(void);

int NextSymb (void);

void DclOp(void);

void Title(void);

void End(void);

void List(void);

void ListIO(void);

void ExeOp(void);

void End(void);

void Expr(void);

FILE *in, *out;

int symbol;     //для хранения кода текущей лексемы

char buf[255]; //буфер для чтения очередной строки из файла

char *pbuf;     //текущая позиция очередной лексемы

int lerr=0;   //количество ошибок лексического блока

int serr=0;   //количество ошибок синтаксического блока

int ilst; //номер строки файла с лексемами

char ostr[255], *postr;            //буфер для выходной строки в Form4

int pos; //смещение для конечной позиции в выходной строке в Form4

char ErrStr[255];

//Головная процедура

  char lname[255],sname[255];

. . . 

  fnsplit(StatusBar1->Panels->Items[0]->Text.c_str(),0,0,lname,0);

  fnsplit(StatusBar1->Panels->Items[0]->Text.c_str(),0,0,sname,0);

  strcat(lname,".lex");

  strcat(sname,".snt");

  out=fopen(lname,"w");

  TBL->code=-1;

  LIT->code=-1;

  lerr=0;

  Form1->Memo2->Clear();  Form3->Memo1->Lines->Clear();

  for ( i=0; i<Memo1->Lines->Count;i++) lex(i+1,Memo1->Lines->Strings[i].c_str());

  Memo2->Visible=(lerr)?true:false;

  Form3->Show();

  fclose (out);

  if (lerr==0) {

      Form1->Memo2->Clear();

      Form4->Memo1->Clear();

      //синт. блок    

      in=fopen(lname,"r");

      out=fopen(sname,"w");

      ilst=1;

      postr=ostr;

      pos=0;

      serr=0;

      if ((pbuf=fgets(buf,80,in))!=NULL) {

            symbol=atoi(pbuf);

            Snt();

            Memo2->Visible=(serr)?true:false;

            Form4->Show();

            fclose (in);

            fclose (out);

      }

  }

}

int NextSymb (void){

    pbuf+=3;

    if (atoi(pbuf)) return (atoi(pbuf));

    fprintf(out,"00\n"); sprintf(postr,"00");

    Form4->Memo1->Lines->Add(ostr);

    ilst++;

    pos=0; postr=ostr;

    if ((pbuf=fgets(buf,80,in))==NULL) return -1;

    else  return (atoi(pbuf));

}

void ErrMes(int ns,char *s){

  char buf[80];

  serr++;

  sprintf(buf,"строка %d: %s",ns,s);

  Form1->Memo2->Lines->Add(buf);

}

void Snt(void){

   if (symbol==TTL) { FPRT; NS; }

   else ErrMes (ilst, "отсутствует заголовок программы");

   DclOp();

   ExeOp();

   if (symbol==END) { FPRT; NS; }

   else ErrMes (ilst, "отсутствует оператор окончания программы");

}

void SetType(int t){

   struct tbl *ptbl=TBL;

   while(ptbl->code!=-1){

             if (ptbl->type=-1) ptbl->type=(t==Int)?0:1;

      ptbl++:

   }      

}

void DclOp(void){

            if(symbol>=BEGTBL && symbol<=ENDTBL) {  

List();

 if (symbol == COLON){

                                    FPRT;NS;

                                    if (symbol == Int ||symbol == REAL ){

                                                SetType(symbol);                 

                                                FPRT;NS;

if (symbol == SCOL){

                                                      FPRT;NS;

      DclOp();

}else ErrMes(ilst,"нет ; в операторе объявления");

                                    }else ErrMes(ilst,"нет задания типа в операторе объявления");

                        } else ErrMes(ilst,"нет двоеточия в операторе объявления");

            }

}

void List(void){

   if(symbol>=BEGTBL && symbol<=ENDTBL){

            FndIdCode(symbol)->type=-1;

            if(FndIdCode(symbol)->dcl==0) FndIdCode(symbol)->dcl=1;

     else{

            sprintf(ErrStr,"идентификатор %s уже был объявлен", FndIdCode(symbol)->name);

             ErrMes(ilst, Errstr);

     }

     FPRT;NS;

     if (symbol == COMMA) {

            FPRT; NS();

List();

    }

  }

}

void ExeOp(void){

   if (symbol == Input){

            FPRT;NS;

            if (symbol == LBR){

               FPRT;NS;

               ListIO();

               if (symbol == RBR){

                        FPRT;NS;

                        if (symbol == SCOL){

                           FPRT;NS;

                        }else ErrMes(ilst,"нет ; в операторе INPUT");

               } else ErrMes(ilst,"нет закр.скобки в операторе INPUT");

            } else ErrMes(ilst,"нет открыв.скобки в операторе INPUT");

            ExeOp();

   }else

   if (symbol == OUTPUT){

            FPRT;NS;

            if (symbol == LBR){

               FPRT;NS;

               ListIO();

               if (symbol == RBR){

                        FPRT;NS;

                        if (symbol == SCOL){

                           FPRT;NS;

                        }else ErrMes(ilst,"нет ; в операторе OUTPUT");

               }else ErrMes(ilst,"нет закр.скобки в операторе OUTPUT");

            } else ErrMes(ilst,"нет открыв.скобки в операторе OUTPUT");

            ExeOp();

   }else

   if(symbol>=BEGTBL && symbol<ENDTBL){