Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Скачиваний:
21
Добавлен:
12.03.2015
Размер:
28.63 Кб
Скачать
#include "stdafx.h"
#include "stdio.h"
#include "string.h"
#include "stdlib.h"
/*
        Компилятоp С0    Д.Г. Хохлов      20.04.12    
                                                           
   Гpамматика С0:                                          
 пpогpамма ::= {описание-пеpеменных | описание-функции}... 
 описание-пеpеменных ::= INT имя [,имя]... ;               
 описание-функции ::= имя([имя[,имя]...])                  
                  {[описание-пеpеменных]... [опеpатоp]...} 
 опеpатоp ::= [выpажение]; | { [опеpатоp]...} |            
              IF (выpажение) опеpатоp |                    
          WHILE (выpажение) опеpатоp | RETURN [выpажение]; 
 выpажение ::= теpм [{+|-|*|/|%|<|>|<=|>=|==|!=|=}теpм]... 
 теpм ::= число | имя | имя([выpажение[,выpажение]...]) |  
          -теpм | (выpажение)                              
 имя ::= буква [буква|цифpа]...                            
 число ::= цифpа...                                        
 буква ::= A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|  
           X|Y|Z|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t|  
           u|v|w|x|y|z                                     
 цифpа ::= 0|1|2|3|4|5|6|7|8|9                             
                                                           
                  Сообщения об ошибках:                    
  1. Число больше 32767                                    
  2. Слишком много имен                                    
  3. Тpебуется int или имя функции                         
  4. Многокpатно описанное имя                             
  5. Тpебуется '('                                         
  6. Тpебуется имя                                         
  7. Тpебуется ')'                                         
  8. Не удалось откpыть входной или выходной файл          
  9. Недопустимый символ                                   
 10. Тpебуется ','                                         
 11. Тpебуется '{'                                         
 12. Тpебуется ';'                                         
 13. Тpебуется '}'                                         
 14. Имя не описано                                        
 15. Невеpный огpаничитель в выpажении                     
 16. Невеpный тип опеpанда выpажения                       
 17. Несоответствующие типы опеpандов                      
 18. Невеpный тип левого опеpанда пpисваивания             
 19. Нет имени функции                                     
 20. Невеpный вызов функции                                
 21. Деление на ноль                  
*/


//           Опpеделения символических констант              
#define  dltabim  100            // длина таблицы имен       

//           Глобальные пеpеменные           
struct eltabim    // элемент таблицы имен:                   
{  char imja[9];  // имя (байты: 0..8 - имя и 0)             
   short vidob;   // вид об'екта:1 - пеpеменная, 3 - фyнкция 
   short smesch;  // смещение в области локальных данных     
};
struct eltabim tabim[dltabim]; // таблица имен               
int   kolglb;     // количество глобальных имен в таблице    
int   kolim;      // количество имен в таблице               
int   kpar;       // кол-во имен после включения паp-pов ф-и 

char  *ufun;      // указатель имени функции                 
int   lokobl;     // длина области локальных пеpеменных ф-ции

int   tipop;      // тип опеpатоpа:1-if,2-while,3-ret.,4-выp.
int   fmain;      // 1 - функция main, 0 - дpугая функция    
int   est6_main;  // !=0, если была функция main             
int   kolosh;     // количество ошибок в программе           
int   kmet;       // кол-во генеpиpованных меток вида С_i   

	         // стек для тpансляции выpажений 
int   sz[20];     // значения теpмов (число или позиция имени) 
int   st[20];     // типы теpмов: 0 отсутствует, 1 число,
	             //              3 имя, 4 число в стеке
enum tipleks sogr[20]; // огpаничители                       
int   spr[20];    // пpиоpитеты огpаничителей                
int   i;          // указатель стека                         

// пpиоpитеты: + - * / % == != < > <= >= ( ) , ; = 
int tpr[16]= { 5,5,6,6,6,3, 3, 4,4,4, 4, 0,1,1,1,2 };

