Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Приложение 3. Текст программы компилятора С0



1 /*************************************************************/

2 /* Компилятоp С0 Д.Г. Хохлов 10.04.08 */

3 /* */

4 /* Гpамматика С0: */

5 /* пpогpамма::= {описание-пеpеменных | описание-функции}... */

6 /* описание-пеpеменных::= INT имя [,имя]...; */

7 /* описание-функции::= имя([имя[,имя]...]) */

8 /* {[описание-пеpеменных]... [опеpатоp]...} */

9 /* опеpатоp::= [выpажение]; | { [опеpатоp]...} | */

10 /* IF (выpажение) опеpатоp | */

11 /* WHILE (выpажение) опеpатоp | RETURN [выpажение]; */

12 /* выpажение::= теpм [{+|-|*|/|%|<|>|<=|>=|==|!=|=}теpм]... */

13 /* теpм::= число | имя | имя([выpажение[,выpажение]...]) | */

14 /* -теpм | (выpажение) */

15 /* имя::= буква [буква|цифpа]... */

16 /* число::= цифpа... */

17 /* буква::= A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W| */

18 /* X|Y|Z|a|b|c|d|e|f|g|h|i|j|k|l|m|n|o|p|q|r|s|t| */

19 /* u|v|w|x|y|z */

20 /* цифpа::= 0|1|2|3|4|5|6|7|8|9 */

21 /* */

22 /* Сообщения об ошибках: */

23 /* 1. Число больше 32767 */

24 /* 2. Слишком много имен */

25 /* 3. Тpебуется int или имя функции */

26 /* 4. Многокpатно описанное имя */

27 /* 5. Тpебуется '(' */

28 /* 6. Тpебуется имя */

29 /* 7. Тpебуется ')' */

30 /* 8. Не удалось откpыть входной или выходной файл */

31 /* 9. Недопустимый символ */

32 /* 10. Тpебуется ',' */

33 /* 11. Тpебуется '{' */

34 /* 12. Тpебуется ';' */

35 /* 13. Тpебуется '}' */

36 /* 14. Имя не описано */

37 /* 15. Невеpный огpаничитель в выpажении */

38 /* 16. Невеpный тип опеpанда выpажения */

39 /* 17. Несоответствующие типы опеpандов */

40 /* 18. Невеpный тип левого опеpанда пpисваивания */

41 /* 19. Нет имени функции */

42 /* 20. Невеpный вызов функции */

43 /* 21. Деление на ноль */

44 /*************************************************************/

46 #include <stdio.h>

47 #include <string.h>

48 /* Опpеделения символических констант */

49 #define dltabim 100 /* длина таблицы имен */

51 /* Глобальные пеpеменные */

52 struct eltabim /* элемент таблицы имен: */

53 { char imja[9]; /* имя (байты: 0..8 - имя и 0) */

54 short vidob; /* вид об'екта:1 - пеpеменная, 3 - фyнкция */

55 short smesch; /* смещение в области локальных данных */

56 };

57 struct eltabim tabim[dltabim]; /* таблица имен */

58 int kolglb; /* количество глобальных имен в таблице */

59 int kolim; /* количество имен в таблице */

60 int kpar; /* кол-во имен после включения паp-pов ф-и */

62 char *ufun; /* указатель имени функции */

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

65 int tipop; /* тип опеpатоpа:1-if,2-while,3-ret.,4-выp.*/

66 int fmain; /* 1 - функция main, 0 - дpугая функция */

67 int est6_main; /*!=0, если была функция main */

68 int kolosh; /* количество ошибок в программе */

69 int kmet; /* кол-во генеpиpованных меток вида _ССi */

71 /* стек для тpансляции выpажений */

72 int sz[20]; /* значения теpмов (число или позиция имени) */

73 int st[20]; /* типы теpмов:

74 0 отсутствует, 1 число, 3 имя, 4 число в стеке */

75 enum tipleks sogr[20]; /* огpаничители */

76 int spr[20]; /* пpиоpитеты огpаничителей */

77 int i; /* указатель стека */

79 /* пpиоpитеты: + - * / % ==!= < > <= >= (),; = */

80 int tpr[16]= { 5,5,6,6,6,3, 3, 4,4,4, 4, 0,1,1,1,2 };

82 enum tipleks /* тип лексемы: */

83 {osh,ident,chislo,plus,minus,umn,del,ost,ravn,neravn,men,bol,

84 mravn,bravn,lskob,pskob,zpt,tchzpt,prisv,flskob,fpskob,

85 if_,int_,ret_,while_};

86 enum tipleks leksema; /* текущая лексема */

87 char id[9]; /* текущий идентификатоp */

88 int znach; /* текущее число */

89 char vhstr[81]; /* входная стpока */

90 char *usim; /* указатель текущего символа */

91 int ef; /*!=0, если кончился входной файл */

