Автор работы: Пользователь скрыл имя, 17 Апреля 2013 в 10:55, курсовая работа
Прогресс компьютерных технологий определил процесс появления новых разнообразных знаковых систем для записи алгоритмов – языков программирования. Смысл появления такого языка – оснащенный набор вычислительных формул дополнительной информации, превращает данный набор в алгоритм. Язык программирования служит двум связанным между собой целям: он дает программисту аппарат для задания действий, которые должны быть выполнены, и формирует концепции, которыми пользуется программист, размышляя о том, что делать. Первой цели идеально отвечает язык, который настолько "близок к машине", что всеми основными машинными аспектами можно легко и просто оперировать достаточно очевидным для программиста образом. Второй цели идеально отвечает язык, который настолько "близок к решаемой задаче", чтобы концепции ее решения можно было выражать прямо и коротко.
Введение. 2
Особенности языков программирования. 4
Понятие грамматики и формальное определение. Формула Бэкуса-Наура. 6
Общая схема распознавателя. 9
Основные компоненты распознавателя. 11
Классификация распознавателей по виду их компонентов. 12
Задача разбора 16
Теоретическая справка. 17
Составление формальной грамматики. 18
Построение конечного распознавателя. 19
Программное моделирование работы конечного распознавателя 20
Реализация алгоритма средствами ООП. 23
Список используемой литературы 38
Оглавление.
Введение. 2
Особенности языков программирования. 4
Понятие грамматики и формальное определение. Формула Бэкуса-Наура. 6
Общая схема распознавателя. 9
Основные компоненты распознавателя. 11
Классификация распознавателей по виду их компонентов. 12
Задача разбора 16
Теоретическая справка. 17
Составление формальной грамматики. 18
Построение конечного распознавателя. 19
Программное моделирование работы конечного распознавателя 20
Реализация алгоритма средствами ООП. 23
Список используемой литературы 38
Введение.
Язык формирует наш способ мышления и определяет то, о чем мы можем мыслить. Б. Л. Ворф
Прогресс компьютерных технологий
определил процесс появления
новых разнообразных знаковых систем
для записи алгоритмов – языков
программирования. Смысл появления
такого языка – оснащенный набор
вычислительных формул дополнительной
информации, превращает данный набор
в алгоритм. Язык программирования
служит двум связанным между собой
целям: он дает программисту аппарат
для задания действий, которые
должны быть выполнены, и формирует
концепции, которыми пользуется программист,
размышляя о том, что делать. Первой
цели идеально отвечает язык, который
настолько "близок к машине", что
всеми основными машинными
Особенности языков программирования.
Языки программирования занимают
промежуточное место между
1. определить множество допустимых символов языка;
2. определить множество правильных программ языка;
3. задать смысл каждой правильной программы.
С помощью теории формальных
языков удается решить (полностью
или частично) только первые два
вопроса. Первый вопрос решается легко.
Алфавит языка и представляет
собой множество его допустимых
символов. Для языков программирования
это, как правило, тот набор символов,
который можно ввести с клавиатуры.
Второй вопрос в теории формальных
языков решается только частично. Для
всех языков программирования существуют
синтаксические правила, но их недостаточно
для строгого определения всех возможных
синтаксических конструкций. Дополнительные
ограничения накладываются
1. изложить смысл программы, написанной на языке программирования, на другом языке, более понятном тому, кому адресована программа;
2. использовать для проверки смысла некоторую «идеальную машину», которая предназначена для проверки программ, написанных на данном языке.
Любой разработчик программ, так или иначе, использует первый подход – это комментарии в программе, построение ее блок-схемы, разработка документации или любое другое описание алгоритма. Все эти способы ориентированы на человека, но универсального способа проверить, насколько описание в действительности соответствует программе, пока не существует. Для изложения программы на языке, понятном машине – в машинных командах – существуют трансляторы. Второй подход используется при отладке программы; оценку результатов выполнения программы при отладке осуществляет человек. Разработчикам компиляторов так или иначе приходится решать вопрос о смысле программ. Во-первых, компилятору для преобразования исходной программы в последовательность машинных команд необходимо иметь представление о том, какая последовательность команд должна соответствовать той или иной части программы. Обычно такие последовательности сопоставляют базовым конструкциям входного языка – используется первый подход к изложению смысла программы. Во-вторых, многие современные компиляторы позволяют выявить сомнительные с точки зрения смысла места в исходной программе – например, недостижимые операторы, неиспользуемые переменные, неопределенные результаты функций и т.п. Обычно компилятор указывает такие места в виде предупреждений, на которые разработчик может обращать или не обращать внимание. Для этого компилятор должен иметь представление о том, как программа будет выполняться, т.е. используется второй подход. Но в любом случае осмысление исходной программы закладывает в компилятор его создатель, который руководствуется неформальными методами – как правило, описанием входного языка. В теории формальных языков вопрос о смысле программ не решается. Итак, возможности трансляторов по проверке осмысленности исходной программы практически равны нулю, поэтому семантические ошибки остаются на совести авторов программ. Выше, когда шла речь о различных способах задания языков, мы выделили как наиболее реальные второй и третий способ, а именно: задание языка с помощью генераторов и распознавателей. В качестве генераторов в общем случае могут использоваться грамматики, а для более узкого класса языков – регулярные выражения. В качестве распознавателей, как правило, применяются автоматы различных типов (в зависимости от класса языка). Рассмотрим способ задания языков с помощью грамматик.
Понятие грамматики и формальное определение. Формула Бэкуса-Наура.
Грамматика, в общем, представляет собой описание способа построения цепочек языка. Например, для естественных языков это набор правил построения различных выражений и предложений. Для многих языков (в том числе для языков программирования) возможно, использовать формализованное описание, т.е. некую математическую систему, описывающую язык. Грамматика задает правила порождения цепочек языка, следовательно, является генератором – реализует второй способ задания языка.
Формальное описание грамматики построено на основе системы правил, или продукций. Правило представляет собой упорядоченную пару цепочек символов (a,b), которую обычно записывают, как a®b и читают как «a порождает b».
Грамматика языка
Говоря далее о грамматиках языков программирования, будем иметь в виду только правила построения синтаксических конструкций языка.
Формально грамматика G определяется как четверка G(VT,VN,P,S), где VT – множество терминальных символов (символы алфавита);
VN – множество нетерминальных символов (слова, понятия, конструкции языка); VTÇVN=Æ; V=VTÈVN – полный алфавит грамматики G;
P – Множество правил вида a®b, где aÎV+, bÎV*;
SÎVN – начальный (целевой) символ грамматики G, с которого начинается процесс порождения цепочек языка.
Каждый нетерминальный символ может встречаться в цепочках как левой, так и правой частей правил, но он обязан быть хотя бы один раз в левой части хотя бы одного правила. Правила грамматики строятся таким образом, что в левой части каждого из них есть хотя бы один нетерминальный символ.
Во множестве правил грамматики может быть несколько правил, имеющих одинаковые левые части, например: a®b1, a®b2, …, a®bn. Тогда эти правила записываются в одну строку: a®b1½b2½…½bn.
Рассмотренная форма записи правил грамматики называется формой Бэкуса-Наура. В ней, как правило, нетерминальные символы заключаются в угловые скобки <>.
Пример: грамматика порождения целых десятичных чисел со знаком.
G({0,1,2,3,4,5,6,7,8,9,–,+}, {<число>,<чс>,<цифра>}, P, <число>).
P:
<число>®<чс>½+<чс>½–<чс>
<чс>®<цифра>½<чс><цифра>
<цифра>® 0½1½2½3½4½5½6½7½8½9
В данной грамматике множество нетерминальных символов содержит 3 элемента (символы <число>,<чс>,<цифра>), множество терминальных символов – 12 элементов (10 цифр и два знака), множество P – 15 правил, записанных в три строки. Начальный символ грамматики – <число>.
В грамматике можно изменить названия нетерминальных символов без какого-то изменения языка, заданного ею. Терминальные символы изменять нельзя! Они соответствуют алфавиту задаваемого языка.
Рассмотренную в примере грамматику для целых десятичных чисел со знаком можно переписать в виде:
G¢({0,1,2,3,4,5,6,7,8,9,–,+}, {S,T,F}, P, S).
P:
S ® T½+T½–T
T®F½TF
F® 0½1½2½3½4½5½6½7½8½9.
Формальные грамматики определяют
бесконечное множество цепочек
языка с помощью конечного
набора правил. Это становится возможным
благодаря использованию
В грамматиках G и G¢ явная рекурсия присутствует во второй части второго правила: <чс>®<чс><цифра>, T®TF.
Чтобы рекурсия не была бесконечной,
участвующий в ней
Явно или неявно, рекурсия всегда присутствует в грамматиках любых реальных языков программирования. Как правило, в грамматиках реального языка программирования присутствует не одно, а множество правил, построенных с помощью рекурсии.
Общая схема распознавателя.
В числе прочих задач компилятор должен определить принадлежность некоторого текста к конкретному языку. В отношении исходной программы компилятор выступает в роли распознавателя, а человек, создавший программу – в роли генератора цепочек этого языка.
Распознаватель – это специальный алгоритм, позволяющий для некоторой цепочки символов определить, принадлежит ли она заданному языку. Это один из способов задания языка.
Распознаватель входит в состав компилятора и является частью программного обеспечения компьютера.
Условная схема распознавателя имеет следующий вид:
Основные компоненты распознавателя:
Алфавит распознавателя конечен; он включает в себя все допустимые символы входных цепочек, а также некоторый дополнительный алфавит символов, которые могут обрабатываться УУ и храниться в рабочей памяти распознавателя.
В процессе своей работы распознаватель может выполнять некоторые элементарные операции, такие как чтение входного символа, сдвиг головки, доступ к рабочей памяти для чтения или записи информации, изменение состояния УУ.
Работа распознавателя состоит из последовательности шагов, или тактов. То, каким должен быть этот такт, определяется текущим входным символом, состоянием УУ и символом, извлеченным из памяти. Итак,
Такт состоит из следующих моментов:
В процессе работы распознавателя происходит смена конфигураций. Конфигурация распознавателя (мгновенное описание) определяется следующими параметрами:
Конфигурация называется
начальной, если УУ находится в начальном
состоянии, входная головка обозревает
самый левый символ на входной
ленте, а память имеет заранее
установленное начальное