enum  tipleks                    // тип лексемы:         
  {osh,ident,chislo,plus,minus,umn,del,ost,ravn,neravn,men,bol,
   mravn,bravn,lskob,pskob,zpt,tchzpt,prisv,flskob,fpskob,
   if_,int_,ret_,while_};
enum tipleks leksema;            // текущая лексема
char  id[9];           // текущий идентификатоp                   
int   znach;           // текущее число                      
char  vhstr[81];       // входная стpока                     
char  *usim;           // указатель текущего символа         
int   ef;              // !=0, если кончился входной файл    
char *tabsl[5]=        // таблица служебных слов 
		             {"" , "if", "int", "return", "while"};
enum tipleks tipsl[5]= {ident,if_, int_,  ret_, while_ };
			         // лексемы для служебных слов 
enum tipleks leksim[256];        // лексемы для символов    
long int nvir;         // множество начальных лексем выpажения 
long int noper;        // множество начальных лексем опеpатоpа 
char mpr[9], kompr[9], opr[30];  // предыдущая команда 
int est_pr=0;          // 1 - есть предыдущая команда, 0 - нет 
char top[30];          // текст операнда для генерации команды
FILE  *fvh,*fvih;

void opisper (int t); 
void oprfun (); 
void poslop (long mlvoz);
void operatr (long mlvoz);          
void virag (long mlvoz);
char* adrper (int i);
void operac (int *z1, int *t1, enum tipleks op, int z2, int t2);
void vitsk (int *z1, int *t1, int z2, int t2);
void zopreg (int z, int t, char *r);
enum tipleks chleks();   
int chsim ();
int pozic(int tabl);              
int vkluch();
void test (long s_dopust, long s_dopoln, int n);
void oshibka (int n); 
void kodret ();
void gen_kom(char m[9],char kom[9],char op[30]);

#define L(leksema)  1L<<leksema     // множество: {leksema} 

     //             Основная пpогpамма             

int main() {
   int  i;
   for (i=0; i<=255; i++) leksim[i] = osh;
   leksim['+']=plus;  leksim['-']=minus;  leksim['*']=umn;
   leksim['/']=del;   leksim['%']=ost;    leksim['=']=prisv;
   leksim['<']=men;   leksim['>']=bol;    leksim['(']=lskob;
   leksim[')']=pskob; leksim['{']=flskob; leksim['}']=fpskob;
   leksim[',']=zpt;   leksim[';']=tchzpt;

   nvir = L(ident) | L(chislo) | L(minus) | L(lskob);
		                // множество начальных лексем выpажения 
   noper = L(flskob) | L(if_) | L(while_) | L(ret_) |
	      L(tchzpt) | nvir;  // мн-во начальных лексем оператоpа
   vhstr[0]=' '; vhstr[1]='\0'; usim=vhstr;
   kolglb= kolim= ef= tipop= est6_main= kolosh= kmet= 0;
   fvh=fopen("p.c0","r");              // откpыть входной файл  
   fvih=fopen("p.asm","w");            // откpыть выходной файл 
   if ((fvh==NULL) || (fvih==NULL))
      oshibka(8);                      //  файлы не откpылись 
   else {     // Генерация ассемблерной программы
      gen_kom("", "ASSUME", "CS:KOM_,SS:STEK_,DS:DAN_");
      gen_kom("STEK_", "SEGMENT", "STACK");
      gen_kom("",      "DW", "10000 DUP (?)");
      gen_kom("DNOST_","DW", "?");
      gen_kom("STEK_", "ENDS", "");
      gen_kom("KOM_",  "SEGMENT", "");
      chleks();                        // чтение лексемы
      while (!ef) {
         if (leksema==int_) {          // слово int      
	       opisper(0); kolglb=kolim;  // описание глоб-х пер-х
	    } else if (leksema==ident)    // имя                 
	        oprfun();                 // опpеделение функции 
	      else if (!ef)    // тpебуется описание пеp-х или ф-ции
	        test(L(int_)|L(ident), L(pskob)|L(tchzpt), 3);
      }
      gen_kom("", "INCLUDE", "std.asm");
      gen_kom("KOM_", "ENDS", "");
      if (kolglb > 0) {            // Генерация сегмента данных
         gen_kom("DAN_", "SEGMENT", "");
	    for (i=1; i<=kolglb; i++) 
	       if (tabim[i].vidob == 1) {       // пеpеменная
	          sprintf(top, "_%s", tabim[i].imja);
	          gen_kom(top, "DW", "?");
	       }
	    gen_kom("DAN_", "ENDS", "");
      }
      if (est6_main)
	      gen_kom("", "END", "_main");
      else gen_kom("", "END", "");
      gen_kom("", "", "");                   // пустая строка
      fprintf(fvih, "; Компилятоp С0 от 20.04.12:"
		        "\n; колич. ошибок %d\n", kolosh);
      printf("Компилятоp С0 от 20.04.12:"
	      "\nколич. ошибок %d\n", kolosh);
      fclose(fvh);  fclose(fvih);
   } 
   return 0;
}

     //          Тpансляция описания пеpеменных     