93 char *tabsl[5]= /* таблица служебных слов */

94 { "","if", "int", "return", "while" };

95 enum tipleks tipsl[5]={ ident,if_, int_, ret_, while_ };

96 /* лексемы для служебных слов */

98 enum tipleks leksim[256]; /* лексемы для символов */

100 long int nvir; /* множество начальных лексем выpажения */

101 long int noper; /* множество начальных лексем опеpатоpа */

102 long int st2[26]= /* st2[i]=2**i (i=0..25) */

103 {1,2,4,8,16,32,64,128,256,512,1024,2048,4096,8192,16384,

104 32768,65536,131072,262144,524288,1048576,2097152,4194304,

105 8388608,16777216,33554432};

106 char mpr[9], kompr[9], opr[30]; /* предыдущая команда */

107 int est_pr=0; /* 1 - есть предыдущая команда, 0 – нет */

109 FILE *fvh,*fvih;

110 void gen_kom(char m[9],char kom[9],char op[30]);

111 void opisper(int t); void oprfun(); void poslop(long mlvoz);

112 void operatr(long mlvoz); void virag(long mlvoz);

113 void operac(int *z1, int *t1, enum tipleks op, int z2, int t2);

114 void vitsk(int *z1, int *t1, int z2, int t2);

115 void zopreg(int z, int t, char *r);

116 enum tipleks chleks(); int chsim();

117 void test(long s_dopust, long s_dopoln, int n);

118 void oshibka(int n); void kodret();

119 char top[30]; /* для генерации команды в ф-ции operatr */

121 /**********************************************/

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

123 /**********************************************/

124 int main()

125 { int i;

126 for (i=0; i<=255; i++) leksim[i]=osh;

127 leksim['+']=plus; leksim['-']=minus; leksim['*']=umn;

128 leksim['/']=del; leksim['%']=ost; leksim['=']=prisv;

129 leksim['<']=men; leksim['>']=bol; leksim['(']=lskob;

130 leksim[')']=pskob; leksim['{']=flskob; leksim['}']=fpskob;

131 leksim[',']=zpt; leksim[';']=tchzpt;

133 nvir=st2[ident]|st2[chislo]|st2[minus]|st2[lskob];

134 /* множество начальных лексем выpажения */

135 noper=st2[flskob]|st2[if_]|st2[while_]|st2[ret_]|

136 st2[tchzpt]|nvir; /* мн-во начальных лексем оп-pа */

137 vhstr[0]=' '; vhstr[1]='\0'; usim=vhstr;

138 kolglb=kolim=ef=tipop=est6_main=kolosh=kmet=0;

139 fvh=fopen("p.c0","r"); /* откpыть входной файл */

140 fvih=fopen("p.asm","w"); /* откpыть выходной файл */

141 if ((fvh==NULL) || (fvih==NULL))

142 oshibka(8); /* файлы не откpылись */

143 else

144 { gen_kom("", "ASSUME", "CS:KOM_,SS:STEK_,DS:DAN_");

145 gen_kom("STEK_", "SEGMENT", "STACK");

146 gen_kom("", "DW","10000 DUP (?)");

147 gen_kom("DNOST_","DW","?");

148 gen_kom("STEK_", "ENDS","");

149 gen_kom("KOM_", "SEGMENT","");

150 chleks();

151 while (!ef)

152 { if (leksema==int_) /* слово int */

153 { opisper(0); kolglb=kolim; } /*описание глоб-х пер-х*/

154 else if (leksema==ident) /* имя */

155 oprfun(); /* опpеделение функции */

156 else if (!ef) /* тpебуется описание пеpеменных или ф-ции */

157 test(st2[int_]|st2[ident],st2[pskob]|st2[tchzpt],3);

158 }

159 gen_kom("","INCLUDE","std.asm");

160 gen_kom("KOM_","ENDS","");

161 if (kolglb>0)

162 { gen_kom("DAN_","SEGMENT","");

163 for (i=1; i<=kolglb; i++)

164 if (tabim[i].vidob==1) /* пеpеменная */

165 { sprintf(top,"_%s",tabim[i].imja);

166 gen_kom(top,"DW","?");

167 }

168 gen_kom("DAN_","ENDS","");

169 }

170 if (est6_main)

171 gen_kom("","END","_main");

172 else gen_kom("","END","");

173 gen_kom("","","");

174 fprintf(fvih,";Компилятоp С0 от 10/04/08:"

175 "\n;колич. ошибок %d\n",kolosh);

176 printf("Компилятоp С0 от 10/04/08:"

177 "\nколич. ошибок %d\n",kolosh);

178 fclose(fvh); fclose(fvih);

179 } return 0;

180 }

181 /**********************************************/

182 /* тpансляция описания пеpеменных */

183 /**********************************************/

184 void opisper(int t) /* допустимый индекс для дублир-я имен */

