#pragma hdrstop
#include <iostream>
#include <fstream>
#include <iomanip>
#include <conio.h>
#include <stdlib.h>
#include <io.h>
#include <windows.h>
#include <string.h>
using namespace std;
/* Лексический анализатор
Таблица кодов лексем
____________________
Лексема Код
____________________
var 1
do 2
begin 3
end 4
read 5
write 6
integer 7
%% 8
+ 100
- 101
* 102
/ 103
= 104
( 105
) 106
, 107
: 108
; 109
0 - тип служебных слов и перечисленных выше операций
ident 200 – тип идентификаторов
const 300 – тип констант */
int buk (char);
int cif (char);
int kol_buk (int);
int kol_cif (int);
void text_to_aray();
// Константы:
#define num_words 8 //кол-во служебных слов
#define max_text 500 //предельный размер исходного текста
#define max_words 30 //ограничение на кол-во служебных слов и перем-х
#define max_lexems 100 //ограничение на общее число лексем
#define max_length_lexem 10 //ограничение длины имени лексемы
char array_all_text[max_text];//массив для исходного текста
//массив для имен идентификаторов
char lex_name[max_words][max_length_lexem] =
{"var","do","begin","end","read","write","integer","%%"};
//массивы для хранения типов и кодов лексем
int array_lex_code[max_lexems];
int array_lex_type[max_lexems];
//счетчики длин масивов
int count_text = 0;
int count_code = 0;
int count_type = 0;
int count_words = num_words; //счетчик идентификаторов
void main(void)
{
SetConsoleCP(1251);
SetConsoleOutputCP(1251);
text_to_aray();//исходный текст в массив
// Лексический анализ
int i=0, j, g, k;
int count_alllex = 0, cf, cf_flag; //счетчик
char alllex[max_lexems][max_length_lexem]= {""};//массив всех найденных лексем
while (i < count_text) //переборка всего текста
{
if (((int)array_all_text[i]) > 32)//если литера печатаемая
{
if (buk(array_all_text[i]))//если буква, то только идентификатор
{
k = kol_buk (i); //определение длины идентификатора
g = 0;
for (j = i; j <= k; j++, g++) //Собираем идентификатор в строку
alllex[count_alllex][g] = array_all_text[j];//переносим из текста в массив всех лексем
for (cf =0; cf < count_words; cf++) //Сравниваем найденный идентификатор с массивом имен,
//перебераем все слова в массиве
{ //Обработка идентификатора
cf_flag = strcmp(lex_name[cf],alllex[count_alllex]);//сравниваем строки
if (cf_flag == 0) //Если есть совпадение
{
if (cf < num_words) //Если совпадение в числе зарезервированных слов
{
array_lex_type[count_type] = 0;//тип у всех зарезервированных слов нулевой
array_lex_code[count_code] = ++cf;//Сохраняем код найденного слова
count_type++;//переходим к следующему элемента масивов типа и кода
count_code++;
break;
}
else // Если совпадение пользовательского идентификатора
{
array_lex_type[count_type] = 200;//тип пользовательского идентификатора
array_lex_code[count_code] = ++cf;//Сохраняем код найденного слова
count_type++;//переходим к следующему элемента массивов и кодов
count_code++;
break;
}
}
}
if(cf_flag != 0) //Если нет совпадений, то добавляем новый идентификатор в таблицу
{
for (j = i, g =0; j <= k; j++, g++)
lex_name[count_words][g] = array_all_text[j];//переносим найденный идентификатор в массив идентификаторов
array_lex_type[count_type] = 200;//тип пользовательского идентификатора
array_lex_code[count_code] = ++cf;//Сохраняем код найденного слова
count_type++;//переходим к следующему элемента масивов типа и кода
count_code++;
count_words++; // Количество известных идентификаторов увеличилось
}
i = k;
count_alllex++;//увеличиваем счетчик во всех масивов идентификаторов
}
if (cif(array_all_text[i]))//если цифра, то далее может быть только цифровая константа
{
k = kol_cif (i); //Выясняем длину константы
g = 0;
//Собираем в строку
for (j = i; j <= k; j++, g++)
alllex[count_alllex][g] = array_all_text[j];
for (cf =0; cf < count_words; cf++) //Сравниваем с массивом имен и констант
{ //Обработка константы
cf_flag = strcmp(lex_name[cf],alllex[count_alllex]);
if (cf_flag == 0) //Если есть совпадение
{
array_lex_type[count_type] = 300;//тип всех констант 300
array_lex_code[count_code] = ++cf;//Сохраняем код найденного слова
count_type++;//переходим к следующему элемента масивов типа и кода
count_code++;
break;
}
}
if(cf_flag != 0) //Если нет совпадений, то добавляем новую константу в таблицу
{
for (j = i, g =0; j <= k; j++, g++)
lex_name[count_words][g] = array_all_text[j];//переносим строку-константу в массив всех лексем
array_lex_type[count_type] = 300;//тип всех констант 300
array_lex_code[count_code] = ++cf;//Сохраняем код найденной константы
count_type++;//переходим к следующему элемента масивов типа и кода
count_code++;
count_words++; // Количество известных идентификаторов увеличилось
}
i = k;
count_alllex++;//увеличиваем счетчик во всех масивов идентификаторов
}
//Если не буква и не цифра, то это может быть только операция
if (!buk(array_all_text[i]) && !cif(array_all_text[i]))
{
switch(array_all_text[i])
{
case '+': array_lex_code[count_code]=100; break;
case '-': array_lex_code[count_code]=101; break;
case '*': array_lex_code[count_code]=102; break;
case '/': array_lex_code[count_code]=103; break;
case '=': array_lex_code[count_code]=104; break;
case '(': array_lex_code[count_code]=105; break;
case ')': array_lex_code[count_code]=106; break;
case ',': array_lex_code[count_code]=107; break;
case ':': array_lex_code[count_code]=108; break;
case ';': array_lex_code[count_code]=109; break;
case '%': {
if (array_all_text[i+1] == '%') //проверяет следующий символ после %
{
array_lex_code[count_code]=8;//если % то это лексема и ее код 8
i++;
break;
}
array_lex_code[count_code]=110; //если это не % то это одиночный % и ее код 110
break;
}
}
array_lex_type[count_type] = 0; //тип оператора 0
alllex[count_alllex][0] = array_all_text[i];//запоминаем символ оператора в массиве всех лексем
if (array_lex_code[count_code] == 8) //если это лексема %% добавляем второй % в массив всех лексем что бы получилось %%
alllex[count_alllex][1] = array_all_text[i];
count_type++;//переходим к следующему элемента масивов типа и кода
count_code++;
count_alllex++;//увеличиваем счетчик во всех масивов идентификаторов
}
}
i++; //переходим к следующему символу в тексте
}
// Запись результатов в файл-отчет
int sss;
ofstream stf ("Result.txt",ios::out);
stf << "\tИсходный файл:\n" << endl;
for (sss = 0; sss < count_text; sss++)
stf << array_all_text[sss];
stf << "\n\n\tРезультат анализа:\n" << endl;
stf << "№\t" << "Лексема\t\t" << "Тип\t" << "Код" << endl << endl;
for (sss = 0; sss < count_code; sss++)//выводим все найденные лексемы, зарезервированные слова, операторы,
//константы и переменные с их типом и кодом
stf<<sss+1<<"\t"<<alllex[sss]<<"\t\t\t"<<array_lex_type[sss]<<"\t"<<array_lex_code[sss]<<endl;
stf << "\n\tИдентификатор таблицы:\n" << endl;
for (sss = 0; sss < count_words; sss++) //выводится все лексемы без типов и кодов
stf << lex_name[sss] << " ";
stf << "\n\nЛексемы: " << count_code << "\nИдентификатор и константы: " << count_words;
stf.close(); //Закрыли открытый файл
cout<<"\nЛексический анализ исходного файла \"prim.lex\" завершен.\n\nРезультат анализа записан в файл \"Result.txt\"\n\n";
system ("pause");
}
//--------------ОПИСАНИЕ ФУНКЦИЙ ---------------------------
// Проверка по ASCII-коду принадлежности символа к буквам латиницы,
// возвращает 1, если буква, иначе 0.
int buk (char a)
{
int flag = (int)a; //если это значение попадает в диапозон то это буква
if (((flag >= 64)&&(flag <= 90))||((flag >= 96)&&(flag <= 122)))
flag = 1;
else flag =0;
return flag;
}
// Проверка по ASCII-коду принадлежности символа к цифрам,
// возвращает 1, если цифра, иначе 0.
int cif (char a)
{
int flag = (int)a; //
if ((flag >= 48) && (flag <= 57))
flag = 1;
else flag =0;//иначе не цифра
return flag;
}
// Определение границ идентификатора. Передаём номер текущего элемента,
// возвращает номер элемента конца идентификатора
int kol_buk (int i)//количество буква
{
int k = i;
while (buk(array_all_text[k])||cif(array_all_text[k]))//до тех пор пока буква переходим к следующей литере текста
k++;
k--;//возвращает на последнюю букву
return k;
}
// Определение границ цифровой константы
int kol_cif (int i)
{
int k = i;
while (cif(array_all_text[k])) //до тех пор пока цифра переходим к следующей литере текста
k++;
k--;//Возвращает на последнюю цифру
return k;
}
//Считываем исходный файл посимвольно в массив
void text_to_aray()
{
ifstream fts;
char ch;
int i = 0;
fts.open ("prim.lex", ios::in);
while ( fts.get(ch) )//пока есть что читать из файла сохраняем прочитанный символ в массив текста
{
array_all_text[i] = ch;
count_text++;//увеличиваем кол-во смволов в тексте(счетсик)
i++;//переходим к следующему элементу текста
}
fts.close();
return;
}