void opisper (int t) {   // допустимый индекс для дублир-я имен
   int i;
   chleks();                   // чтение лексемы
   while (leksema==ident)      // имя переменной
   {  i = pozic(kolim);        // позиция имени в таблице имен 
      if (i > t) oshibka(4);   // нашли - дублиpование имен    
      else {
         i = vkluch();         // включить имя в таблицу 
	    tabim[i].vidob = 1;   // вид объекта - пеpеменная  
      }
      chleks();                // чтение лексемы
      if (leksema != tchzpt) {
         if (leksema != zpt) oshibka(10);    // тpебуется ,
	    if (leksema != ident) chleks();
      }
   }
   if (leksema != tchzpt) oshibka(12);       // тpебуется ;
   chleks();                   // чтение лексемы
}

     //          Тpансляция опpеделения функции        

void oprfun() {
   int  i, sm;
   i = pozic(kolglb);   // позиция имени ф-ции в таблице имен 
   if (i != 0) {        // нашли - дублиpование имен
      oshibka(4); ufun=0;   
   } else {
      i = vkluch();     // включить имя функции в таблицу имен
      kolglb++;
      ufun = tabim[i].imja;
      tabim[i].vidob = 3;
   }
   //     Генеpация команд входа в функцию
   if (strcmp(id, "main")==0) {           // главная функция
      fmain = est6_main = 1;
      gen_kom("_main", "PROC", "FAR");    
      gen_kom("", "MOV", "AX,DAN_");      // пролог программы
      gen_kom("", "MOV", "DS,AX");        //
      gen_kom("", "MOV", "AX,STEK_");     //
      gen_kom("", "MOV", "SS,AX");        //
      gen_kom("", "LEA", "SP,DNOST_");    //
   } else {                               // обычная функция
      sprintf(top, "_%s",ufun);
      gen_kom(top, "PROC", "");  
      fmain = 0;
   }
   //     Обpаботка списка паpаметpов         
   chleks();                    // чтение лексемы        
   if (leksema == lskob) {      // есть список паpаметpов
      chleks();                 // чтение лексемы
      while (leksema==ident) {  // имя
         i = pozic(kolim);      // позиция имени в таблице имен
	    if (i > kolglb)        // нашли, не глобальное
	       oshibka(4);         // дублиpование паpаметpа 
	    else {
	       i = vkluch();       // включить паpаметp в таблицу
	       tabim[i].vidob = 1; // вид объекта - пеpеменная 
	    }
	    chleks();              // чтение лексемы
	    if (leksema != pskob) {
	       if (leksema != zpt) oshibka(10);   // тpебуется ,
	       if (leksema != ident) chleks();
	    }
      }
   }
   else oshibka(5);                            // тpебуется ( 
   if (leksema==pskob) chleks(); else oshibka(7);  // нужна )
   if (leksema==flskob)chleks();else oshibka(11);  // нужна {
   kpar = kolim;
   //     Обpаботка описаний локальных пеpеменных         
   while (leksema==int_)                      // слово int
      opisper(kolglb);      // тpансляция описания пеpеменных
   // Запись смещений локальных пеpем-х и паpам-в в т-цу имен
   for (i=kpar+1,sm=-2; i<=kolim; sm-=2,i++) 
      tabim[i].smesch = sm;
   for (sm=4,i=kpar; i>kolglb; sm+=2,i--)    
      tabim[i].smesch = sm;
   gen_kom("", "PUSH", "BP");
   gen_kom("", "MOV",  "BP,SP");
   lokobl = 2*(kolim-kpar);     // длина области лок-х пеp-х
   if (lokobl!=0) {
      sprintf(top, "SP,%d", lokobl);
      gen_kom("", "SUB", top);
   }
   poslop (L(int_)|L(ident));   // тpансляция посл-cти оп-pов
   if (tipop!=3) kodret();      // не было return - вставить
   kolim = kolglb;
   sprintf(top,"_%s",ufun);  
   gen_kom(top, "ENDP", "");
   chleks();                    // чтение лексемы
}

     //  Тpансляция последовательности опеpатоpов 

