diff --git a/lab4/report/.gitignore b/lab4/report/.gitignore new file mode 100644 index 0000000..38a3719 --- /dev/null +++ b/lab4/report/.gitignore @@ -0,0 +1,5 @@ +**/* +!.gitignore +!report.tex +!img +!img/** \ No newline at end of file diff --git a/lab4/report/img/compiler.png b/lab4/report/img/compiler.png new file mode 100644 index 0000000..3439d90 Binary files /dev/null and b/lab4/report/img/compiler.png differ diff --git a/lab4/report/img/scheme.png b/lab4/report/img/scheme.png new file mode 100644 index 0000000..e44da2a Binary files /dev/null and b/lab4/report/img/scheme.png differ diff --git a/lab4/report/img/syntax_diagram_addop.png b/lab4/report/img/syntax_diagram_addop.png new file mode 100644 index 0000000..7ebb40f Binary files /dev/null and b/lab4/report/img/syntax_diagram_addop.png differ diff --git a/lab4/report/img/syntax_diagram_cmpi.png b/lab4/report/img/syntax_diagram_cmpi.png new file mode 100644 index 0000000..d870d0c Binary files /dev/null and b/lab4/report/img/syntax_diagram_cmpi.png differ diff --git a/lab4/report/img/syntax_diagram_digit.png b/lab4/report/img/syntax_diagram_digit.png new file mode 100644 index 0000000..806b3b5 Binary files /dev/null and b/lab4/report/img/syntax_diagram_digit.png differ diff --git a/lab4/report/img/syntax_diagram_expression.png b/lab4/report/img/syntax_diagram_expression.png new file mode 100644 index 0000000..0ffe560 Binary files /dev/null and b/lab4/report/img/syntax_diagram_expression.png differ diff --git a/lab4/report/img/syntax_diagram_factor.png b/lab4/report/img/syntax_diagram_factor.png new file mode 100644 index 0000000..ee3e4e6 Binary files /dev/null and b/lab4/report/img/syntax_diagram_factor.png differ diff --git a/lab4/report/img/syntax_diagram_ident.png b/lab4/report/img/syntax_diagram_ident.png new file mode 100644 index 0000000..52e378f Binary files /dev/null and b/lab4/report/img/syntax_diagram_ident.png differ diff --git a/lab4/report/img/syntax_diagram_letter.png b/lab4/report/img/syntax_diagram_letter.png new file mode 100644 index 0000000..dba2400 Binary files /dev/null and b/lab4/report/img/syntax_diagram_letter.png differ diff --git a/lab4/report/img/syntax_diagram_mulop.png b/lab4/report/img/syntax_diagram_mulop.png new file mode 100644 index 0000000..824402e Binary files /dev/null and b/lab4/report/img/syntax_diagram_mulop.png differ diff --git a/lab4/report/img/syntax_diagram_program.png b/lab4/report/img/syntax_diagram_program.png new file mode 100644 index 0000000..5088374 Binary files /dev/null and b/lab4/report/img/syntax_diagram_program.png differ diff --git a/lab4/report/img/syntax_diagram_relation.png b/lab4/report/img/syntax_diagram_relation.png new file mode 100644 index 0000000..728cd45 Binary files /dev/null and b/lab4/report/img/syntax_diagram_relation.png differ diff --git a/lab4/report/img/syntax_diagram_statement.png b/lab4/report/img/syntax_diagram_statement.png new file mode 100644 index 0000000..7f038a8 Binary files /dev/null and b/lab4/report/img/syntax_diagram_statement.png differ diff --git a/lab4/report/img/syntax_diagram_statementList.png b/lab4/report/img/syntax_diagram_statementList.png new file mode 100644 index 0000000..cea778d Binary files /dev/null and b/lab4/report/img/syntax_diagram_statementList.png differ diff --git a/lab4/report/report.tex b/lab4/report/report.tex new file mode 100644 index 0000000..832f419 --- /dev/null +++ b/lab4/report/report.tex @@ -0,0 +1,433 @@ +\documentclass[a4paper, final]{article} +%\usepackage{literat} % Нормальные шрифты +\usepackage[14pt]{extsizes} % для того чтобы задать нестандартный 14-ый размер шрифта +\usepackage{tabularx} +\usepackage[T2A]{fontenc} +\usepackage[utf8]{inputenc} +\usepackage[russian]{babel} +\usepackage{amsmath} +\usepackage[left=25mm, top=20mm, right=20mm, bottom=20mm, footskip=10mm]{geometry} +\usepackage{ragged2e} %для растягивания по ширине +\usepackage{setspace} %для межстрочно го интервала +\usepackage{moreverb} %для работы с листингами +\usepackage{indentfirst} % для абзацного отступа +\usepackage{moreverb} %для печати в листинге исходного кода программ +\usepackage{pdfpages} %для вставки других pdf файлов +\usepackage{tikz} +\usepackage{graphicx} +\usepackage{afterpage} +\usepackage{longtable} +\usepackage{float} + + + +% \usepackage[paper=A4,DIV=12]{typearea} +\usepackage{pdflscape} +% \usepackage{lscape} + +\usepackage{array} +\usepackage{multirow} + +\renewcommand\verbatimtabsize{4\relax} +\renewcommand\listingoffset{0.2em} %отступ от номеров строк в листинге +\renewcommand{\arraystretch}{1.4} % изменяю высоту строки в таблице +\usepackage[font=small, singlelinecheck=false, justification=centering, format=plain, labelsep=period]{caption} %для настройки заголовка таблицы +\usepackage{listings} %листинги +\usepackage{xcolor} % цвета +\usepackage{hyperref}% для гиперссылок +\usepackage{enumitem} %для перечислений + +\newcommand{\specialcell}[2][l]{\begin{tabular}[#1]{@{}l@{}}#2\end{tabular}} + + +\setlist[enumerate,itemize]{leftmargin=1.2cm} %отступ в перечислениях + +\hypersetup{colorlinks, + allcolors=[RGB]{010 090 200}} %красивые гиперссылки (не красные) + +% подгружаемые языки — подробнее в документации listings (это всё для листингов) +\lstloadlanguages{ SQL} +% включаем кириллицу и добавляем кое−какие опции +\lstset{tabsize=2, + breaklines, + basicstyle=\footnotesize, + columns=fullflexible, + flexiblecolumns, + numbers=left, + numberstyle={\footnotesize}, + keywordstyle=\color{blue}, + inputencoding=cp1251, + extendedchars=true +} +\lstdefinelanguage{MyC}{ + language=SQL, +% ndkeywordstyle=\color{darkgray}\bfseries, +% identifierstyle=\color{black}, +% morecomment=[n]{/**}{*/}, +% commentstyle=\color{blue}\ttfamily, +% stringstyle=\color{red}\ttfamily, +% morestring=[b]", +% showstringspaces=false, +% morecomment=[l][\color{gray}]{//}, + keepspaces=true, + escapechar=\%, + texcl=true +} + +\textheight=24cm % высота текста +\textwidth=16cm % ширина текста +\oddsidemargin=0pt % отступ от левого края +\topmargin=-1.5cm % отступ от верхнего края +\parindent=24pt % абзацный отступ +\parskip=5pt % интервал между абзацами +\tolerance=2000 % терпимость к "жидким" строкам +\flushbottom % выравнивание высоты страниц + + +% Настройка листингов +\lstset{ + language=python, + extendedchars=\true, + inputencoding=utf8, + keepspaces=true, + % captionpos=b, % подписи листингов снизу +} + +\begin{document} % начало документа + + + + % НАЧАЛО ТИТУЛЬНОГО ЛИСТА + \begin{center} + \hfill \break + \hfill \break + \normalsize{МИНИСТЕРСТВО НАУКИ И ВЫСШЕГО ОБРАЗОВАНИЯ РОССИЙСКОЙ ФЕДЕРАЦИИ\\ + федеральное государственное автономное образовательное учреждение высшего образования «Санкт-Петербургский политехнический университет Петра Великого»\\[10pt]} + \normalsize{Институт компьютерных наук и кибербезопасности}\\[10pt] + \normalsize{Высшая школа технологий искусственного интеллекта}\\[10pt] + \normalsize{Направление: 02.03.01 <<Математика и компьютерные науки>>}\\ + + \hfill \break + \hfill \break + \hfill \break + \hfill \break + \large{Лабораторная работа №4}\\ + \large{<<Доработка компилятора языка MiLan>>}\\ + \large{по дисциплине}\\ + \large{<<Математическая логика и теория автоматов>>}\\ + \large{Вариант 8}\\ + + % \hfill \break + \hfill \break + \end{center} + + \small{ + \begin{tabular}{lrrl} + \!\!\!Студент, & \hspace{2cm} & & \\ + \!\!\!группы 5130201/20102 & \hspace{2cm} & \underline{\hspace{3cm}} &Тищенко А. А. \\\\ + \!\!\!Преподаватель & \hspace{2cm} & \underline{\hspace{3cm}} & Востров А. В. \\\\ + &&\hspace{4cm} + \end{tabular} + \begin{flushright} + <<\underline{\hspace{1cm}}>>\underline{\hspace{2.5cm}} 2025г. + \end{flushright} + } + + \hfill \break + % \hfill \break + \begin{center} \small{Санкт-Петербург, 2025} \end{center} + \thispagestyle{empty} % выключаем отображение номера для этой страницы + + % КОНЕЦ ТИТУЛЬНОГО ЛИСТА + \newpage + + \tableofcontents + + + \newpage + + \section*{Введение} + \addcontentsline{toc}{section}{Введение} + Лабораторная №4 заключается в доработке компилятора языка MiLan согласно варианту работы. + + \textit{Вариант 8}: В компилятор необходимо добавить поддержку операций инкремента и декремента, как постфиксных, так и префиксных: \texttt{++i}, \texttt{--i}, \texttt{i++}, \texttt{i--}. С точки зрения действия на операнд i между префиксными и постфиксными операциями разницы нет. Если эти выражения являются частью более сложного выражения, то при префиксной форме сначала изменяется операнд i, и уже измененный результат используется в выражении. При постфиксной форме операторов инкремента или декремента сначала операнд i используется в выражении, а потом уже изменяется. + + + \newpage + \section {Математическое описание} + \subsection{Обзор языка MiLan} + Язык Милан — учебный язык программирования, описанный в учебнике~\cite{karpov}. + + Программа на Милане представляет собой последовательность операторов, заключенных между ключевыми словами \texttt{begin} и \texttt{end}. Операторы отделяются друг от друга точкой с запятой. После последнего оператора в блоке точка с запятой не ставится. Компилятор \texttt{CMilan} не учитывает регистр символов в именах переменных и ключевых словах. + + В базовую версию языка Милан входят следующие конструкции: константы, идентификаторы, арифметические операции над целыми числами, операторы чтения чисел со стандартного ввода и печати чисел на стандартный вывод, оператор присваивания, условный оператор, оператор цикла с предусловием. + + Программа может содержать комментарии, которые могут быть многострочными. Комментарий начинается символами \texttt{/*} и заканчивается символами \texttt{*/}. Вложенные комментарии не допускаются. + + В данной лабораторной рассматривается добавление поддержки операций инкремента и декремента, как постфиксных, так и префиксных: \texttt{++i}, \texttt{--i}, \texttt{i++}, \texttt{i--}. С точки зрения действия на операнд i между префиксными и постфиксными операциями разницы нет. Если эти выражения являются частью более сложного выражения, то при префиксной форме сначала изменяется операнд i, и уже измененный результат используется в выражении. При постфиксной форме операторов инкремента или декремента сначала операнд i используется в выражении, а потом уже изменяется. + + \subsection{Лексический анализ} + В реальных трансляторах языков программирования (ЯП) первой фазой является так называемый лексический анализ входной программы — предварительная + обработка входного текста с выделением в нем структурно значимых единиц — лексем. На Рис.~\ref{fig:scheme} представлена схема транслятора. + + \begin{figure}[h!] + \centering + \includegraphics[width=0.7\linewidth]{img/scheme.png} + \caption{Схема транслятора.} + \label{fig:scheme} + \end{figure} + + Лексемы — минимальные единицы языка, которые имеют смысл. + + Значение лексемы, определяющее подстроку символов входной цепочки, соответствующих распознанному классу лексемы. В зависимости от класса, значение + лексемы может быть преобразовано во внутреннее представление уже на этапе лексического анализа. + + Класс лексемы, определяющий общее название для категории элементов, обладающих общими свойствами (идентификатор, целое число, строка символов...). + + Лексический анализатор обрабатывает входную цепочку, а на его вход подаются + символы, сгруппированные по категориям. Поэтому перед лексическим анализом + осуществляется дополнительная обработка, сопоставляющая с каждым символом его + класс, что позволяет сканеру манипулировать единым понятием для целой группы + символов. + + Лексический анализатор (лексер) — это конечный автомат, который преобразует входную строку символов в последовательность токенов. Формально его можно описать следующим образом: + + Пусть заданы: + \begin{itemize} + \item $\Sigma$ — входной алфавит (множество допустимых символов) + \item $T$ — множество типов токенов + \item $D$ — множество допустимых значений токенов + \end{itemize} + + Тогда лексический анализатор реализует отображение: + \[ + F_{\text{lexer}} : \Sigma^* \rightarrow (T \times D)^* + \] + + где: + \begin{itemize} + \item $\Sigma^*$ — множество всех возможных строк над алфавитом $\Sigma$ + \item $(T \times D)^*$ — множество последовательностей пар (тип токена, значение) + \end{itemize} + + Процесс лексического анализа можно представить как \textbf{детерминированный конечный автомат (ДКА)}: + \[ + M = (Q, \Sigma, \delta, q_0, F), + \] + где: + \begin{itemize} + \item $Q$ — множество состояний автомата + \item $\delta : Q \times \Sigma \rightarrow Q$ — функция переходов + \item $q_0 \in Q$ — начальное состояние + \item $F \subseteq Q$ — множество конечных состояний + \end{itemize} + + Для каждого распознанного токена $t_i$ выполняется: + \[ + t_i = (\text{type}, \text{value}), \quad \text{где } \text{type} \in T, \text{value} \in D + \] + + \subsection{Синтаксический анализ} + Синтаксический анализ — процесс сопоставления линейной последовательности лексем естественного или формального языка с его формальной грамматикой. + Результатом обычно является дерево разбора. Обычно применяется совместно с лексическим анализом. + + Синтаксический анализатор выражений (парсер) — часть программы, + выполняющая чтение и анализ выражения. + + Существует два типа алгоритмов синтаксического анализа: нисходящий и восходящий: + \begin{itemize} + \item Нисходящий парсер — продукции грамматики раскрываются, начиная со стартового символа, до получения требуемой последовательности токенов. + \item Восходящий парсер — продукции восстанавливаются из правых частей, начиная с токенов и кончая стартовым символом. + \end{itemize} + + Грамматика языка MiLan использует нисходящий парсер. При восстановлении + синтаксического дерева при нисходящем разборе слева направо последовательно анализирует все поддеревья, принадлежащие самому левому нетерминалу. Когда самым + левым становится другой нетерминал, анализируется уже он. + + Компилятор CMilan включает три компонента (Рис.~\ref{fig:compiler}): + \begin{enumerate} + \item лексический анализатор; + \item синтаксический анализатор; + \item генератор команд виртуальной машины Милана. + \end{enumerate} + + \begin{figure}[h!] + \centering + \includegraphics[width=0.7\linewidth]{img/compiler.png} + \caption{Компоненты компилятора CMilan.} + \label{fig:compiler} + \end{figure} + + \subsection{Грамматика языка MiLan} + Грамматика языка Милан является контекстно-свободной, так как удовлетворяет определению КС-грамматики, т.е. продукции грамматики имеют вид $A \rightarrow \beta$, где $A$ – одиночный нетерминал, а $\beta$ – произвольная цепочка из терминалов и нетерминалов. Более того, грамматика языка Милан является LL(1) грамматикой, так как необходимо просмотреть поток всего на один символ вперед при принятии решения о том, какое правило грамматики необходимо применить. В данной работе в грамматику были добавлены операции инкремента и декремента, однако это не повлияло на LL(1) свойство грамматики. + + Грамматика языка Милан, расширенная операцией инкремента и декремента, в форме Бэкуса-Наура приведена ниже: + + \begin{verbatim} + ::= ‘begin’ ‘end’ + ::= ‘;’ + | epsilon + ::= ‘:=’ + | ‘if’ ‘then’ + [‘else’ ] ‘fi’ + | ‘while’ ‘do’ ‘od’ + | ‘write’ ‘(’ ‘)’ + ::= { } + ::= { } + ::= + | ‘++’ + | ‘--’ + | ‘++’ + | ‘--’ + | + | ‘(’ ‘)’ + ::= + ::= ‘+’|‘-’ + ::= ‘*’|‘/’ + ::= ‘=’|‘!=’|‘<’|‘<=’|‘>’|‘>=’ + ::= { | } + ::= ‘a’|‘b’|‘c’ | ...| ‘z’|‘A’|‘B’|‘C’ | ...| ‘Z’ + ::= ‘0’|‘1’|‘2’|‘3’|‘4’|‘5’|‘6’|‘7’|‘8’|‘9’ + \end{verbatim} + + Изменения коснулись только правила \texttt{}, в котором были добавлены 4 новые продукции, описывающие операции постфиксного и префиксного инкремента и декремента. + + Синтаксические диаграммы для всех нетерминалов грамматики приведены на Рис.~\ref{fig:syntax_diagram_program} — Рис.~\ref{fig:syntax_diagram_digit}. Обновлённая синтаксическая диаграмма для нетерминала \texttt{} приведена на Рис.~\ref{fig:syntax_diagram_factor}. + + \begin{figure}[h!] + \centering + \includegraphics[width=0.9\linewidth]{img/syntax_diagram_program.png} + \caption{Синтаксическая диаграмма для нетерминала \texttt{}.} + \label{fig:syntax_diagram_program} + \end{figure} + + \begin{figure}[h!] + \centering + \includegraphics[width=0.7\linewidth]{img/syntax_diagram_statementList.png} + \caption{Синтаксическая диаграмма для нетерминала \texttt{}.} + \label{fig:syntax_diagram_statementList} + \end{figure} + + \begin{figure}[h!] + \centering + \includegraphics[width=1\linewidth]{img/syntax_diagram_statement.png} + \caption{Синтаксическая диаграмма для нетерминала \texttt{}.} + \label{fig:syntax_diagram_statement} + \end{figure} + + \begin{figure}[h!] + \centering + \includegraphics[width=0.7\linewidth]{img/syntax_diagram_expression.png} + \caption{Синтаксическая диаграмма для нетерминала \texttt{}.} + \label{fig:syntax_diagram_expression} + \end{figure} + + \begin{figure}[h!] + \centering + \includegraphics[width=1\linewidth]{img/syntax_diagram_relation.png} + \caption{Синтаксическая диаграмма для нетерминала \texttt{}.} + \label{fig:syntax_diagram_relation} + \end{figure} + + \begin{figure}[h!] + \centering + \includegraphics[width=0.5\linewidth]{img/syntax_diagram_addop.png} + \caption{Синтаксическая диаграмма для нетерминала \texttt{}.} + \label{fig:syntax_diagram_addop} + \end{figure} + + \begin{figure}[h!] + \centering + \includegraphics[width=0.5\linewidth]{img/syntax_diagram_mulop.png} + \caption{Синтаксическая диаграмма для нетерминала \texttt{}.} + \label{fig:syntax_diagram_mulop} + \end{figure} + + \begin{figure}[h!] + \centering + \includegraphics[width=0.65\linewidth]{img/syntax_diagram_factor.png} + \caption{Синтаксическая диаграмма для нетерминала \texttt{}, дополненная операциями инкремента и декремента (отмечены зеленым цветом).} + \label{fig:syntax_diagram_factor} + \end{figure} + + \begin{figure}[h!] + \centering + \includegraphics[width=0.6\linewidth]{img/syntax_diagram_ident.png} + \caption{Синтаксическая диаграмма для нетерминала \texttt{}.} + \label{fig:syntax_diagram_ident} + \end{figure} + + \begin{figure}[h!] + \centering + \includegraphics[width=1\linewidth]{img/syntax_diagram_letter.png} + \caption{Синтаксическая диаграмма для нетерминала \texttt{}.} + \label{fig:syntax_diagram_letter} + \end{figure} + + \begin{figure}[h!] + \centering + \includegraphics[width=1\linewidth]{img/syntax_diagram_digit.png} + \caption{Синтаксическая диаграмма для нетерминала \texttt{}.} + \label{fig:syntax_diagram_digit} + \end{figure} + + + \newpage + \phantom{text} + + \section{Особенности реализации} + \subsection{Token} + + + + \newpage + \section{Результаты работы программы} + Результаты работы программы представлены на Рис.~\ref{fig:result1}. + + % \begin{figure}[h!] + % \centering + % \includegraphics[width=1\linewidth]{img/result1.png} + % \caption{Результаты работы программы.} + % \label{fig:result1} + % \end{figure} + + % % \newpage + + % \begin{figure}[h!] + % \centering + % \includegraphics[width=0.5\linewidth]{img/wrong.png} + % \caption{Реакция программы на некорректный пользовательский ввод.} + % \label{fig:wrong} + % \end{figure} + + На Рис.~\ref{fig:wrong} представлена реакция программы на некорректный пользовательский ввод. + + + \newpage + \section*{Заключение} + \addcontentsline{toc}{section}{Заключение} + В ходе выполнения лабораторной работы была построена контекстно-свободная грамматика для подмножества немецкого языка, описывающая простое прошедшее время Претерит. На основе разработанной грамматики была реализована программа, которая проверяет принадлежность входной строки заданному языку и генерирует случайные корректные предложения. Для анализа предложений использовался алгоритм LL(1)-разбора, основанный на построении множеств FIRST и FOLLOW для всех нетерминалов грамматики и создании таблицы синтаксического анализа. + + Из достоинств выполнения лабораторной работы можно выделить возможность задания грамматики в отдельном текстовом файле, что позволяет легко изменять и расширять её без модификации программного кода. Также программа автоматически проверяет, что введенная грамматика является LL(1)-грамматикой. В противном случае, программа выводит сообщение об ошибке, в указывается на конкретные правила грамматики, между выбором которых возникает неоднозначность. + + К недостаткам текущей реализации можно отнести ограниченность словарного запаса, что сужает разнообразие генерируемых предложений. Также алгоритм генерации не контролирует длину предложений, что может приводить к избыточно длинным или коротким конструкциям. В текущей версии система не учитывает некоторые грамматические особенности немецкого языка, например, склонение прилагательных и согласование артиклей с родом существительных. + + Функционал программы несложно масштабировать. Грамматику легко расширять, добавляя новые слова и правила в текстовый файл без необходимости изменения программного кода. Класс Grammar может служить хорошей основой для создания полноценного LL(k) анализатора. + + На выполнение лабораторной работы ушло около 12 часов. Работа была выполнена в среде разработки Visual Studio Code. Программа написана на Python версии 3.13. + +\newpage +\section*{Список литературы} +\addcontentsline{toc}{section}{Список литературы} + +\vspace{-1.5cm} +\begin{thebibliography}{0} + \bibitem{vostrov} + Востров, А.В. Курс лекций по дисциплине <<Математическая логика>>. URL \url{https://tema.spbstu.ru/compiler/} (дата обращения 01.05.2025 г.) + \bibitem{aho} + А. Ахо, М. Лам, Р. Сети, Дж. Ульман, Компиляторы: принципы, технологии и инструментарий, 2-е изд. М.: Вильямс, 2011. + \bibitem{karpov} + Ю.Г. Карпов, Теория и технология программирования. Основы построения трансляторов. СПб.: БХВ-Петербург, 2005. +\end{thebibliography} + +\end{document} \ No newline at end of file