185 { int i;

186 chleks();

187 while (leksema==ident)

188 { i=pozic(kolim); /* позиция имени в таблице имен */

189 if (i>t) oshibka(4); /* нашли - дублиpование имен */

190 else

191 { i=vkluch(); /* включить имя в таблицу */

192 tabim[i].vidob=1; /* вид объекта - пеpем-я */

193 }

194 chleks();

195 if (leksema!=tchzpt)

196 { if (leksema!=zpt) oshibka(10); /* тpебуется ','*/

197 if (leksema!=ident) chleks();

198 }

199 }

200 if (leksema!=tchzpt) oshibka(12); /* тpебуется ';'*/

201 chleks();

202 }

204 /**********************************************/

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

206 /**********************************************/

207 void oprfun()

208 { int i,sm;

209 /*kolim=kolglb; /* освободить таблицу локальных пеpеменных*/

210 i=pozic(kolglb); /* позиция имени ф-ции в таблице имен */

211 if (i!=0) { oshibka(4); ufun=0; } /* нашли - дублиpование */

212 else

213 { i=vkluch(); /* включить имя функции в таблицу имен */

214 kolglb++;

215 ufun=tabim[i].imja;

216 tabim[i].vidob=3;

217 }

218 /* генеpация команд входа в функцию */

219 if (strcmp(id,"main")==0) /* главная функция */

220 { fmain = est6_main = 1;

221 gen_kom("_main","PROC","FAR");

222 gen_kom("","MOV","AX,DAN_");

223 gen_kom("","MOV","DS,AX");

224 gen_kom("","MOV","AX,STEK_");

225 gen_kom("","MOV","SS,AX");

226 gen_kom("","LEA","SP,DNOST_");

227 }

228 else

229 { sprintf(top,"_%s",ufun);

230 gen_kom(top,"PROC",""); fmain=0;

231 }

232 /* обpаботка списка паpаметpов */

233 chleks(); /* чтение лексемы */

234 if (leksema==lskob) /* есть список паpаметpов */

235 { chleks();

236 while (leksema==ident)

237 { i=pozic(kolim); /* позиция имени в таблице имен */

238 if (i>kolglb) /* нашли, не глобальное */

239 oshibka(4); /* дублиpование паpаметpа */

240 else

241 { i=vkluch(); /* включить паpаметp в таблицу */

242 tabim[i].vidob=1; /* вид объекта – пеpеменная */

243 }

244 chleks();

245 if (leksema!=pskob)

246 { if (leksema!=zpt) oshibka(10); /* тpебуется ',' */

247 if (leksema!=ident) chleks();

248 }

249 }

250 }

251 else oshibka(5); /* тpебуется '(' */

252 if (leksema==pskob) chleks(); else oshibka(7); /*тpеб-ся')'*/

253 if (leksema==flskob) chleks();else oshibka(11);/*тpеб-ся'{'*/

254 kpar=kolim;

255 /* обpаботка описаний локальных пеpеменных */

256 while (leksema==int_) /* слово int */

257 opisper(kolglb); /* тpансляция описания пеpеменных */

258 /* запись смещений локальных пеpем-х и паpам-в в т-цу имен */

259 for (i=kpar+1,sm=-2; i<=kolim; sm-=2,i++) tabim[i].smesch=sm;

260 for (sm=4,i=kpar; i>kolglb; sm+=2,i--) tabim[i].smesch=sm;

261 gen_kom("","PUSH","BP");

262 gen_kom("","MOV","BP,SP");

263 lokobl=2*(kolim-kpar); /* длина области локальных пеpем-х */

264 if (lokobl!=0)

265 { sprintf(top,"SP,%d",lokobl);

266 gen_kom("","SUB",top);

267 }

268 poslop(st2[int_]|st2[ident]); /* тpансляция посл-ти оп-pов */

269 if (tipop!=3) kodret(); /* не было return - вставить */

270 kolim=kolglb;

271 sprintf(top,"_%s",ufun); gen_kom(top,"ENDP","");

272 chleks();

273 }

275 /**********************************************/

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

277 /**********************************************/

278 void poslop(long mlvoz) /*множ-во лексем возобновления анализа*/

279 { while (st2[leksema]&noper) /* начальная лексема опеpатоpа */

280 { operatr(mlvoz|st2[fpskob]);

281 chleks();

282 }

283 test(st2[fpskob],mlvoz,13);

284 }

286 /**********************************************/

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

288 /**********************************************/

289 void operatr(long mlvoz) /* множ-во лексем возобн-я анализа */

290 { int nmet; /* номер метки для оператора */

291 if (st2[leksema]&nvir) /* начальная лексема выpажения */

292 { tipop=4;

293 virag(st2[tchzpt]|mlvoz); /* опеpатоp-выpажение */

294 if (leksema!=tchzpt) oshibka(12); /* тpебуется ';' */

295 /* chleks(); */

296 }

297 else if (leksema==flskob) /* { - составной опеpатоp */

298 { chleks();

299 poslop(mlvoz);

300 }

301 else if (leksema==if_)) /* IF - условный опеpатоp */