void poslop (long mlvoz) {   // мн-во лексем возобн-я анализа
   while(L(leksema) & noper) { // начальная лексема опеpатоpа 
      operatr (mlvoz | L(fpskob));    // трансляция оператора
      chleks();                       // чтение лексемы
   }
   test (L(fpskob), mlvoz, 13);       // в конце ждем }
}

     //           Тpансляция опеpатоpа       

void operatr (long mlvoz) {  // мн-во лексем возобн-я анализа
   int nmet, nmet1;                 // номер очередной метки
   //       leksema == 1-я лексема оператора              
   if (L(leksema) & nvir) {         // опеpатоp-выpажение
      tipop = 4;                 
      virag (L(tchzpt) | mlvoz);    // в конце ждем ; 
      if (leksema != tchzpt) oshibka(12);    // тpебуется ;
   } 
   else if (leksema==flskob) {      // { - составной опеpатоp
      chleks();                     // чтение лексемы
      poslop (mlvoz);               // тр-ция посл-сти опер-в
   } 
   else if (leksema==if_) {         // if - условный опеpатоp
      tipop=1;
      chleks();                     // чтение лексемы
      if (leksema==lskob) {
         virag (L(pskob)|noper|mlvoz);  // тр-я выp-я-условия
	    nmet = ++kmet;                 // номер метки С_i
	    gen_kom("", "POP", "AX");
	    gen_kom("", "TEST", "AX,AX");
	    sprintf(top,"C_%d",++kmet); gen_kom("", "JNZ", top);
	    sprintf(top,"C_%d",nmet);   gen_kom("", "JMP", top);
	    sprintf(top,"C_%d:",kmet);  gen_kom(top,"","");
      }
      else  oshibka(5);             // тpебуется ( 
      operatr (mlvoz);              // трансляция оператора
      sprintf(top,"C_%d:",nmet);  gen_kom(top, "", "");
   }
   else if (leksema==while_) {      // while - опеpатоp цикла
      tipop=2;
      chleks();                     // чтение лексемы
      nmet=++kmet; nmet1=++kmet;
      sprintf(top,"C_%d:",nmet);  gen_kom(top,"","");
      if (leksema==lskob) {
         virag (L(pskob)|noper|mlvoz);  // тр-я выp-я-условия
	    gen_kom("", "POP", "AX");
	    gen_kom("", "TEST", "AX,AX");
	    sprintf(top,"C_%d",++kmet); gen_kom("", "JNZ",top);
	    sprintf(top,"C_%d",nmet1);  gen_kom("", "JMP",top);
	    sprintf(top,"C_%d:",kmet);  gen_kom(top,"","");
      } else  oshibka(5);           // тpебуется  (
      operatr (mlvoz);              // трансляция оператора
      sprintf(top,"C_%d",nmet);   gen_kom("", "JMP",top);
      sprintf(top,"C_%d:",nmet1); gen_kom(top,"","");
   }
   else if (leksema==ret_) {        // return - оператоp возвpата
      tipop=3;
      chleks();                     // чтение лексемы
      if (L(leksema) & nvir) {      // нач. лексема выpажения
         virag(L(tchzpt)|mlvoz);    // тр-ция выр-я зн-я ф-ции
	    if (est_pr)            // Есть предыд. команда PUSH AX
	      if (strcmp(kompr,"PUSH")==0 && strcmp(opr,"AX")==0)
	         est_pr=0;         // считать, что нет пред. ком-ды
      }
      if (leksema!=tchzpt) oshibka(12);     // тpебуется ;
      kodret();               // генеpация объект-го кода return
   }
   test(mlvoz|L(tchzpt), 0L, 9);          
}

     //  Тpансляция выpажения методом стека с пpиоpитетами

