Разработка анализирующей части компилятора языка С

Разработка анализирующей части компилятора для выполнения проверки исходной программы на соответствие грамматике языка, правилам семантики и построения внутреннего представления. Описание анализаторов: лексического, синтаксического и семантического.

Рубрика Программирование, компьютеры и кибернетика
Вид контрольная работа
Язык русский
Дата добавления 01.02.2013
Размер файла 704,9 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Размещено на http://www.allbest.ru/

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

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

«Магнитогорский государственный технический университет им Г.И. Носова»

Кафедра вычислительной техники и прикладной математики

Курсовая работа по дисциплине:

«Теория языков программирования и методы трансляции»

на тему

«Разработка анализирующей части компилятора языка С»

Выполнил: студент гр. АВ-09

Габдрахманов И.А.

г. Магнитогорск, 2013

Оглавление

  • Введение
  • 1. Лексический анализатор
  • 2. Синтаксический анализатор
  • 3. Семантический анализатор
  • Заключение
  • Библиографический список
  • Введение
  • Анализирующая часть выполняет проверку исходной программы на соответствие грамматике языка, правилам семантики и построение внутреннего представления. Анализирующая часть включает в себя 3 анализатора: лексический, синтаксический и семантический.

Анализирующая часть компилятора разбивает исходную программу на составляющие ее элементы (конструкции языка) и создает промежуточное представление исходной программы. В качестве промежуточного представления обычно используются деревья, в частности, так называемые деревья разбора. Под деревом разбора понимается дерево, каждый узел которого соответствует некоторой операции, а сыновья этого узла - операндам.

Компилятор переводит программы с одного языка на другой. Входом компилятора служит цепочка символов, составляющая исходную программу на языке программирования . Выход компилятора (объектная программа) также представляет собой цепочку символов, но принадлежащую другому языку , например, языку некоторого компьютера. При этом сам компилятор написан на языке , возможно, отличающемся от первых двух. Будем называть язык исходным языком, язык - целевым языком, а язык - языком реализации. Таким образом, можно говорить о компиляторе как об отображении множества в множество , т.е. .

1. Лексический анализатор

Основная задача лексического анализа - разбить входной текст, состоящий из последовательности одиночных символов, на последовательность слов, или лексем, т.е. выделить эти слова из непрерывной последовательности символов. Все символы входной последовательности с этой точки зрения разделяются на символы, принадлежащие каким-либо лексемам, и символы, разделяющие лексемы (разделители). В некоторых случаях между лексемами может и не быть разделителей.

Обычно все лексемы делятся на классы. Примерами таких классов являются числа (целые, восьмеричные, шестнадцатиричные, действительные и т.д.), идентификаторы, строки. Отдельно выделяются ключевые слова и символы пунктуации (иногда их называют символы-ограничители). Как правило, ключевые слова - это некоторое конечное подмножество идентификаторов.

Лексический анализатор построен с использованием GNU Flex -- генератора лексических анализаторов. Входным файлом для Flex является файл c.l, содержащий описание лексики языка. Lex-файл состоит из трех секций -- блока определений, блока правил и блока кода на Си. Блоки разделяются c помощью строк, содержащих %%.

Блок определений включает в себя описания именованных регулярных выражений в формате: имя выражение. Каждое выражение описывается в отдельной строке.

([Pp][+-]?{D}+)

Блок правил содержит правила для определения принадлежности лексемы классу языка в формате: «регулярное выражение» { код на си, обрабатывающий лексему и возвращающий ее класс }

Каждое правило располагается в отдельной строке. Пример правила для определения десятичной константы:

[1-9]{D}*{IS}?

В процессе создания лексического анализатора командой lex c.l из Lex-файла генерируется код на C, содержащийся в файле c.lexer.c. Данный файл содержит функцию yylex(), которая и выполняет лексический анализ программы. После каждого вызова функция возвращает тип лексемы из входного потока, либо 0, в случае его окончания, а также помещает в переменную yytext текст лексемы. Кроме того, в каких-либо других внешних (extern) переменных может находиться информация о лексеме, полученная из пользовательского кода на С. Для корректной работы данной функции переменная yyin должна указывать на открытый файл с исходным текстом программы.

Рисунок 1 - пример работы лексического анализатора (без ошибок)

Рисунок 2 - пример работы лексического анализатора (с ошибками)

2. Синтаксический анализатор