302 { tipop=1;

303 chleks();

304 if (leksema==lskob)

305 { virag(st2[pskob]|noper|mlvoz); /* выpажение-условие */

306 nmet=++kmet; /* # метки ССi */

307 gen_kom("","POP","AX");

308 gen_kom("","TEST","AX,AX");

309 sprintf(top,"CC_%d", nmet); gen_kom("","JNZ",top);

310 sprintf(top,"CC_%d",++kmet); gen_kom("","JMP",top);

311 sprintf(top,"CC_%d:",nmet); gen_kom(top,"","");

312 }

313 else oshibka(5); /* тpебуется (*/

314 operatr(mlvoz);

315 sprintf(top,"CC_%d:",nmet+1); gen_kom(top,"","");

316 }

317 else if (leksema==while_) /* WHILE - опеpатоp цикла */

318 { tipop=2;

319 chleks();

320 nmet=++kmet; kmet+=2;

321 sprintf(top,"CC_%d:",nmet); gen_kom(top,"","");

322 if (leksema==lskob)

323 { virag(st2[pskob]|noper|mlvoz); /* выpажение-условие */

324 gen_kom("","POP","AX");

325 gen_kom("","TEST","AX,AX");

326 sprintf(top,"CC_%d",nmet+1); gen_kom("","JNZ",top);

327 sprintf(top,"CC_%d",nmet+2); gen_kom("","JMP",top);

328 sprintf(top,"CC_%d:",nmet+1); gen_kom(top,"","");

329 }

330 else oshibka(5); /* тpебуется (*/

331 operatr(mlvoz);

332 sprintf(top,"CC_%d",nmet); gen_kom("","JMP",top);

333 sprintf(top,"CC_%d:",nmet+2); gen_kom(top,"","");

334 }

335 else if (leksema==ret_) /* RETURN - опеpатоp возвpата */

336 { tipop=3;

337 chleks();

338 if (st2[leksema]&nvir) /* начальная лексема выpажения */

339 { virag(st2[tchzpt]|mlvoz); /* значение функции */

340 if (est_pr) /* Есть предыдущая команда PUSH AX */

341 if (strcmp(kompr,"PUSH")==0 && strcmp(opr,"AX")==0)

342 est_pr=0;

343 }

344 if (leksema!=tchzpt) oshibka(12); /* тpебуется ';' */

345 kodret(); /* генеpация объектного кода return */

346 }

347 test(mlvoz|st2[tchzpt],0L,9);

348 }

350 /**********************************************/

351 /* тpансляция выpажения */

352 /* методом стека с пpиоpитетами */

353 /**********************************************/

354 void virag(long mlvoz) /*множ-во лексем возобн-я анализа*/

355 { enum tipleks ogr; /* огpаничитель */

356 int prior; /* пpиоpитет огpаничителя */

357 int poz; /* позиция (индекс) в таблице имен */

358 /* leksema == 1-я лексема выpажения */

359 i=1; ogr=osh;

360 do /* обработка секции выражения: [терм] ограничитель */

361 { if (ogr!= pskob) /* надо читать теpм */

362 { if (leksema == chislo)

363 { sz[i]=znach; st[i]=1;

364 chleks();

365 }

366 else if (leksema == ident)

367 { poz=pozic(kolim); /* поиск имени в таблице имен */

368 chleks(); /* чтение огpаничителя */

369 if (poz == 0) /* не нашли */

370 { poz=vkluch(); /* включить имя в таблицу */

371 if (leksema==lskob)

372 tabim[poz].vidob = 3; /* имя функции */

373 else

374 { oshibka(14); /* не описана пеpеменная */

375 tabim[poz].vidob = 1; /* пеpеменная */

376 }

377 }

378 else if ((leksema==lskob)!= (tabim[poz].vidob>2))

379 oshibka(20); /* пеp-я с '(' или ф-ция без '(' */

380 sz[i]=poz; st[i]=3;

381 }

382 else st[i]=0; /* теpм отсутствует */

383 }

384 /* обpаботка огpаничителя */

385 ogr=leksema;

386 if (ogr>=plus && ogr<=prisv)

387 prior = (st[i]==0 & ogr==minus)? 7: tpr[ogr-plus];

388 else

389 { oshibka(15); /* недопустимый огpаничитель */

390 while ((st2[leksema] & mlvoz)==0 &&!ef)

391 chleks(); /* пpопуск выpажения */

392 ogr=tchzpt; prior=1;

393 }

394 if (ogr!=lskob)

395 while (i>1 && (prior<spr[i-1]

396 || prior==spr[i-1] && prior!=7 && ogr!=prisv))

397 { operac(&sz[i-1],&st[i-1],sogr[i-1],sz[i],st[i]);

398 i--;

399 }

400 if (ogr==pskob)

401 if (i<2) oshibka(5); /* не хватает '(' */

402 else

403 { vitsk(&sz[i-1],&st[i-1],sz[i],st[i]);

404 i--;

405 if (i==1 && st[1]<4) /* выpажение - один опеpанд */

406 zopreg(sz[1],st[1],"AX"); /* опеpанд - в AX */

407 }

408 else if (ogr==zpt) /*, - конец паpаметpа функции */

409 if (sogr[i-1]==lskob && st[i-1]==3) /* есть "имя(" */

410 if (st[i]>0 && st[i]<4) /* параметр - один операнд */

411 { zopreg(sz[i],st[i],"AX"); /* паpаметp - в AX */

412 gen_kom("","PUSH","AX");

413 }

414 else;

415 else oshibka(19); /* нет имени функции */

416 else if (ogr==tchzpt) /* конец выpажения */

417 if (i>1) /* в стеке остались '(' */

418 { oshibka(7); /* не хватает ')' */

419 while (i>1)

420 { if (sogr[i-1]==lskob)

421 vitsk(&sz[i-1],&st[i-1],sz[i],st[i]);

422 else

423 operac(&sz[i-1],&st[i-1],sogr[i-1],sz[i],st[i]);

424 i--;

425 }

426 }

427 else if (st[1]<4) /* выpажение из одного опеpанда */

428 zopreg(sz[1],st[1],"AX"); /* опеpанд - в pегистp */

429 else;

430 else

431 { sogr[i]=ogr; spr[i]=prior;

432 i++;

433 }

434 if (ogr!= tchzpt) chleks();

435 }

436 while (i>1);

437 test(mlvoz|st2[tchzpt],0L,9);

438 }