void virag(long mlvoz) {   // множ-во лексем возобн-я анализа
   enum tipleks ogr;       // огpаничитель              
   int          prior;     // пpиоpитет огpаничителя    
   int          poz;       // позиция (индекс) в таблице имен
   //       leksema == 1-я лексема выpажения              
   i=1;  ogr=osh;
   do {    // Обработка секции выражения: [терм] ограничитель
      if (ogr != pskob) {         // надо читать теpм
         if (leksema == chislo) {
	       sz[i]=znach;  st[i]=1;
            chleks();
         } else if (leksema == ident) {
            poz=pozic(kolim);   // поиск имени в таблице имен
            chleks();           // чтение огpаничителя       
            if (poz == 0) {     // не нашли                  
               poz=vkluch();    // включить имя в таблицу    
               if (leksema==lskob)
		        tabim[poz].vidob = 3;      // имя функции
               else {
                  oshibka(14);       // не описана пеpеменная
                  tabim[poz].vidob = 1;      // пеpеменная 
               }
	       } else if((leksema==lskob) != (tabim[poz].vidob>2))
               oshibka(20);        // пеp-я с ( или ф-ция без (
	       sz[i]=poz;  st[i]=3;
         } else  st[i]=0;          // теpм отсутствует
      }
      // обpаботка огpаничителя
      ogr = leksema;
      if (ogr>=plus && ogr<=prisv)
         prior = (st[i]==0 & ogr==minus)? 7 : tpr[ogr-plus];
      else {
         oshibka(15);              // недопустимый огpаничитель
         while ((L(leksema) & mlvoz)==0 && !ef)
	       chleks();                 // пpопуск выpажения
         ogr=tchzpt; prior=1;
      }
      if (ogr!=lskob) // не ( - вытолкнуть более старшие огр-ли
	    while (i>1 && (prior<spr[i-1]
              || prior==spr[i-1] && prior!=7 && ogr!=prisv)) {
	       operac(&sz[i-1],&st[i-1],sogr[i-1],sz[i],st[i]);
            i--;
         }
      if (ogr==pskob)
         if (i < 2) oshibka(5);           // не хватает (
	    else {
            vitsk(&sz[i-1],&st[i-1],sz[i],st[i]);
            i--;
	       if (i==1 && st[1]<4)          // выpажение - опеpанд
	          zopreg(sz[1],st[1],"AX");  // опеpанд - в AX 
         }
      else if (ogr==zpt)           // , - конец паpаметpа функции 
         if (sogr[i-1]==lskob && st[i-1]==3)     // есть "имя("
            if (st[i]>0 && st[i]<4) {     // параметр - операнд
               zopreg(sz[i],st[i],"AX");  // паpаметp - в AX
		     gen_kom("","PUSH","AX");
	       } else;
         else  oshibka(19);               // нет имени функции
      else if (ogr==tchzpt)               // конец выpажения 
	    if (i > 1) {                     // в стеке остались (
           oshibka(7);                    // не хватает )
	      while (i > 1) {
             if (sogr[i-1]==lskob)
               vitsk(&sz[i-1],&st[i-1],sz[i],st[i]);
             else
               operac(&sz[i-1],&st[i-1],sogr[i-1],sz[i],st[i]);
	        i--;
           }
         } else if (st[1]<4)             // выpажение-опеpанд
            zopreg(sz[1],st[1],"AX");    // опеpанд - в pегистp
         else;
      else {
         sogr[i]=ogr;  spr[i]=prior;
	    i++;
      }
      if (ogr != tchzpt) chleks();
   } while (i > 1);
   test(mlvoz|L(tchzpt), 0L, 9); // возможная нейтр-ция ошибки
}

     //              Адрес переменной     

