В процессе лексического анализа определяются (назначаются) глобальные переменные. Lex - для распознанной лексемы, eval - значение лексем, nst номер строки программы, которая содержит лексему. Различаются следующие лексемы:

служебные слова if,while,return,print,read,begin,end,int, const, then, do, которые кодируются соответственно командами IFL, WHILEL, RETRL, PRITL, READL, BEGINI, ENDL,INTL, CONSTL, THENL,DOL,

знаки операций и разделители, закодированные литеральными константами ‘+’, ’-’, ’*’, ’/’, ’%’, ’=’, ‘(‘,’)’, ‘;’, ‘;’;

целые без знака с кодом NUMB и значением eval;

идентификатор  с кодом  IDEN и значением val, которые являются указателями таблицы идентификаторов TNM;

конец файла с кодом EOF.

Файл lexan.e с функциями лексического анализа имеет вид

/* коды лексем языка программирования SPL*/

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

int nst=0;

int lval,lex;

static char nch='\n';

extern FILE *PF;

/*get-ввод следующей лексемы в lex и lval из PF*/

get()

{if(nch==EOF)

{lex=EOF;return;}

while (isspace (nch))

{if (nch=='\n')nst++;nch=getc(PF);}

if(isdigit(nch))number();else if(isupper(nch))word();

else if(strchr("(),;=+-*/%",nch))

{lex=nch;nch=getc(PF);}

else if(nch==EOF)lex=EOF;

else error("%c:недопустимый символ",nch);

}

/*number-ввод лексемы число*/

number()

{

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

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

lex=NUMB;

}

/*word-ввод лексемы-идентификатора или ключевого слова */

word()

{

static char *serv[]={"IF","WHILE","RETURN","PRINT","READ",

"BEGIN","END","INT","CONST","THEN","DO"};

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

INTL,CONSTL,THENL,DOL};

char tx[40],*p,*add();

int i=0;

for(p=tx;isupper(nch)||isdigit(nch); )

{

*(p++)=nch;

nch=getc(PF);}

*p='\0';

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

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

{lex=cdl[i];return;}

lex=IDEN;lval=add(tx);

return;

}_

 

За каждым обращением к функции get ( ) из файла исходной программы    последовательность литер, которая образует очередную лексему, распознается лексема и отыскиваются значения переменных lex, nst и если необходимо  lval.Функция add ( ) осуществляет поиск и в случае необходимости вводит идентификатор  в таблицу  TNM. Массив TNM содержит цепочки литер, которые задают все разные идентификаторы, которые встречаются в исходной программе. Так массив для программ VAR.2.5 (рисунок 95) содержит 4 цепочки: «main», «a», «b», «z» и указатель ptn первого свободного элемента TNM [11] массива.

 

TNM:

m

a

i

N

\0

a

\0

b

\0

8

\0

×

×

××

 

 

 

 

 

 

 

 

 

 

­ ptn

 

 

Рисунок 95

Описание функции add и таблицы TNM, размещенное в файле table.c имеет вид

/*add - поиск и добавление в TNM идентификатора nm* /

char TNM[400];

char *ptn=TNM;

char *add(nm)

char *nm;

{

char *p,*strcpy();

p=NULL;

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

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

if((ptn+=strlen(nm))+1>TNM+400)error («Переполнен­ TNM");

return(strcpy(p,nm));

}

Тут используются функции из библиотеки языка Си для выполнения операций над строками, которые кончаются символом ‘\0’.