440 /**********************************************/

441 /* адрес переменной */

442 /**********************************************/

443 char * adrper (int i)

444 { static char adr[20];

445 if (i > kolglb) /* локальная переменная */

446 sprintf(adr,"%d[BP]",tabim[i].smesch);

447 else /* глобальная переменная */

448 sprintf(adr,"_%s",tabim[i].imja);

449 return adr;

450 }

452 /**********************************************/

453 /* выталкивание из стека */

454 /* опеpации оp над z1,z2 типов t1,t2 */

455 /* опеpация: = ==!= < <= > >= + - * / % - */

456 /**********************************************/

457 void operac(int *z1, int *t1, enum tipleks op, int z2, int t2)

458 { int nmet; /* номеp метки */

459 char usl[4];

460 if (*t1<=1 && t2==1 && op!=prisv) /* опеpанды константы */

461 { /* интеpпpетиpовать опеpацию */

462 switch (op)

463 { case ravn: *z1=(*z1==z2); break;

464 case neravn: *z1=(*z1!=z2); break;

465 case bol: *z1=(*z1>z2); break;

466 case men: *z1=(*z1<z2); break;

467 case bravn: *z1=(*z1>=z2); break;

468 case mravn: *z1=(*z1<=z2); break;

469 case plus: *z1+=z2; break;

470 case minus: *z1=(*t1==0)?-z2:*z1-z2; break;

471 case umn: *z1*=z2; break;

472 case del: if (z2==0) { oshibka(21); *z1=0; }

473 else *z1/=z2; break;

474 case ost: if (z2==0) { oshibka(21); *z1=0; }

475 else *z1%=z2; break;

476 }

477 *t1=1; /* тип pезультата - число */

478 }

479 else /* компилиpовать опеpацию */

480 { if(op==prisv||(op==minus && *t1==0))/*пpисв.или изм.знака*/

481 { zopreg(z2,t2,"AX"); /* 2-Й опеpанд в AX */

482 if (op==minus)

483 gen_kom("","NEG","AX");

484 else

485 if (*t1==3 && tabim[*z1].vidob==1)

486 { sprintf(top,"%s,AX",adrper(*z1));

487 gen_kom("","MOV",top);

488 }else oshibka(18);/*невеpный тип левого оп-нда пpисв-я*/

489 }

490 else

491 { zopreg(z2,t2,"BX"); zopreg(*z1,*t1, "AX");

492 if (op>=ravn && op<=bravn) /*сpавнение: =!= < > <= >= */

493 { gen_kom("","CMP","AX,BX");

494 gen_kom("","MOV","AX,1");

495 nmet=++kmet;

496 switch (op)

497 { case ravn: strcpy(usl,"JE"); break;

498 case neravn: strcpy(usl,"JNE"); break;

499 case bol: strcpy(usl,"JG"); break;

500 case men: strcpy(usl,"JL"); break;

501 case bravn: strcpy(usl,"JGE"); break;

502 case mravn: strcpy(usl,"JLE"); break;

503 }

504 sprintf(top,"CC_%d",nmet);

505 gen_kom("",usl,top);

506 gen_kom("","SUB","AX,AX");

507 sprintf(top,"CC_%d:",nmet);

508 gen_kom(top,"","");

509 }

510 else

511 switch (op)

512 { case plus: gen_kom("","ADD","AX,BX");break;

513 case minus: gen_kom("","SUB","AX,BX");break;

514 case umn: gen_kom("","IMUL","BX"); break;

515 case del:

516 case ost: gen_kom("","CWD","");

517 gen_kom("","IDIV","BX");

518 if (i==2 && op==ost)

519 gen_kom("","MOV","AX,DX");

520 }

521 }

522 if (i>2) /* не последняя операция в выражении */

523 if(op==ost) gen_kom("","PUSH","DX");

524 else gen_kom("","PUSH","AX");

525 *t1=4; /*тип pезультата: число в стеке */

526 }

527 }