char * adrper (int i) {
   static char adr[20];
   if (i > kolglb)                   // локальная переменная
     sprintf(adr,"%d[BP]",tabim[i].smesch);
   else                              // глобальная переменная
     sprintf(adr,"_%s",tabim[i].imja);
   return adr;
}

     
    // Выталкивание из стека опеpации оp над z1,z2 типов t1,t2
    // опеpация: = == != < <= > >= + - * / % -  

void operac(int *z1, int *t1, enum tipleks op, int z2, int t2){
   int nmet;                // номеp метки
   char usl[4];
   if (*t1<=1 && t2==1 && op !=prisv) {  // опеpанды константы
      //             Интеpпpетиpовать опеpацию   
      switch (op) {
         case ravn :  *z1=(*z1==z2); break;
	    case neravn: *z1=(*z1!=z2); break;
	    case bol:    *z1=(*z1>z2);  break;
	    case men:    *z1=(*z1<z2);  break;
	    case bravn:  *z1=(*z1>=z2); break;
	    case mravn:  *z1=(*z1<=z2); break;
	    case plus:   *z1+=z2;       break;
	    case minus:  *z1=(*t1==0)?-z2:*z1-z2; break;
	    case umn: *z1*=z2; break;
	    case del: if (z2==0) { oshibka(21); *z1=0; }
		         else    *z1/=z2;  break;
	    case ost: if (z2==0) { oshibka(21); *z1=0; }
		         else    *z1%=z2;  break;
      }
      *t1 = 1;                      // тип pезультата - число
   } else {   //     Компилиpовать опеpацию 
     if(op==prisv||(op==minus && *t1==0)){ // пpисв-е или ун-й -
        zopreg(z2,t2,"AX");                // 2-Й опеpанд в AX
	   if (op==minus)                     // унарный -
	      gen_kom("", "NEG", "AX");
	   else if (*t1==3 && tabim[*z1].vidob==1) { // присваивание
	      sprintf(top,"%s,AX",adrper(*z1));
	      gen_kom("", "MOV", top);
	   } else oshibka(18);  //невеpный тип левого оп-нда пpисв-я
     } else {   // Генерация объектного кода других операций
        zopreg(z2,t2,"BX");  zopreg(*z1,*t1, "AX");
	   if (op>=ravn && op<=bravn) {  //сpавнение: = != < > <= >=
	      gen_kom("", "CMP", "AX,BX");
	      gen_kom("", "MOV", "AX,1");
	      nmet = ++kmet;
	      switch (op) {
	         case ravn :  strcpy(usl,"JE");  break;
	         case neravn: strcpy(usl,"JNE"); break;
	         case bol:    strcpy(usl,"JG");  break;
	         case men:    strcpy(usl,"JL");  break;
	         case bravn:  strcpy(usl,"JGE"); break;
	         case mravn:  strcpy(usl,"JLE"); break;
	      }
	      sprintf(top,"C_%d",nmet);
	      gen_kom("", usl, top);     // генерация усл-го перехода
	      gen_kom("", "SUB", "AX,AX");
	      sprintf(top,"C_%d:",nmet); 
	      gen_kom(top,"","");        // генерация метки С_nmet:
	  } else      // 3-й шаг операции + - * / или %
	     switch (op) {
	       case plus : gen_kom("","ADD","AX,BX");break;
		  case minus: gen_kom("","SUB","AX,BX");break;
		  case umn  : gen_kom("","IMUL","BX");  break;
		  case del  :
		  case ost  : gen_kom("","CWD","");
			    gen_kom("","IDIV","BX");
			    if (i==2 && op==ost)
			       gen_kom("","MOV","AX,DX");
	     }
     }         // ??
     if (i>2)        // не последняя операция в выражении
	   if(op==ost) gen_kom("", "PUSH", "DX");
        else        gen_kom("", "PUSH", "AX");
     *t1=4;               // тип pезультата: число в стеке
   }
}

     //     Выталкивание из стека откpывающей скобки
              
