Языки программирования и трансляторы.Синтаксический анализатор с использованием одного из табличных методов, страница 5

if(operation==6 && (state==80 || state==81)) //встретили op1+op2 в присваивании

{

fprintf(out,"add ax,%s ;add operands\n",lexem); //складываем операнды, результат - в ax

fprintf(out,"mov [bx],ax ;write to variable\n",lexem); //помещаем результат по адресу присваиваимой переменной

}

if(operation==5 && (state==80 || state==81)) //встретили op1-op2 в присваивании

{

fprintf(out,"sub ax,%s ;subtract operands\n",lexem); //вычитаем операнды, результат - в ax

fprintf(out,"mov [bx],ax ;write to variable\n",lexem); //помещаем результат по адресу присваиваимой переменной

}

if(state==79) //встретили op1 в присваивании

{

fprintf(out,"mov [bx],ax ;write to variable\n",while_level);

}

if(state==90) //встретили op1 в условии

{

fprintf(out,"test ax,ax\n"); //проверяем результат на равенство нулю

fprintf(out,"jz end%d%d\n",while_level,while_number);

fprintf(out,";body of the loop\n");

}

if(while_level && (state==33 || state==43 || state==53 || state==61)) //генерируем остальную часть кода для всех вложенных while

{

while(while_level) //заканчиваем все while

{

fprintf(out,";end of the loop\n");

fprintf(out,"jmp start%d%d\n",while_level,while_number); //переход на проверку условия

fprintf(out,"\n\tend%d%d: ;end of while\n",while_level,while_number); //метка конца цикла

while_level--;

}

while_number++;

}

if(state==29 || state==39 || state==49 || state==57) //встретили начало операции присваивания

{

fprintf(out,"mov bx,offset %s ;beginning of id=A;\n",lexem); //в bx помещаем адрес левой части присваивания

}

if(state==71 || state==73) //встретили начало присваиваемого выражения

{

fprintf(out,"mov ax,%s ;first operand\n",lexem); //в ax помещаем значение переменной или константы

}

fflush(out);

}

//--------------------------------------------------------------------------void syntax_analyzer::print_error(FILE *out){

if(state==2 || state==7 || state==5 || state==10)fprintf(out,"\nОжидается while или присваивание!\n");

if(state==24)fprintf(out,"\nОжидается идентификатор или константа!\n");

if(state==26 || state==36 || state==47 || state==55)fprintf(out,"\nОжидается (!\n");

if(state==65 || state==69)fprintf(out,"\nОжидается )!\n");

if(state==65 || state==69)fprintf(out,"\nОжидается )!\n");

else fprintf(out,"\nНеопознанная ошибка!\n");

}

//--------------------------------------------------------------------------void syntax_analyzer::analyze(char *filein,char *fileout){

FILE *in,*out;

int b,c;

int i,tmp,tmp2;

int type; //тип лексемы, определяется номером таблицы

in=fopen(filein,"r");

out=fopen(fileout,"w");

fscanf(in,"%d %d %d %19s",&type,&b,&c,lexem);

generate_code(out);

while(!feof(in) && !error)//до конца файла или до ошибки

{

if(accepted)

{

fscanf(in,"%d %d %d %s",&type,&b,&c,lexem); //если предыдущая лексема обработана, считать следующую

accepted=0;

}

if(!feof(in))

{

//type: 1 - переменная 2- константа, 3 - ключевое слово, 4 - разделитель

//переменная, ищем id в списке терминалов, до 5 терминалов

tmp=(type==1);

for(i=0,tmp2=0;i<TERMINAL_NUM;i++)tmp2=tmp2 || strcmp("id\0",analyze_table[state].terminals[i])==0;

tmp=tmp && tmp2;

//константа, ищем const в списке терминалов

for(i=0,tmp2=0;i<TERMINAL_NUM;i++)tmp2=tmp2 || strcmp("const\0",analyze_table[state].terminals[i])==0;

tmp=tmp || (tmp2 && type==2);

//ключевое слово или разделитель, проверяем буквальное совпадение по списку терминалов

for(i=0,tmp2=0;i<TERMINAL_NUM;i++)tmp2=tmp2 || strcmp(lexem,analyze_table[state].terminals[i])==0;

tmp=tmp || tmp2;

if(tmp) //если текущая лексема есть в списке терминалов текущего состояния

{

if(analyze_table[state].accept)accepted=1; //можно ли принять текущую лексему?

if(analyze_table[state].ret) //если только что закончили вывод нетерминала

{

if(stack[0]) //если стек не пуст

{

state=stack[0]; //переходим к состоянию из стека

for(i=0;stack[i]!=0;i++)stack[i]=stack[i+1]; //обновляем стек

}

}

else //иначе переходим к состоянию из поля jump

{

if(analyze_table[state].stack) //если требуется положить следующее состояние в стек

{

//обновляем стек

i=0;

while(stack[i]!=0)i++;

for(;i>0;i--) stack[i+1]=stack[i];