Синтаксический анализ - это процесс, который определяет, принадлежит ли некоторая последовательность лексем языку, порождаемому грамматикой. В принципе, по любой грамматике можно построить синтаксический анализатор, но грамматики, используемые на практике, имеют специальную форму. Например, известно, что для любой контекстно-свободной грамматики может быть построен анализатор, сложность которого не превышает O(n3) для входной строки длины n, но в большинстве случаев по заданному языку программирования мы можем построить такую грамматику, которая позволит сконструировать и более быстрый анализатор. Анализаторы реально используемых языков обычно имеют линейную сложность; это достигается, например, за счет просмотра исходной программы слева направо с заглядыванием вперед на один терминальный символ (лексический класс).

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

Выход синтаксического анализатора - дерево разбора и таблицы, например, таблица идентификаторов и таблица типов, которые являются входом для следующего просмотра компилятора (например, это может быть просмотр, осуществляющий контроль типов).

Для реализации синтаксического анализатора выбран генератор анализаторов GNU Bison. На входе данного генератора -- описание грамматики в БНФ, на выходе -- анализирующий модуль на языке Си.

Bison интегрирован с Flex и полученный с его помощью анализатор использует в качестве входа результаты вызовов функции yylex().

Yacc (bison)-файл состоит из трех секций -- описания токенов, описания грамматики и кода на Си.

Код на Си обязательно должен включать в себя реализацию функции yyerror, которая является обработчиком ошибок.

Описание токенов содержит просто список возможных типов токенов. При генерации кода каждому типу токенов будет присвоено уникальное значение типа yylval, которое и возвращает yylex().

Описание грамматики содержит в себе набор правил в БНФ и код на Си, например, для построения дерева разбора, обрабатывающий каждое правило.

Пример:

unary_expression /* Ok */

: postfix_expression { $$ = $1; }

| INC_OP unary_expression { $$ = makeTreeNode($1, $2); }

| DEC_OP unary_expression { $$ = makeTreeNode($1, $2); }

| unary_operator cast_expression { $$ = makeTreeNode($1, $2); }

| SIZEOF unary_expression { $$ = makeTreeNode($1, $2); }

| SIZEOF '(' type_name ')' { $$ = makeTreeNode($1, $3); }

;

Переменные $1, $2 и т. д. в коде на Си соответствуют токенам в выражении, переменная $$ - результат, который будет использован при обработке выражения более высокого уровня. При сборке анализирующей части получается файл c.parser.h, содержащий LR-анализатор на языке Си. Анализатор запускается вызовом функции yyparse(). По завершении анализа функция возвращает 0, если программа не содержит синтаксических ошибок, либо 1, если ошибки есть.

Рисунок 3 - пример работы лексического анализатора

Рисунок 4 -разбор управляющей конструкции

Рисунок 5 - пример работы синтаксического анализатора (с ошибками)

3. Семантический анализатор

Фаза контроля типов проверяет, удовлетворяет ли программа контекстным условиям. Главной составляющей контекстных условия является "правильное использование" программой типов данных, предоставляемых входным языком, т.е. корректность выражений, встречающихся в программе, с точки зрения использования типов. Данная задача включает нахождение объявления в программе каждого используемого идентификатора, и проверку корректности его появления в использующем контексте.

Идентификация идентификаторов - одна из задач, решение которой необходимо для проверки правильности использования типов.

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

Каждое вхождение идентификатора в программу является либо определяющим, либо использующим. Под определяющим вхождением идентификатора понимается его вхождение в описание, например, int i. Все остальные вхождения являются использующими, например, i = 5 или i+13.

Цель идентификации идентификаторов, определить тип использующего вхождения идентификатора. Эта задача может быть полностью или частично решена на фазе синтаксического анализа. Все зависит от того, может ли использующее вхождение идентификатора встретиться в программе до определяющего вхождения или нет. Если все определяющие вхождения идентификаторов должны быть расположены текстуально перед использующими вхождениями, то мы можем выполнить идентификацию на фазе синтаксического анализа. Если же нет, то на фазе синтаксического анализа мы можем обработать определяющие вхождения идентификаторов и только на следующем просмотре текста программы выполнить собственно идентификацию.

Семантический анализатор реализован методом рекурсивного спуска. Просмотр ведется от начала дерева.

Алгоритм для одного уровня следующий:

Последовательно просматриваем каждый узел дерева данного уровня. Если это объявление переменной, определение пользовательского типа или функции -- добавляем его в соответствующую таблицу. Если это выражение -- рекурсивно разбираем его, восходящим методом. Сначала определяются типы операндов в листах поддерева, затем -- типы узлов-операций первого уровня и т. д., пока не будет получен тип выражения, находящегося на рассматриваемом уровне.