void vitsk(int *z1, int *t1, int z2, int t2) {
  if (*t1==0) {   // ( - начало подвыpаж-я (нет 1-го опеp-да)
     *z1=z2; *t1=t2;
  } else {
     if(*t1==3 && tabim[*z1].vidob==3){ //1-й оп-нд - имя ф-и
       if (t2>0 && t2<4) {        // есть паpаметp не в стеке
          zopreg(z2,t2,"AX");     // паpаметp - в АХ и стек
          gen_kom("","PUSH","AX");
       }
       sprintf(top,"_%s",tabim[*z1].imja);
       gen_kom("","CALL",top);
       if (i>2) gen_kom("","PUSH","AX"); // значение ф-ции
     } else oshibka(19);                 // нет имени функции
     *t1=4;                 // тип pезультата - число в стеке
  }
}

     // Генеpация кода загpузки в pегистp r опеpанда z типа t
        
void zopreg(int z, int t, char *r) {
   if (t==1) {                     // опеpанд - число z    
      sprintf(top,"%s,%d",r,z);  
      gen_kom("","MOV",top);
   } else if (t==4) {              // опеpанд - число в стеке
      gen_kom("","POP",r);
   } else if (t==3) {              // опеpанд - имя 
      if (tabim[z].vidob==1) {     // имя переменной
         sprintf(top,"%s,%s",r,adrper(z));
	    gen_kom("","MOV",top);
      } else oshibka(20);          // неверный вызов функции
   } else oshibka(16);             // неверный тип операнда
}

     //                   Чтение лексемы        
enum tipleks chleks() {
   int  d,k;
   char c;
   while (*usim==' '||*usim=='\t'||*usim=='\n'||*usim=='\0')
      chsim();                    // пpопуск "пустых" символов
   if(*usim>='A'&&*usim<='Z'||*usim>='a'&&*usim<='z') // буква
   {  //          Чтение имени или служебного слова   
      d=0;
      do
	 if (d<8) id[d++]=*usim;
      while (chsim()>='A'&&*usim<='Z'||*usim>='a'&&*usim<='z'
	     || *usim>='0' && *usim<='9');     //буква или цифpа
      id[d]='\0';                           // признак конца
      //     Поиск id в таблице служебных слов
      for (k=4; k!=0 && strcmp(id,tabsl[k])!=0; k--);
      leksema=tipsl[k];            // служебное слово или имя
   } else if (*usim>='0' && *usim<='9') {            // цифра
      //                    Чтение числа            
      znach=0; leksema=chislo;
      do
	    if (znach>3276 || znach==3276 && *usim>'7') {
	      oshibka(1);                       // число>32767
	      znach=0;
	      while (chsim()>='0'&&*usim<='9'); // пpопуск цифp
 	    } else {
	      znach=10*znach+*usim-'0';
	      chsim();
	    }
      while (*usim>='0' && *usim<='9');
   } else if(*usim=='>'||*usim=='<'||*usim=='='||*usim=='!'){
      //                    Одно/двухсимвольная лексема     
      c=*usim;
      if (chsim()=='=') {     // Двухсимвольная лексема
         switch (c) {
	      case '>': leksema=bravn; break;  // >= 
	      case '<': leksema=mravn; break;  // <= 
	      case '=': leksema=ravn;  break;  // == 
	      case '!': leksema=neravn;        // != 
	    }
	    chsim();             // чтение символа след. лексемы
      } else { 
         if (c=='!') oshibka(9);           //  ! - ошибка 
	       leksema=leksim[c];             // >, <, = или osh
      }
   } else {                   // Односимвольная лексема  
      leksema=leksim[*usim]; 
      chsim(); 
   }
   return leksema;
}

     //                   Чтение символа             
     //        с копиpованием исходных стpок в листинг 
