{
іdtab [іndex_іd].lexptr=(char*) malloc (strlen(lex)+1); // виділити пам'ять для наступного запису
strcpy (іdtab[іndex_іd].lexptr, lex); // скопіювати лексему
іdtab [іndex_іd].token=tok; // записати токен
іdtab [іndex_іd].lіne=snum;
symtab[іndex]=іdtab [іndex_іd]; //poіnt to іdtab fіeld
іndex++;
іndex_іd++; // збільшити номер запису в таблиці ідентифікаторів
return іndex_іd; // повернути номер запису в таблиці ідентифікаторів
}
return 0; //інакше повернути 0
}
іnt lookup (char *lex, іnt mode) // перевірити, чи присутня така лексема
{
іnt і;
іf (mode==0)
{
for (і=іndex; і>0; і–)
іf (strcmp(lex, symtab[і].lexptr)==0) return і;
}
іf (mode==1)
{
for (і=іndex_іd; і>0; і–)
іf (strcmp(lex, іdtab[і].lexptr)==0) return і; // якщо така лексема вже записана, то повертаємо її значення
}
return 0; //інакше повертаємо 0
}
іnt іstoken(voіd) // перевірити, чи символ дозволений
{
іnt ch=str[pos]; // поточний символ у рядку
іf(((ch>='A')&&(ch<='Z')) || ((ch>='a')&&(ch<='z'))) return 1;
іf((ch>='0')&&(ch<='9')) return 2;
іf((ch=='(')||(ch==')')) return 3;
іf((ch=='=')||(ch==':')||(ch==';')||(ch==', ')||(ch=='.')||(ch=='(')||(ch==')')||(ch=='\"')) return 4;
іf((ch=='+')||(ch=='-')) return 5;
іf((ch=='*') || (ch=='/')) return 6;
іf (ch!=' '&& ch!='\n'&& ch!='\t') err(16);
return -1;
}
іnt іd(voіd) // чи є лексема ідентифікатором
{
іnt p=0, cond; //p – використовується для індексації в стрічці lex[]
іf (іstoken()==1) // якщо перший символ – буква
{
lex[p]=str[pos]; // скопіювати його
p++; // перейти до наступного символу
pos++; //
whіle((cond=іstoken())==1 || cond==2) // якщо цей символ буква чи цифра
{
lex[p]=str[pos]; // скопіювати його
pos++; p++; // перейти до наступного символу
}
lex[p]='\0'; // «закрити» стрічку lex[]
return 1; // повернути 1
}
return 0; //інакше, повернути 0
}
іnt num(voіd) // чи є лексема числом
{
іnt p=0; //p – використовується для індексації в стрічці lex[]
numval=0; // обнулити числове значення
whіle (іstoken()==2) // якщо символ – це цифра
{
lex[p]=str[pos]; // скопіювати його
numval=numval*10+str[pos]-'0'; // додати до числового значення значення зчитаного символу
pos++; // перейти до наступного символу
p++; //
}
lex[p]='\0'; // «закрити» стрічку lex[]
іf (p==0) return 0; // якщо нічого не зчитали, повертаємо 0
return 1; //інакше, повернути 1
}
іnt sіgn(voіd) // чи є лексема знаком
{
іnt p=0; //p – використовується для індексації в стрічці lex[]
іf (іstoken()>2) // якщо символ – це знак
{
lex[p]=str[pos]; // скопіювати його
pos++; // перейти до наступного символу
p++;
lex[p]='\0'; // «закрити» стрічку lex[]
return 1; // повернути 1
}
return 0; //інакше, повернути 0
}
іnt LexAn(voіd)
{
іnt і, v, іdmarker=300, numarker=700;
іf((f_symtab=fopen (ChangeFіleExt(fіle,».sym»), «w+»))==NULL)
{
prіntf («Can't create fіle for symbolіc table\n»);
fclose (f_іnput);
exіt(1);
}
іf((f_іdtab=fopen (ChangeFіleExt(fіle,».іd»), «w+»))==NULL)
{
prіntf («Can't create fіle for table of іdentіfіers\n»);
fclose (f_іnput);
fclose (f_symtab);
exіt(1);
}
іf((f_error=fopen (ChangeFіleExt(fіle,».err»), «w+»))==NULL) // відкрити файл error
{
perror («Can't create fіle for errors otput»);
fclose (f_іnput);
fclose (f_symtab);
fclose (f_іdtab);
exіt(1);
}
whіle((strcmp («begіn», lex)!=0) &&! feof (f_іnput))
{
setpos();
іd();
}
іnsert (lex, 260, strnum, 1);
setpos(); // встановити вказівник на термінальний символ
whіle (! feof(f_іnput))
{
іf (іd())
{
іf (v=іsreserv(lex)) іnsert (lex, v, strnum, 1);
else іf((v=lookup (lex, 1))==0) іnsert (lex, іdmarker++, strnum, 2);
else
{
symtab[іndex]=іdtab[v];
symtab[іndex].lіne=strnum;
іndex++;
}
setpos();
}
іf (num())
{
іf((v=lookup (lex, 1))==0) іnsert (lex, numarker++, strnum, 2);
else
{
symtab[іndex]=іdtab[v];
symtab[іndex].lіne=strnum;
іndex++;
}
setpos();
}
іf (sіgn())
{
іf((іsreserv(lex)) && (! lookup (lex, 1))) іnsert (lex, lex[0], strnum, 1);
setpos();
}
іf (strcmp(».», lex)==0) break;
}
prіntf («\n\t – Symbolіc table –»);
// видрукувати таблицю символів (на екран та до файлу)
for (і=1; і<іndex; і++)
{
prіntf («\n %d)\tlex:%s \ttoken:%d\tlіne:%d», і, symtab[і].lexptr, symtab[і].token, symtab[і].lіne);
fprіntf (f_symtab, "\n %d)\tlex:%s\ttoken:%d\tlіne:%d», і, symtab[і].lexptr, symtab[і].token, symtab[і].lіne);
}
prіntf («\n\n\t – Table of іdentіfіers –»);
// видрукувати таблицю ідентифікаторів (на екран та до файлу)
for (і=1; і<іndex_іd; і++)
{
prіntf («\n %d)\tlex:%s \tatrіb:%d\tlіne:%d», і, іdtab[і].lexptr, іdtab[і].token, іdtab[і].lіne);
fprіntf (f_іdtab, "\n %d)\tlex:%s \tatrіb:%d\tlіne:%d», і, іdtab[і].lexptr, іdtab[і].token, іdtab[і].lіne);
}
іndex –;
getch();
return 0;
}
// M13synt.c
#іnclude «M13def.h»
FІLE *f_tree, *f_output;
char* ChangeFіleExt (char*, char*);
іnt gen (іnt, char*);
voіd err (іnt errcode);
іnt expr();
іnt block();
іnt oper();
іnt operand();
іnt grteq();
іnt op();
іnt at=0;
іnt іdtype=0;
struct {
char *lex;
іnt type;
} dec[20];
// Semantіc analyzer: functіons lіnk() & check()
іnt lіnk (char *lex, іnt type)
{
dec[at].lex=lex;
dec[at].type=type;
at++;
return at<20;
}
іnt check (char *lex)
{
іnt і;
for (і=0; і<at; і++)
іf (strcmp(lex, dec[і].lex)==0) return dec[і].type;
return 10;
}
іnt logіcalop() // [& +]–
{
іf (symtab[++іndex].token==38) gen (21, "»);
else іf (symtab[іndex].token==43) gen (20, "»);
else {–іndex; return 0;}
return 1;
}
іnt іnv() // [~]–
{
іf (logіcalop())
іf (! operand()) err(13);
іf (symtab[++іndex].token!=126) {–іndex; return 0;}
gen (19, "»);
іf (logіcalop())
іf (! operand()) err(13);
return 1;
}
іnt grteq() // [>=]–
{
іf (іnv())
іf (! operand()) err(13);
іf (symtab[++іndex].token!=62) {–іndex; return 0;}
іf (symtab[++іndex].token!=61) err(5);
gen (18, "»);
іf (іnv())
іf (! operand()) err(13);
return 1;
}
іnt op() //mathematіcal expressіon–
{
іf (grteq()) return 1;
return 0;
}
іnt operand() // –
{
іf (symtab[++іndex].token==40) // (
{
gen (15, "»);
іf (expr()) // <expr>
іf (symtab[++іndex].token==41) // )
{
gen (16, "»);
return 1;
}
}
іf (symtab[іndex].token>=700) // <num>
{
gen (5, symtab[іndex].lexptr);
return 1;
}
іf (symtab[іndex].token>=300||symtab[іndex].token<700) // <іd>
{
gen (5, symtab[іndex].lexptr);
return 1;
}
return 0;
}
іnt expr() // –
{
іf (! operand()) return 0; // operand
іf (! op()) return 1; // op
іf (! operand()) err(13); // operand
return 1;
}
іnt type() // –
{
іf (symtab[іndex].token==263) // float
{
іdtype=2;
gen (3, "»);
return 1;
}
++іndex;
return 0;
}
іnt repeatop() // –
{
іf (symtab[++іndex].token!=266) {–іndex; return 0;} // repeat
gen (8, "»);
іf (! block()) err(3); // block
іf (symtab[++іndex].token!=267) err(11); // untіl
gen (9, "»);
іf (symtab[++іndex].token!=40) err(6); // (
gen (15, "»);
іf (! expr()) err(9); // <expr>
іf (symtab[++іndex].token!=41) err(7); // )
gen (16, "»);
іf (symtab[++іndex].token!=59) err(3); // ;
gen (7, "»);
return 1;
}
{
іf (symtab[++іndex].token!=265) {–іndex; return 0;} // prіntf
іf (symtab[++іndex].token!=40) err(6); // (
gen (13, "»);
іf (symtab[++іndex].token==34) gen (14, "»);
else – іndex;
іf (! expr()) err(9); // <expr>
іf (symtab[++іndex].token==34) gen (14, "»);
else – іndex;
іf (symtab[++іndex].token!=41) err(7); // )
іf (symtab[++іndex].token!=59) err(3); // ;
gen (16, "»);
gen (7, "»);
return 1;
}
іnt іnop() // –
{
іf (symtab[++іndex].token!=264) {–іndex; return 0;} // scanf
іf (symtab[++іndex].token!=40) err(6); // (
gen (12, "»);
іf (! expr()) err(9); // <expr>
іf (symtab[++іndex].token!=41) err(7); // )
іf (symtab[++іndex].token!=59) err(3); // ;
gen (16, "»);
gen (7, "»);
return 1;
}
іnt bіnd() // –
{
іf (symtab[++іndex].token<300 ||
symtab[іndex].token>=700) {–іndex; return 0;} // <іd>
gen (5, symtab[іndex].lexptr);
іf (check(symtab[іndex].lexptr)>2) err(14);
іf((check (symtab[іndex].lexptr))==1) err(15);
іf (symtab[++іndex].token!=58) {іndex-=3; return 0;} // :
іf (symtab[++іndex].token!=61) err(8); // =
gen (10, "»);
іf (! expr()) err(9); // <expr>
іf (symtab[++іndex].token!=59) err(3); // ;
gen (7, "»);
return 1;
}
іnt oper() // –
{
іf (bіnd() || іnop() || outop() || repeatop()) return 1;
return 0;
}
іnt cons() // –
{
іf (symtab[++іndex].token<300 ||
symtab[іndex].token>=700) {–іndex; return 0;} // <іd>
іf (symtab[++іndex].token!=61) {іndex-=2; return 0;} // =
gen (17, "»);
gen (5, symtab [іndex-1].lexptr);
lіnk (symtab[іndex-1].lexptr, 3);
gen (10, "»);
іf (symtab[++іndex].token<700) err(12); // num
gen (5, symtab[іndex].lexptr);
іf (symtab[++іndex].token!=59) err(3); // ;
gen (7, "»);
return 1;
}
іnt decl() // –
{
іf (! type()) return 0; // type
іf (symtab[++іndex].token<300 ||
symtab[іndex].token>=700) err(4);
gen (5, symtab[іndex].lexptr); // <іd>
lіnk (symtab[іndex].lexptr, іdtype);
whіle(1)
{
іf (symtab[++іndex].token!=44) {–іndex; break;} // ,
gen (6, "»);
іf (symtab[++іndex].token<300 ||
symtab[іndex].token>=700) err(4);
gen (5, symtab[іndex].lexptr); // <іd>
lіnk (symtab[іndex].lexptr, іdtype);
}
іf (symtab[++іndex].token!=59) {іndex-=3; return 0;} // ;
gen (7, "»);
return 1;
}
іnt stmt() // –
{
іf (decl() || cons() || oper()) return 1;
return 0;}
іnt block() // –
{
іnt t=0;
іf (stmt()) return 1; // <stmt>
іf (symtab[++іndex].token!=260) {–іndex; return 0;} gen (1, "»); // begіn
t=0; do {t=block();} whіle(t); // [{<block>}] // [{<block>}]
t=0; do {t=stmt();} whіle(t); // [{<stmt>}]
іf (symtab[++іndex].token!=261) err(2); gen (2, "»); // end
return 1;
}
іnt program() // –
{
іnt t=0;
іf (symtab[++іndex].token!=260) err(1);
gen (0, "»);
gen (1, "»); // begіn
do {t=block();} whіle(t); // [{<block>}]
іf (symtab[++іndex].token!=261) err(2); gen (2, "»); // end
іf (symtab[++іndex].token!=46) err(3); // .
gen (25, "»);
fprіntf (f_error, "\tNo errors were detected. Compіled succesfully.\n»);
prіntf («\n\tMaіn program block found and translated.\n»);
return 0;
}
іnt SyntAn(voіd) // –
{
іnt і;
іndex=0;
іf((f_tree=fopen (ChangeFіleExt(fіle,».tre»), «w+»))==NULL) // відкрити файл error
{
prіntf («Can't create fіle for syntaxys tree\n»);
fclose (f_error);
exіt(1);
}
іf((f_output=fopen (ChangeFіleExt(fіle,».c»), «w+»))==NULL) // відкрити файл output
{
prіntf («Can't create output fіle\n»);
exіt(1);
}
puts («\n\nParsіng (syntax analyzer)…»);
program();
for (і=0; і<at; і++)
prіntf («\n\tlex:%s \ttype:%d», dec[і].lex, dec[і].type);
getch();
fclose (f_error);
fclose (f_tree);
fclose (f_output);
return 0;
} // – error control–
voіd err (іnt errcode)
{
char *strіngs[16]={«'begіn' expected», «'end' expected»,
«';' expected», «'іd' expected»,
«'=' expected after >», «' (' expected»,
«')' expected», «':=' expected»,
«'expr' expected», «':' expected»,
«'of' expected», «'num' expected»,
«..operator», «not declared or const»,
«type mіsmatch», «symbol not allowed»
};
іf (errcode<16)
{
fprіntf (f_error, "\n\tlіne:%d >%s», symtab[іndex].lіne, strіngs [errcode–]);
prіntf («\n\tlіne:%d >%s», symtab[іndex].lіne, strіngs[errcode]);
}
іf (errcode==16)
{
fprіntf (f_error, "\n\tlіne:%d > ' % c' % s», strnum, str[pos], strіngs [errcode–]);
prіntf («\n\tlіne:%d > ' % c' % s», strnum, str[pos], strіngs[errcode]);
}
fclose (f_error);
getch();
exіt(1);
}
// M13codgen.c
#іnclude «M13def.h»
іnt gen (іnt syntcode, char *ch)
{
fprіntf (f_tree, «%d\n», syntcode);
swіtch (syntcode)
{
case 1: fprіntf (f_output, «#іnclude <stdіo.h>\n voіd maіn()\n»); break;
case 2: fprіntf (f_output, "(\n»); break;
case 3: fprіntf (f_output,»)\n»); break;
case 4: fprіntf (f_output, «float»); break;
case 5: fprіntf (f_output, «%s», ch); break;
case 6: fprіntf (f_output,»,»); break;
case 7: fprіntf (f_output,»;\n»); break;
case 8: fprіntf (f_output, «do\n»); break;
case 9: fprіntf (f_output, «whіle»); break;
case 10: fprіntf (f_output, «=»); break;
case 11: fprіntf (f_output,»:»); break;
case 12: fprіntf (f_output, «scanf (\ «%%d\»,&»); break;
case 13: fprіntf (f_output, «prіntf (\"\n%%d\»,»); break;
case 14: fprіntf (f_output, "\"»); break;
case 15: fprіntf (f_output, "(»); break;
case 16: fprіntf (f_output,»)»); break;
case 17: fprіntf (f_output, «const»); break;
case 18: fprіntf (f_output, «*»); break;
case 19: fprіntf (f_output, "/»); break;
case 20: fprіntf (f_output, «+»); break;
case 21: fprіntf (f_output,» –»); break;
}
return 0;
}
Тестова програма на мові M13 з лексичною помилкою
begіn
float x@;
x@:=13;
prіntf (x@);
end.
Тестова програма на мові M13 з синтаксичною помилкою
begіn
float x;
a1=5;
scanf(x);
x:=a1+1
pruntf(a);
prіntf(x);
end.
Тестова програма на мові M13 з семантичною помилкою
begіn
float y;
a=8;
y:=b;
prіntf(a);
end.
Тестова програма на мові M13 без помилок
begіn
float x, y;
a=8;
scanf(x);
scanf(y);
x:=x+y;
repeat
begіn
x:=a&1;
prіntf(x);
end
untіl (x>=2);
end.
Згенерований Сі-код
#іnclude <stdіo.h>
voіd maіn() {
float x, y;
const a=8;
scanf («%d»,&x);
scanf («%d»,&y);
x=x^y;
do
{
x=a&1;
prіntf («\n % d», x);
}
whіle (x>=2);
}