void param( )

{

exam (‘(‘);

if (lex!=’)’ )

{

exan (IDEN);

while (lex = =’,’)

{

get( );

exam (IDEN);

}

}

exam (‘)’);

return;

}

В соответствии с синтаксической диаграммой вначале проверяется, является ли прочитанная лексема левой скобкой ‘(‘. При совпадении в функции (‘)’). При совпадении в функции exam( ), как уже не раз подчеркивалось, вызывается get( ) и поставляет новую лексему. И если это не ’)’, то должна быть IDEN. И вновь-таки, если после проверки лексемы IDEN была прочитана лексема ‘,’, то в цикле идет exam (IDEN). После выхода из цикла лексема должна быть ‘)’, и никакая другая.

7 BODYbeginl (DCONST |DVARB) * STML endl

Функция bоdy( ) вызывается из dfunc( ) после param( ). Функция param( ) заканчивается вызовом exam(‘)’). Следовательно, в случае успешной проверки будет вызвана get( ) и появится новая лексема. Она должна быть BEGINL.

void body( )

{

exam (BEGINL);

while(lex = = INTL || lex = = CONSTL)

if (lex = = INTL) dvarb( );

else

dconst( );

stml( );

exam(ENDL);

return;

}

8 STML → STAT (‘;’ STAT)*

Перед вызовом stml( ) выполнялось dconst( ). В начале этой функции есть exam(‘;’). При успешной проверке вызывается get( ), и она возвращает новую лексему.

void stml( )

{

stat( );

while (lex = = ‘;’)

{

get( );

stat( );

}

return;

}

9 STAT iden ‘=’ EXPR |readl iden |pritl EXPR |retrl EXPR |ifl EXPR thenl STML endl |whilel EXPR dol STML endl

Перед вызовом stat( ) “свежая” лексема есть. В зависимости от ее значения идет разветвление по witch (lex).

НЕ нашли? Не то? Что вы ищете?

void stat( )

{

switch (lex)

{

case IDEN: get( ); exam (‘=’); expr( ); break;

case READL: get( ); exam (IDEN); break;

case PRITL: get( ); expr( ); break;

case RETRL: get( ); expr( ); break;

case IFL: get( ); expr( ); exam(THENL); stml( ); exam(ENDL); break;

case WHILEL: get( ); expr( ); exam(DOL); stml( ); exam(ENDL); break;

default: printf(“stat nst=%i \n”, nst);

}

return;

}

10 EXPR → [‘+’|’-’] TERM ((‘+’|’-’)TERM)*

//“Свежая” лексема есть

void expr( )

{

if (lex = = ‘+’ || lex = = ‘-‘)

get( ); term( );

while (lex = = ‘+’ || lex = = ‘-‘)

{

get( );

term( );

}

return;

}

6 Пояснения к выполнению курсовой работы

Постановка задачи. Составить программу на Си для лексического анализа программы на модифицированном языке SPL. Вывести в файл "getrez. dan" и на экран таблицу идентификаторов и их адресов.

Программа на модифицированном языке SPL (вычисляет xy)

exp(a, b)

begin int z;

z=1;

while b do

if b%2 then z=z*a end;

a=a*a;b=b/2

end;

return z

end

main()

begin int x, y;

read x;

read y;

print exp(x, y)

end

#include<stdio. h>

#include<stdlib. h>

#include<ctype. h>

#include<conio. h>

#include<alloc. h>

#include<string. h>

/*Коды лексем языка SPL*/

enum{BEGINL=257,ENDL, IFL, THENL, WHILEL, DOL, RETRL, READL, PRITL, INTL, CONSTL, IDEN, NUMB};

int nst=0;

int lval, lex;

static char nch='\n';

FILE*PF,*padres;

void get(void);

void number(void);

void word(void);

char*add(char*nm);

void main(int ac, char*av[])

{

clrscr();

if(!ac)

puts("Hет исходного файла");

PF=fopen(av[1],"r");

padres=fopen("getrez. dan","w");

if(!PF)

puts("Файл не открывается");

else

get();

}

void get()

{

while(nch!=EOF)

{

while(isspace(nch))

{

if(nch=='\n')

nst++;

nch=getc(PF);

}

if(isdigit(nch))

number();

else

if(isalpha(nch))

word();

else

if(nch=='('||nch==')'||nch==','||nch==';'||nch=='='||nch=='+'||nch=='-'||nch=='*'||nch=='/'||nch=='%')

{

lex=nch;

nch=getc(PF);

}

}

if(nch==EOF)

lex=EOF;

else

puts("Hедопустимый символ");

return;

}

void number()

{

for(lval=0;isdigit(nch);nch=getc(PF))

lval=lval*10+nch-'0';

lex=NUMB;

return;

}

void word()

{

static int cdl[]={BEGINL, ENDL, IFL, THENL, WHILEL, DOL, RETRL, READL,

PRITL, INTL, CONSTL, IDEN, NUMB};

static char*serv[]={"begin","end","if","then","while","do","return","read",

"print","int","const"};

int i;

char tx[40];

char*p,*add();

for(p=tx;isdigit(nch)||isalpha(nch);nch=getc(PF))

*(p++)=nch;

*p='\0';

for(i=0;i<11;i++)

if(strcmp(tx, serv[i])==0)

{

lex=cdl[i];

return;

}

lex=IDEN;

lval=(int)add(tx);

printf("Адрес для %s =%p\n",tx, lval);

fprintf(padres,"Адрес для %s =%p\n",tx, lval);

return;

}

