Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ЛР2 Саляхов

.docx
Скачиваний:
0
Добавлен:
25.06.2025
Размер:
121.09 Кб
Скачать

Министерство образования и науки Российской Федерации

Федеральное государственное бюджетное образовательное учреждение высшего образования

«Уфимский университет науки и технологий»

Кафедра ТК

Отчет по лабораторной работе № 2

«Системное программное обеспечение»

Тема: «Проектирование лексического анализатора» Вариант 11

Выполнил:

студент группы ИВТ-429Б

Саляхов А.Ф.

Проверил:

доцент кафедры ТК

Ракипова А.С.

Уфа 2024

Цель работы:

Изучение основных понятий теории регулярных грамматик, ознакомление с назначением и принципами работы лексических анализаторов (сканеров), получение практических навыков построения сканера на примере заданного простейшего входного языка.

Задание:

Написать программу, которая выполняет лексический анализ входного текста в соответствии с заданием и порождает таблицу лексем с указанием их типов и значений. Текст на входном языке задаётся в виде символьного (текстового) файла. Программа должна выдавать сообщение о наличии во входном тексте ошибок, которые могут быть обнаружены на этапе лексического анализа. Длину идентификаторов и строковых констант можно считать ограниченной 32 символами. Программа должна допускать наличие комментариев неограниченной длинны во входном файле. Форму организации комментариев предлагается выбрать самостоятельно.

Вариант 11:

Входной язык содержит операторы условия типа if ... then .. else и if .. then, разделённые символом ; (точка с запятой). Операторы условия содержат идентификаторы, знаки сравнения <, >, =, шестнадцатеричные числа, знак присваивания (:=)

Описание КС - грамматики входного языка:

G ({1,2,3,4,5,6,7,8,9,0,A,B,C,D,E,F,e,f,h,i,n,l,s,t,#,’:’,’=’, ‘;’, ‘<‘, ‘>’}, ({A,B,C,D,E,F,G,H,I,J,K,L,M,N,R,T,i,O,s},P)

P:

A→ i

B→Af

C→t

D→Ch

E→De

F→En

G→e

R→/*

H→Gl

I→Hs

J→Ie

K→;

L→ < | > | =

M→ :

N→ M=

T→*/

O→ 1∣2∣3∣4∣5∣6∣7∣8∣9∣0∣O1∣O2∣O3∣O4∣O5∣O6∣O7∣O8∣O9∣O0∣OA∣OB∣OC∣OD∣OE∣OF

i→h*|i*|A*|B*|C*|D*|E*|F*|G*|H*|I*|J*

s→i#|B#|F#|J#|K#|L#|N#|Q#|S#|A#|C#|D#|E#|G#|H#|I#|

i* - множество всех символов

h*- множество всех символов, крoме терминальных символов

A*- множество всех символов, кроме #, f

B*- множество всех символов, кроме #

C*- множество всех символов, кроме #, h

D*- множество всех символов, кроме #, e

E*- множество всех символов, кроме #, n

F*- множество всех символов, кроме #

G*- множество всех символов, кроме #, i

H*- множество всех символов, кроме #, s

I*- множество всех символов, кроме #, e

J*- множество всех символов, кроме #

Схема цепочки:

Код программы:

#include <iostream>

#include <fstream>

#include <string>

#include <vector>

#include <cctype>

using namespace std;

struct Lexeme {

string value;

string type;

string chain;

int lineNumber;

};

string determineLexemeType(const string& lexeme) {

if (!lexeme.empty() && isdigit(lexeme[0])) {

bool isHex = true;

for (char ch : lexeme) {

if (!isxdigit(ch)) {

isHex = false;

break;

}

}

if (isHex) return "Шестнадцатеричное число";

}

// Проверки для других типов

if (lexeme == "if" || lexeme == "then" || lexeme == "else") return "Оператор условия";

if (lexeme == "<" || lexeme == ">" || lexeme == "=") return "Знак сравнения";

if (lexeme == ":=") return "Оператор присваивания";

if (lexeme == ";") return "Разделитель";

if (isalpha(lexeme[0])) return "Идентификатор";

return "Неизвестная лексема";

}

string generateChain(const string& lexeme) {

string chain = "h";

char State = 'h';

for (char ch : lexeme) {

switch (State) {

case 'h':

if (ch == 'i') State = 'A';

else if (ch == 't') State = 'C';

else if (ch == ':') State = 'M';

else if (ch == 'e') State = 'G';

else if (ch == ';') State = 'K';

else if (ch == '>' || ch == '<' || ch == '=') State = 'L';

else if (isdigit(ch)) State = 'O'; // Обработка для чисел

else State = 'i';

break;

case 'A':

if (ch == 'f') State = 'B';

else State = 'i';

break;

case 'C':

if (ch == 'h') State = 'D';

else State = 'i';

break;

case 'M':

if (ch == '=') State = 'N';

else State = 'e';

break;

case 'O':

if (isdigit(ch) || (toupper(ch) >= 'A' && toupper(ch) <= 'F')) State = 'O'; // Обработка для шестнадцатеричных чисел

break;

default:

break;

}

chain += State;

}

chain += "s";

return chain;

}

void reportUnknownLexeme(const string& lexeme, int lineNumber) {

cout << "Неизвестная лексема \"" << lexeme << "\" в строке " << lineNumber << endl;

}

vector<Lexeme> lexicalAnalysis(const string& text) {

vector<Lexeme> lexemes;

string current;

bool inComment = false;

int lineNumber = 0;

for (size_t i = 0; i < text.length(); i++) {

char ch = text[i];

if (ch == '\n') lineNumber++;

if (!inComment && ch == '/' && text[i + 1] == '*') {

inComment = true;

i++;

continue;

}

if (inComment && ch == '*' && text[i + 1] == '/') {

inComment = false;

i++;

continue;

}

if (inComment) continue;

if (isspace(ch) || ch == ';' || ch == '<' || ch == '>' || ch == '=' || ch == ':') {

if (!current.empty()) {

string type = determineLexemeType(current);

if (type == "Неизвестная лексема") {

reportUnknownLexeme(current, lineNumber);

}

else {

lexemes.push_back({ current, type, generateChain(current), lineNumber });

}

current.clear();

}

if (ch == ';' || ch == '<' || ch == '>' || ch == '=') {

string lexemeStr(1, ch);

string type = determineLexemeType(lexemeStr);

if (type == "Неизвестная лексема") {

reportUnknownLexeme(lexemeStr, lineNumber);

}

else {

lexemes.push_back({ lexemeStr, type, generateChain(lexemeStr), lineNumber });

}

}

if (ch == ':' && text[i + 1] == '=') {

lexemes.push_back({ ":=", "Оператор присваивания", generateChain(":="), lineNumber });

i++;

}

}

else {

current += ch;

}

}

if (!current.empty()) {

string type = determineLexemeType(current);

if (type == "Неизвестная лексема") {

reportUnknownLexeme(current, lineNumber);

}

else {

lexemes.push_back({ current, type, generateChain(current), lineNumber });

}

}

return lexemes;

}

int main() {

setlocale(LC_ALL, "Russian");

ifstream file("D:/EclipseWorkspace/12345/src/input.txt");

if (!file) {

cerr << "Не удалось открыть файл." << endl;

return 1;

}

string line, text;

while (getline(file, line)) {

text += line + '\n';

}

file.close();

vector<Lexeme> lexemes = lexicalAnalysis(text);

cout << "Лексема\t\tТип лексемы\t\tЦепочка" << endl;

cout << "--------------------------------------------------------" << endl;

for (const auto& lex : lexemes) {

cout << lex.value << "\t\t" << lex.type << "\t\t" << lex.chain << endl;

}

return 0;

}

Исходный текст для обработки:

Пример выполнения программы:

Вывод: в ходе выполнения лабораторной работы были изучены основные понятия теории регулярных грамматик, ознакомились с назначением и принципами работы лексических анализаторов (сканеров), получили практические навыки построения сканера на примере заданного простейшего входного языка.

Соседние файлы в предмете Системное программное обеспечение