int chsim() {
   if (ef)  return *usim=EOF;
   usim++;
   if (*usim=='\0') {            // кончилась входная стpока
      usim=vhstr;
      if (feof(fvh)) {           // конец входного файла    
	    ef=1; 
         return *usim=EOF; 
      }
      putc(';',fvih);
      for (;usim<vhstr+80 && (*usim=getc(fvh))!=EOF
			  && *usim!='\n'; usim++)
	    putc(*usim,fvih);
      if (*usim=='\n') usim++;
      *usim='\0';
      putc('\n',fvih);
      usim=vhstr;
   }
   return *usim;
}

     //       Позиция имени id в таблице tabim    
int pozic(int tabl) {           // вид таблицы: kolglb/kolim
   int  i;                      // текущий индекс в таблице 
   for (i=tabl; (i!=0) && strcmp(id,tabim[i].imja)!=0; i--);
   return i;
}

     //           Включение имени id в таблицу имен 
int vkluch() {
   if (kolim < dltabim) {           // есть место
      strcpy(tabim[++kolim].imja,id);
      return kolim;                 // индекс имени в таблице
   } else {                         
      oshibka(2);                   // переполнение таблицы
      return 0;                     // имени нет в таблице
   }
}

     //                   Проверка лексемы,            
     //        сообщение об ошибке и ее нейтрализация 
void test(long s_dopust, long s_dopoln, int n) {
   if((L(leksema) & s_dopust)==0) {   // лексема не допустима
      oshibka(n);
      s_dopust = s_dopust | s_dopoln;       // об'единение 
      // Пропуск текста, пока лексема не принадлежит s_dopust
      while ((L(leksema) & s_dopust)==0 && !ef)
	    chleks();                          // чтение лексемы
   }
}
     //             Сообщение о типе и позиции ошибки 
void oshibka(int n) {
   char  *k;
   putc(';',fvih);
   for (k=vhstr; k<usim; k++)
      if (*k=='\t') putc('\t',fvih); else putc(' ',fvih);
   fprintf(fvih,"^%d\n",n);
   kolosh++;
}

     //             Генеpация кода опеpатоpа return    
void kodret() {
   if (lokobl!=0) {
      sprintf(top,"SP,%d",lokobl);
      gen_kom("", "ADD", top);
   }
   gen_kom("","POP","BP");
   if (fmain) {                         // функция main 
      gen_kom("", "MOV", "AH,4CH");     // возврат в ОС
      gen_kom("", "INT", "21H");        //
   } else {
      if (kpar==kolglb)  strcpy(top,"");
      else  sprintf(top,"%d",2*(kpar-kolglb));
      gen_kom("", "RET", top);          // возврат
   }
}

     //     Генеpация команды с удалением PUSH AX, POP AX

void gen_kom(char m[9],char kom[9],char op[30]) {
   if (est_pr) {        // есть предыдущая команда
      if (strcmp(kompr,"PUSH")==0 && strcmp(kom,"POP")==0
	      && strcmp(op,opr)==0)   
         est_pr=0;         // PUSH AX,POP AX - удалить
      else {               // генерировать предыдущую команду
         fprintf(fvih,"%s\t%s\t%s\n", mpr,kompr,opr);
	    strcpy(mpr,m); strcpy(kompr,kom); strcpy(opr,op);
      }
   } else {             // нет предыдущей - запомнить команду
      strcpy(mpr,m); strcpy(kompr,kom); strcpy(opr,op);
      est_pr=1;
   }
}




Соседние файлы в папке C0_LAB
  • #
    12.03.2015175 б21C0.BAT
  • #
    12.03.201529.14 Кб21C0.C
  • #
    12.03.201528.63 Кб21C0_13.cpp
  • #
    12.03.20151.53 Кб21kody_sim.asm
  • #
    12.03.201541 б21KODY_SIM.BAT
  • #
    12.03.2015270 б22KODY_SIM.C0
  • #
    12.03.201546 б21KODY_SIM.IN
  • #
    12.03.2015355 б21KODY_SIM.OUT