char TNM[400];

char*ptn=TNM;

char*add(char*nm)

{

char*p,*strcpy();

for(p=TNM;p<ptn;p+=strlen(p)+1)

if(strcmp(p, nm)==0)

return p;

if((ptn+=strlen(nm)+1)>TNM+400)

{

puts("Переполнение таблицы");

exit(0);

}

return(strcpy(p, nm));

}

Образец результата работы программы

Адрес для exp =0586

Адрес для a =058B

Адрес для b =058D

Адрес для z =058F

Адрес для z =058F

Адрес для b =058D

и т. д.

6. 1 Пример выполнения курсовой работы

Вариант задания курсовой работы

Составить программу на Си для лексического анализа программы на модифицированном языке SPL, в котором все ключевые слова переведены на русский язык и вместо begin и end используются соответственно левая и правая фигурные скобки. Вывести в файл и на экран таблицу идентификаторов и их адресов.

Вариант программы на модифицированном языке SPL (вычисляет xy), где по условию задачи все ключевые слова заменены на соответствующие на русском языке, а вместо begin и end используются соответственно { и }

exp(a, b)

{

целый z;

z=1;

пока b делать

если b%2 тогда z=z*a };

a=a*a;b=b/2

};

возврат z

}

main()

{

целый x, y;

читать x;

читать y;

печатать exp(x, y) }

Замечание: жирным шрифтом выделены изменения, которые необходимо внести в предыдущую программу, согласно варианту задания.

#include<stdio. h>

#include<stdlib. h>

#include<ctype. h>

#include<conio. h>

#include<alloc. h>

#include<string. h>

/*Коды лексем языка SPL*/

enum{BEGINL=257,ENDL, IFL, THENL, WHILEL, DOL, RETRL, READL, PRITL, INTL, CONSTL, IDEN, NUMB};

int nst=0;

int lval, lex;

static char nch='\n';

FILE*PF,*padres;

void get(void);

void number(void);

void word(void);

char*add(char*nm);

int isalpharus(char c);

int isspace1(char c);

int isdigit1(char c);

void main(int ac, char*av[])

{

clrscr();

if(!ac)

puts("Hет исходного файла");

PF=fopen(av[1],"r");

padres=fopen("getrez. dan","w");

if(!PF)

puts("Файл не открывается");

else

get();

}

void get()

{

while(nch!=EOF)

{

while(isspace1(nch))

{

if(nch=='\n')

nst++;

nch=getc(PF);

}

if(isdigit1(nch))

number();

else

if(isalpharus(nch))

word();

else

if(nch=='('||nch==')'||nch==','||nch==';'||nch=='='||nch=='+'||nch=='-'||nch=='*'||nch=='/'||nch=='%'||nch=='{'||nch=='}')

{

lex=nch;

nch=getc(PF);

}

}

if(nch==EOF)

lex=EOF;

else

puts("Hедопустимый символ");

return;

}

void number()

{

for(lval=0;isdigit1(nch);nch=getc(PF))

lval=lval*10+nch-'0';

lex=NUMB;

return;

}

void word()

{

static int cdl[]={BEGINL, ENDL, IFL, THENL, WHILEL, DOL, RETRL, READL,

PRITL, INTL, CONSTL, IDEN, NUMB};

static char*serv[]={"{","}","если","тогда","пока","делать","возврат","читать","печатать","целый","const"};

int i;

char tx[40];

char*p,*add();

for(p=tx;isdigit1(nch)||isalpharus(nch);nch=getc(PF))

*(p++)=nch;

*p='\0';

for(i=0;i<11;i++)

if(strcmp(tx, serv[i])==0)

{

lex=cdl[i];

return;

}

lex=IDEN;

lval=(int)add(tx);

printf("Адрес для %s =%p\n",tx, lval);

fprintf(padres,"Адрес для %s =%p\n",tx, lval);

return;

}

char TNM[400];

char*ptn=TNM;

char*add(char*nm)

{

char*p,*strcpy();

for(p=TNM;p<ptn;p+=strlen(p)+1)

if(strcmp(p, nm)==0)

return p;

if((ptn+=strlen(nm)+1)>TNM+400)

{

puts("Переполнение таблицы");

exit(0);

}

return(strcpy(p, nm));

}

/* Добавляем к исходной программе функции пользователя для распознавания букв, специальных знаков и цифр */

int isalpharus(char c)

{

int v;

if(isalpha(c)||c=='а'||c=='б'||c=='в'||c=='г'||c=='д'||c=='е'

||c=='ж'||c=='з'||c=='д'||c=='е'||c=='ж'||c=='з'||c=='и'|| c=='й'||c=='к'||c=='л'||c=='м'||c=='н'||c=='о'||c=='п'|| c=='р'||c=='с'||c=='т'||c=='у'||c=='ф'||c=='х'||c=='ц'||c=='ч'||c=='ш'||c=='щ'||c=='ы'||c=='э'||c=='ю'||c=='я'||c== 'ь')

Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 6 7