#pragma hdrstop #include #include #include #include #include #include #include #include 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<= 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; }