Если это конструкция языка -- условный оператор, цикл, блок -- рекурсивно выполняем его обработку по тем же правилам. При вызове рекурсивного обработчика для такой конструкции в него передаются копии таблиц идентификаторов, функций и типов.

Рисунок 6 - пример работы семантического анализатора (без ошибок)

Рисунок 7 - пример работы семантического анализатора (с ошибками)

компилятор анализатор грамматика язык

Заключение

В данной работе раскрыт вопрос о написании анализирующей части компилятора для языка высокого уровня, а именно: лексический анализатора, синтаксический анализатора и семантический анализатора.

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

Библиографический список

1) Ахо А.В. - Компиляторы: принципы, технологии и инструментарий, 2-е изд. Э Пер. с англ. - ООО «И.Д. Вильямс», 2008. - 1184 с.

2) flex lexical analyser -- Wikipedia, the free encyclopedia // Wikipedia, the free encyclopedia [Электронный ресурс] / Wikimedia Foundation - Электрон. дан. - 2001-2013 - Режим доступа: http://en.wikipedia.org/wiki/Flex_lexical_analyser, свободный. - Загл. с экрана.

3) GNU Bison -- Wikipedia, the free encyclopedia // Wikipedia, the free encyclopedia [Электронный ресурс] / Wikimedia Foundation - Электрон. дан. - 2001-2013 - Режим доступа: http://en.wikipedia.org/wiki/GNU_Bison, свободный. - Загл. с экрана.

Размещено на Allbest.ru


Подобные документы

  • Структура, классификация и требования к реализации компилятора. Проектирование и реализация анализирующей части компилятора языка С++. Способы реализации лексического анализа. Алгоритм работы синтаксического анализатора. Принципы программной реализации.

    курсовая работа [774,2 K], добавлен 26.01.2013

  • Функции компилятора как системной обрабатывающей программы. Этапы компиляции: анализ и синтез. Разработка лексического анализатора. Алгоритм и программа лексического анализа. Реализация двухфазного компилятора. Описание логической структуры программы.

    курсовая работа [310,4 K], добавлен 26.03.2010

  • Конструкции условных операторов if-else и простые типы языка Си. Общая схема работы компилятора. Алгоритм построения дерева разбора, строки вывода синтаксического разбора. Построение обратной польской записи как формы внутреннего представления программы.

    курсовая работа [1,3 M], добавлен 01.06.2013

  • Проектирование лексического и синтаксического анализаторов учебного языка. Правила преобразования логических выражений в ПОЛИЗ. Формирование триад, оптимизация их списка. Логическая структура программы. Тестирование модулей транслятора-интерпретатора.

    курсовая работа [1,3 M], добавлен 28.05.2013

  • Взаимосвязь стадий процесса проектирования сложных программных систем. Создание компилятора подмножества языка высокого уровня (Pascal) на язык Ассемблера. Структура входных и выходных данных, алгоритмы их обработки. Рабочая документация программы.

    курсовая работа [256,7 K], добавлен 27.07.2014

  • Построение компилятора с языка высокого уровня как одного из элементов системы программирования. Разработка компилятора ассемблера, модификация базы данных исходного макета. Загрузчик, эмулятор, отладчик. Использование Flex и Bison для программирования.

    курсовая работа [599,0 K], добавлен 04.11.2014

  • Проектирование программы-анализатора, состоящей из двух частей: лексического анализатора, разбивающего исходный текст программы на лексемы и заполняющего таблицу имен; синтаксического анализатора, проверяющего соответствие текста заданной грамматике.

    курсовая работа [2,0 M], добавлен 14.06.2010

  • Задачи трансляторов, характеристика их видов. Этапы и функции основных фаз процесса компиляции. Описание используемых директив и команд ассемблера, алгоритмов, таблиц. Листинг программы. Алгоритм работы программной реализации разрабатываемого компилятора.

    курсовая работа [1,3 M], добавлен 24.06.2013

  • Программный комплекс для разработки программы транслирующей программу с языка Pascal на язык С++. Построение логической и арифметической модели решения. Разработка компилятора для программы. Методы отладки программы и создание для нее документации.

    курсовая работа [742,6 K], добавлен 03.07.2011

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

    курсовая работа [703,1 K], добавлен 08.02.2011

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.