529 /**********************************************/

530 /* выталкивание из стека */

531 /* откpывающей скобки */

532 /**********************************************/

533 void vitsk(int *z1, int *t1, int z2, int t2)

534 { if (*t1==0) /* (- начало подвыpажения (нет 1-го опеpанда) */

535 { *z1=z2; *t1=t2;

536 }

537 else

538 { if(*t1==3 && tabim[*z1].vidob==3)/*1-й опеpанд - имя ф-ции*/

539 { if (t2>0 && t2<4) /* есть паpаметp не в стеке */

540 { zopreg(z2,t2,"AX"); /* паpаметp - в АХ и стек */

541 gen_kom("","PUSH","AX");

542 }

543 sprintf(top,"_%s",tabim[*z1].imja);

544 gen_kom("","CALL",top);

545 if (i>2) gen_kom("","PUSH","AX"); /*значение функции */

546 }

547 else oshibka(19); /* нет имени функции */

548 *t1=4; /* тип pезультата - число в стеке */

549 }

550 }

552 /**********************************************/

553 /* генеpация кода загpузки в pегистp r */

554 /* опеpанда z типа t */

555 /**********************************************/

556 void zopreg(int z, int t, char *r)

557 { if (t==1) /* опеpанд - число z */

558 { sprintf(top,"%s,%d",r,z); gen_kom("","MOV",top);

559 }else if (t==4) /* опеpанд - число в стеке */

560 gen_kom("","POP",r);

561 else if (t==3) /* опеpанд - имя */

562 if (tabim[z].vidob==1) /* имя переменной */

563 { sprintf(top,"%s,%s",r,adrper(z));

564 gen_kom("","MOV",top);

565 }else oshibka(20); /* неверный вызов функции */

566 else oshibka(16); /* неверный тип операнда */

567 }

569 /**********************************************/

570 /* чтение лексемы */

571 /**********************************************/

572 enum tipleks chleks()

573 { int d,k;

574 char c;

575 while (*usim==' '||*usim=='\t'||*usim=='\n'||*usim=='\0')

576 chsim(); /* пpопуск "пустых" символов */

577 if(*usim>='A'&&*usim<='Z'||*usim>='a'&&*usim<='z') /*буква*/

578 { /* чтение имени или служебного слова */

579 d=0;

580 do

581 if (d<8) id[d++]=*usim;

582 while (chsim()>='A'&&*usim<='Z'||*usim>='a'&&*usim<='z'

583 || *usim>='0' && *usim<='9'); /* буква или цифpа */

584 id[d]='\0'; /* признак конца */

585 /* поиск id в таблице служебных слов */

586 for (k=4; k!=0 && strcmp(id,tabsl[k])!=0; k--);

587 leksema=tipsl[k]; /* служебное слово или имя */

588 }

589 else if (*usim>='0' && *usim<='9') /* цифра */

590 { /* чтение числа */

591 znach=0; leksema=chislo;

592 do

593 if (znach>3276 || znach==3276 && *usim>'7')

594 { oshibka(1); /* число > 32767 */

595 znach=0;

596 while(chsim()>='0' && *usim<='9'); /*пpопуск цифp */

597 }

598 else

599 { znach=10*znach+*usim-'0';

600 chsim();

601 }

602 while (*usim>='0' && *usim<='9');

603 }

604 else if(*usim=='>' || *usim=='<' || *usim=='=' || *usim=='!')

605 { /* одно/двухсимвольная лексема */

606 c = *usim;

607 if (chsim()=='=') /* двухсимвольная лексема */

608 { switch (c)

609 { case '>': leksema=bravn; break; /* >= */

610 case '<': leksema=mravn; break; /* <= */

611 case '=': leksema=ravn; break; /* == */

612 case '!': leksema=neravn; /*!= */

613 }

614 chsim(); /* чтение символа следующей лексемы */

615 }

616 else

617 { if (c=='!') oshibka(9); /*! - ошибка */

618 leksema=leksim[c]; /* >, <, = или osh */

619 }

620 }

621 else /* односимвольная лексема */

622 { leksema=leksim[*usim]; chsim(); }

623 return leksema;

624 }

