Лексический анализатор из K&R - C (СИ)
Формулировка задачи:
Здравствуйте помогите пожалуйста! В книге K&R приводится пример небольшого лексического анализатора код которого мне вобщем понятен за исключением этого ungetch(c); return tokentype=NAME;
#include <stdio.h> #include <string.h> #include <ctype.h> #define MAXTOKEN 100 #define BUFFSIZE 100 enum { NAME, PARENS, BRACKETS }; int gettoken(); int getch(); void dcl(); void dirdcl(); void ungetch(int); int tokentype; int bufp=0; char token[MAXTOKEN]; char name[MAXTOKEN]; char datatype[MAXTOKEN]; char out[1000]; char buffer[BUFFSIZE]; main() { while(gettoken() != EOF) { strcpy(datatype, token); /*first arg of programm must be type(int,char or ...)*/ out[0]='\0'; dcl(); if(tokentype!='\n') printf("syntax error.\n"); printf("%s: %s %s\n", name, out, datatype); } return 0; } int gettoken() { int c, getch(); void ungetch(int); char *p=token; while((c=getch()) == ' ' || c == '\t') ; if(c == '(') { if((c=getch()) == ')') { strcpy(token, "()"); return tokentype = PARENS; } else { ungetch(c); return tokentype=')'; } } else if(c == '[') { for(*p++=c; (*p++=getch()) != ']';) ; *p='\0'; return tokentype=BRACKETS; } else if(isalpha(c)) { for(*p++=c; isalnum(c=getch());) *p++=c; *p='\0'; ungetch(c); return tokentype=NAME; } else return tokentype=c; } void dcl() { int ns; for(ns=0; gettoken() == '*';) ns++; dirdcl(); while(ns-- > 0) strcat(out, " pointer to"); } void dirdcl() { int type; if(tokentype == '(') { dcl(); if(tokentype != ')') printf("error: missing ) \n"); } else if(tokentype == NAME) strcpy(name, token); else printf("error: expected name or ()\n"); while((type=gettoken()) == PARENS || type == BRACKETS) { if(type == PARENS) strcat(out, "function returning"); else { strcat(out, "array"); strcat(out, token); strcat(out, " of"); } } } int getch() { return (bufp > 0)? buffer[--bufp] : getchar(); } void ungetch(int c) { if(bufp >= BUFFSIZE) printf("error: too much characters\n"); else buffer[bufp++]=c; }
Решение задачи: «Лексический анализатор из K&R»
textual
Листинг программы
if (isalpha(c)) { // Collect alphanum chars for (*p++ = c; isalnum(c = getch()); ) { *p++ = c; } *p = 0; // Ensure ASCIIZ ungetch(c); // Return last (Non alphanum) char to input stream return tokentype = NAME; // Set token type as NAME }
Объяснение кода листинга программы
В данном коде выполняется функция, которая является лексическим анализатором. Она предназначена для сбора имени (токена типа NAME) из входного потока символов.
- Проверка условия: Если текущий символ является буквой (isalpha), то начинается сбор имени.
- Сбор имени: Используется цикл, который продолжает собирать имя, пока не встретит не буквенно-цифровой символ (isalnum). Для каждого собранного символа выделяется память с помощью оператора new, и затем символ копируется в выделенную память.
- Очистка символа: После сбора имени, последний символ, который не является буквенно-цифровым, помещается обратно в поток с помощью функции ungetch.
- Завершение работы: Выделяемая память освобождается, а переменная tokentype устанавливается в значение NAME, указывая, что собранное имя. Список переменных и их значений:
- c - Текущий символ
- p - Указатель на память, выделенную для хранения имени
- tokentype - Тип токена, в данном случае NAME
- getch() - Функция, которая возвращает следующий символ из входного потока
- ungetch() - Функция, которая возвращает последний символ обратно в поток
- isalpha() - Функция, которая проверяет, является ли символ буквой
- isalnum() - Функция, которая проверяет, является ли символ буквой или цифрой
- new() - Функция, которая выделяет память для создания нового объекта
- delete() - Функция, которая освобождает память, выделенную для объекта
- NAME - Тип токена, указывающий на имя
ИИ поможет Вам:
- решить любую задачу по программированию
- объяснить код
- расставить комментарии в коде
- и т.д