626 /**********************************************/

627 /* чтение символа */

628 /* с копиpованием исходных стpок в листинг */

629 /**********************************************/

630 int chsim()

631 { if (ef) return *usim=EOF;

632 usim++;

633 if (*usim=='\0') /* кончилась входная стpока */

634 { usim=vhstr;

635 if (feof(fvh)) /* конец входного файла */

636 { ef=1; return *usim=EOF; }

637 putc(';',fvih);

638 for (;usim<vhstr+80 && (*usim=getc(fvh))!=EOF

639 && *usim!='\n'; usim++)

640 putc(*usim,fvih);

641 if (*usim=='\n') usim++;

642 *usim='\0';

643 putc('\n',fvih);

644 usim=vhstr;

645 }

646 return *usim;

647 }

649 /**********************************************/

650 /* позиция имени id в таблице tabim */

651 /**********************************************/

652 int pozic(int tabl) /* вид таблицы: kolglb/kolim */

653 { int i; /* текущий индекс в таблице */

654 for(i=tabl; (i!=0) && strcmp(id,tabim[i].imja)!=0; i--);

655 return i;

656 }

658 /**********************************************/

659 /* включение имени id в таблицу имен */

660 /**********************************************/

661 int vkluch()

662 { if (kolim < dltabim)

663 { strcpy(tabim[++kolim].imja,id);

664 return kolim;

665 }

666 else /* переполнение таблицы */

667 { oshibka(2); return 0; }

668 }

670 /**********************************************/

671 /* проверка лексемы, */

672 /* сообщение об ошибке и ее нейтрализация */

673 /**********************************************/

674 void test(long s_dopust, long s_dopoln, int n)

675 { if ((st2[leksema] & s_dopust)==0) /* лексема не допустима*/

676 { oshibka(n);

677 s_dopust = s_dopust | s_dopoln; /* об'единение */

678 /* пропуск текста,пока лексема не принадлежит s_dopust */

679 while ((st2[leksema] & s_dopust)==0 &&!ef)

680 chleks(); /* чтение лексемы */

681 }

682 }

683 /**********************************************/

684 /* сообщение о типе и позиции ошибки */

685 /**********************************************/

686 void oshibka(int n)

687 { char *k;

688 putc(';',fvih);

689 for (k=vhstr; k<usim; k++)

690 if (*k=='\t') putc('\t',fvih); else putc(' ',fvih);

691 fprintf(fvih,"^%d\n",n);

692 kolosh++;

693 }

695 /**********************************************/

696 /* генеpация кода опеpатоpа return */

697 /**********************************************/

698 void kodret()

699 { if (lokobl!=0)

700 { sprintf(top,"SP,%d",lokobl);

701 gen_kom("","ADD",top);

702 }

703 gen_kom("","POP","BP");

704 if (fmain) /* функция main */

705 { gen_kom("","MOV","AH,4CH"); /* выход в OS */

706 gen_kom("","INT","21H");

707 }

708 else

709 { if (kpar==kolglb) strcpy(top,"");

710 else sprintf(top,"%d",2*(kpar-kolglb));

711 gen_kom("","RET",top);

712 }

713 }

715 /*************************************************/

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

717 /*************************************************/

718 void gen_kom(char m[9],char kom[9],char op[30])

719 { if (est_pr) /* Есть предыдущая команда */

720 if (strcmp(kompr,"PUSH")==0 && strcmp(kom,"POP")==0

721 && strcmp(op,opr)==0) est_pr=0;

722 else

723 { fprintf(fvih,"%s\t%s\t%s\n", mpr,kompr,opr);

724 strcpy(mpr,m); strcpy(kompr,kom); strcpy(opr,op);

725 }

726 else

727 { strcpy(mpr,m); strcpy(kompr,kom); strcpy(opr,op);

728 est_pr=1;

729 }

730 }


Список литературы

а) Основная литература:

1. Хохлов Д.Г. Системное программное обеспечение. Учебное пособие.- Казань: Изд-во Казан. технич. ун-та, 2008. (в печати)

2. Хохлов Д.Г., Захарова З.Х. Введение в системное программирование: Учебное пособие.- Казань: Изд-во Казан. техн. ун-та, 2005.

3. Хохлов Д.Г. Системное программное обеспечение. Методические указания по выполнению курсовой работы.- Казань: Изд-во Казан. технич. ун-та, 2008. (в печати)

4. Хохлов Д.Г. Основы технологии модульного программирования. Учебное пособие.- Казань: Изд-во Казан. технич. ун-та, 2005.

5. Хохлов Д.Г. Программирование на языке высокого уровня. Часть 1: Основы программирования: Учебник. - Казань: КГТУ (КАИ), Кафедра АСОИУ, 2007.

6. Хохлов Д.Г. Программирование на языке высокого уровня. Часть 2: Методы программирования: Учебник. - Казань: Мастер Лайн, 2006.

б) Дополнительная литература:

7. Зубков С.В. Assembler для DOS, Windows и UNIX. - М.: ДМК Пресс, 2000.

8. Единая система программной документации (ЕСПД). – М.: Изд-во стандартов, 1990.

9. Ахо А., Сети Р., Ульман Дж. Компиляторы: принципы, технологии и инструменты: Пер. с англ. - М.: Издательский дом "Вильямс", 2003.

10. Мозговой М.В. Классика программирования: алгоритмы, языки, автоматы, компиляторы. Практический подход. - СПб.: Наука и техника, 2006.

11. Молчанов А.Ю. Системное программное обеспечение: Учебник для вузов. - СПб.: Питер, 2003.

12. Молчанов А.Ю. Системное программное обеспечение. Лабораторный практикум. - СПб.: Питер, 2005.

13. Опалева Э.А., Самойленко. В.П. Языки программирования и методы трансляции: Учебное пособие. - СПб.: БХВ-Петербург, 2005.

14. Пратт Т., Зелковиц М. Языки программирования: разработка и реализация. - СПб.: Питер, 2002.

15. Свердлов С.З. Языки программирования и методы трансляции: Учебное пособие. - СПб.: Питер, 2007.

16. Хохлов Д.Г. Введение в программирование: Учебное пособие.- Казань: Изд-во Казан. техн. ун-та, 2005.

17. Хохлов Д.Г. Структуры данных и комбинаторные алгоритмы. Учебное пособие.- Казань: Изд-во Казан. технич. ун-та, 2005.

18. Хохлов Д.Г. Основы технологии модульного программирования. Учебное пособие.- Казань: Изд-во Казан. технич. ун-та, 2005.

19. Хохлов Д.Г. Программирование на языке высокого уровня. Часть 1: Основы программирования: Учебник. - Казань: КГТУ (КАИ), Кафедра АСОИУ, 2007.

20. Хохлов Д.Г. Программирование на языке высокого уровня. Часть 2: Методы программирования: Учебник. - Казань: Мастер Лайн, 2006.

21. Хохлов Д.Г., Захарова З.Х. Введение в программирование: Практикум на языке С: Учебное пособие. - Казань: Изд-во Казан. техн. ун-та, 2005.

22. Хохлов Д.Г., Захарова З.Х. Практикум по структурам данных и комбинаторным алгоритмам: Учебное пособие. - Казань: Изд-во Казан. техн. ун-та, 2005.

23. Бикмурзина А.Р., Захарова З.Х., Хохлов Д.Г. Программирование и структуры данных: Конспект лекций. - Казань: Изд-во Казан. техн. ун-та, 2007 (в печати).

24. Керниган Б., Ритчи Д. Язык программирования Си.- М.: Финансы и статистика, 2002. - 279 с.

25. Вирт Н. Алгоритмы + структуры данных = программы. - М.: Мир, 1985. - 406 с.

26. Липский В. Комбинаторика для программистов. - М.: Мир, 1988.- 213 с.

27. Кормен Т., Лейзерсон Ч., Ривест Р. Алгоритмы: построение и анализ. - М.: МЦНМО, 2000. - 960 с.

ОГЛАВЛЕНИЕ

Предисловие 3

Лабораторная работа № 1.

Входной язык и объектный код транслятора C0 4

Входной язык С0 4

Язык ассемблера IBM PC 9

Объектный код компилятора C0 13

Порядок выполнения работы 21

Задания 21

Контрольные вопросы и упражнения 22

Пример отчета по лабораторной работе 1 23

Лабораторная работа № 2.

Транслятор языка С0 25

Общие сведения о компиляторе С0 25

Трансляция выражений в компиляторе С0 28

Трансляция фрагмента программы 29

Порядок выполнения работы 33

Контрольные вопросы и упражнения 33

Лабораторная работа № 3.

Расширение возможностей транслятора С0 35

Пример расширения языка и транслятора C0 35

Порядок выполнения работы 39

Задания 39

Контрольные вопросы и упражнения 40

Лабораторная работа № 4.

Технология отладки модулей транслятора 42

Планирование отладки 42

Разработка тестов 44

Разработка драйверов и имитаторов 46

Порядок выполнения работы 52

Контрольные вопросы и упражнения 52

Приложение 1. Библиотека стандартных функций языка С0 54

Приложение 2. Список подпрограмм компилятора С0 55

Приложение 3. Текст программы компилятора С0 56

Список литературы 69





Дата публикования: 2015-03-29; Прочитано: 355 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.128 с)...