Конструирование модели лексического и синтаксического анализа

Проведение исследования лексем в языках программирования. Построение регулярной грамматики по конечному автомату. Характеристика логического и физического проектирования. Изучение связи между контекстно-свободными грамматиками и синтаксическим анализом.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 23.05.2021
Размер файла 2,7 M

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

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

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

2

Институт информационных технологий

Кафедра Математического и программного обеспечения ЭВМ

направление подготовки (специальности)

Информационные системы и технологии

КУРСОВАЯ РАБОТА

по дисциплине Теория автоматов и формальных языков

на тему Конструирование модели лексического и синтаксического анализа

Выполнил студент группы

1ИСб-00-21оп

Фурсов Георгий Алексеевич

Руководитель

Ганичева Оксана Георгиевна

Череповец, 2020

Оглавление

Введение

1. Описание и анализ предметной области

1.1 Описание предметной области

1.2 Анализ предметной области

2. Конструирование модели лексического анализа

2.1 Лексический анализ

2.2 Построение конечного автомата

2.3 Построение регулярной грамматики по конечному автомату

3. Построение лексического анализатора

3.1 Определение лексического анализатора

3.2 Моделирование работы лексического анализатора

3.3 Логическое проектирование

3.4 Физическое проектирование

4. Конструирование модели синтаксического анализа

4.1 Связь между КС-грамматиками и синтаксическим анализом

4.2 Построение КС-грамматики

4.3 Построение дерева разбора

Заключение

Список литературы

Приложения

Введение

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

Как правило, лексический анализ производится с точки зрения определённого формального языка или набора языков. Язык, а точнее его грамматика, задаёт определённый набор лексем, которые могут встретиться на входе процесса.

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

Синтаксический анализ -- это процесс сопоставления линейной последовательности лексем (слов) естественного или формального языка с его формальной грамматикой. Результатом обычно является дерево разбора (синтаксическое дерево). Обычно применяется совместно с лексическим анализом.

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

Простейший способ реагирования на некорректную входную цепочку лексем -- завершить синтаксический анализ и вывести сообщение об ошибке. Однако часто оказывается полезным найти за одну попытку синтаксического анализа как можно больше ошибок. Именно так ведут себя трансляторы большинства распространённых языков программирования.

1. Описание и анализ предметной области

1.1 Описание предметной области

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

Лексема -- это структурная единица языка, которая состоит из элементарных символов языка и не содержит в своем составе других структурных единиц языка. Ярчайшим примером лексем в повседневной жизни служат слова русского языка.

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

Лексемы представляют собой набор, последовательность символов кода, которая соответствует шаблону. Шаблон - правило, описывающее набор лексем, которые могут представлять определенную лексему в исходной программе.

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

Лексический анализ включают в состав практически всех компиляторов по следующим причинам:

• применение лексического анализатора упрощает работу с текстом исходной программы на этапе синтаксического разбора и сокращает объем обрабатываемой информации;

• для выделения в тексте и разбора лексем применяется простая и эффективная техника анализа, в то время как на этапе синтаксического анализа конструкций исходного языка используются достаточно сложные алгоритмы разбора;

• при конструкции компилятора, когда лексический анализ реализован отдельно от синтаксического, для перехода от одной версии языка программирования к другой достаточно только перестроить относительно простой лексический анализатор

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

Таким образом, можно выделить следующие функции лексического анализатора:

• исключение из текста исходной программы комментариев;

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

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

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

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

• последовательный;

• параллельный.

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

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

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

В основе анализатора лежит распознаватель текста кода программы на основе некой грамматики. Синтаксические конструкции языков могут быть описаны через контекстно-свободные (КС) грамматики, однако существуют и языки, описываемые с помощью регулярной грамматики. Чаще всего языки высокого уровня построены на основе синтаксиса именно КС-языков. [4]

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

Синтаксический разбор -- это основная часть компилятора на этапе анализа. Без выполнения синтаксического разбора работа компилятора бессмысленна, в то время как лексический разбор в принципе является необязательной фазой. Все задачи по проверке синтаксиса входного языка могут быть решены на этапе синтаксического разбора. Лексический анализатор только позволяет избавить сложный по структуре синтаксический анализатор от решения примитивных задач по выявлению и запоминанию лексем входной программы. [4]

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

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

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

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

• Грамматика дает точную и при этом простую для понимания синтаксическую спецификацию языка программирования.

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

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

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

1.2 Анализ предметной области

Входящая последовательность - исходный код программы (рис. 1). В коде присутствуют массивы String Char, Int, Float, а так же указатели и ссылки “*”. Программа, работающая по исходному коду, в качестве результата выводит сначала размер массива после выводит массив рандомных чисел от 0 до 10 (рис. 2). В ходе лексического анализа должны быть выделены лексемы каждого класса, в том числе ключевых слов. Также в ходе анализа должны быть обнаружены ошибки в написании лексем, если таковые имеются. Синтаксический анализ на основе грамматики проверит правильность написания с точки зрения синтаксиса.

#include <iostream>

#include <string>

#include <ctime>

using namespace std;

void opF(int* ar, int* gogo) {

*gogo += *ar;

}

int main()

{

srand(time(NULL));

int m = 0;

int arr[5] = { 3,4,2 };

string mas ="awd";

for (int i = 0; i <2; i++)

{

opF(& arr[i], &m);

}

float *m1 = new float[m];

for (int y = 0; y < m; y++) {

m1[y] = rand() % 10;

cout <<"_"<<m1[y];

}

}

2. Конструирование модели лексического анализа

2.1 Лексический анализ

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

Каждый класс лексем описывается правилом, называемым шаблоном. Шаблон соответствует каждой строке в наборе-классе лексем. Лексема же представляет собой последовательность символов исходной программы, которая соответствует шаблону.

2.2 Построение конечного автомата

Граф конечного автомата представлен в п. 2.3, рис. 1

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

Конечный автомат состоит из пяти компонентов следующего вида:

А = (X, S, F, S0, д), где:

- X - конечное непустое множество входных символов;

- S - конечное непустое множество состояний;

- F - множество выделенных заключительных состояний;

- S0 - начальное состояние;

- д - функция перехода конечного автомата (X*S > S).

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

X: ( 0..9, a..z, A..Z,

операторы - {+, -, *, /, %, =, !, ++,--,+=,-=,*=, << , >>},

сравнения - {>, <,<=,>=,==,!=,||,&&},

пунктуации - {;, (, ), [, ], {, }, “.”, “,”, “})

F: {S1, S2, S301, S305, S100, S101}

S: (S0, S1, S2, S3, S4, S5, S6, S7, S8, S9, S10, S11, S12, S13, S14, S15, S16, S17, S18, S19, S20, S21, S22, S23, S24, S25, S26, S27, S28, S29, S30, S31, S32, S33, S34, S35, S36, S37, S38, S39, S40, S41, S42, S43, S47, S48, S49, S50, S60, S61, S62, S63, S64, S65, S66, S67, S68, S69, S70, S71, S100, S101, S200, S300, S301, S302, S305, S400, S401)

д: функция переходов конечного автомата представлена в таблице (табл. 1):

Таблица 1. Функция д

(S2, a..z, A..Z) >S2

(S3..S99, a..z, A..Z )>S200

(S3..S99,пунктуация )>S0

(S3..S99,операторы )>S300

(S, c )> S3

(S3, o)> S34

(S20, a)> S21

(S41, a)> S42

(S0, b)> S6

(S3, i)> S43

(S21, t)> S1

(S42, i)> S43

(S0, e)> S11

(S3, a)> S69

(S22, t)> S23

(S43, n)> S1

(S0, i)> S16

(S4, a)> S5

(S22, w)> S64

(S47, e)> S48

(S0, f)> S18

(S5, r)> S1

(S22, y)> S36

(S47, a)> S49

(S0, s)> S22

(S6, o)> S7

(S23, r)> S24

(S48, w)> S1

(S0, v)> S31

(S7, o)> S7

(S24, i)> S25

(S49, m)> S50

(S0, m)> S41

(S7, l)> S1

(S25, n)> S26

(S49, m)> S50

(S0, d)> S56

(S6, r)> S8

(S26, g)> S1

(S50, e)> S51

(S0, r)> S61

(S8, e)> S9

(S27, l)> S28

(S51, s)> S52

(S0, n)> 47

(S9, a)> S10

(S28, u)> S29

(S52, p)> S53

(S0, a..z, A..Z)>S2

(S10, k)> S1

(S29, d)> S30

(S53, a)> S54

(S0,0..9)> S100

(S11, n)> S12

(S29, d)> S1

(S54, c)> S55

(S0, “(“ )> S400

(S12, d)> S13

(S30, e)> S1

(S55, e)> S1

(S0, “)” )> S400

(S13, l)> S1

(S31, o)> S32

(S56, o)> S57

(S0, { )> S400

(S11, l)> S14

(S32, i)> S33

(S57, u)> S58

(S0, })> S400

(S14, s)> S15

(S33, d)> S1

(S58, b)> S59

(S0, [ )> S400

(S15, e)> S1

(S34, u)> S35

(S59, l)> S60

(S0, ])> S400

(S16, n)> S17

(S35, t)> S1

(S60, e)> S1

(S0, ;)> S400

(S17, t)> S1

(S36, s)> S37

(S61, a)> S62

(S0,”:”)>S400

(S17, c)> S27

(S37, t)> S38

(S62, n)> S63

(S0,”,”)> S400

(S18, l)> S19

(S38, e)> S39

(S63, d)> S1

(S0, “.”)> S400

(S18, o)> S40

(S39, m)> S1

(S64, i)> S65

(S3,v)> S4

(S19, o)> S20

(S40, r)> S1

(S65, t)> S66

(S300, *=)>S301

(S0, !)> S300

(S0, <)> S300

(S66, c)> S67

(S300, >>)> S301

(S0, &)> S300

(S0, +) > S300

(S300, <<)> S301

(S0, >)> S300

(S0, -)> S300

(S300, ++)> S301

(S0, 0..9)> S100

(S0, *)> S300

(S300, --)> S301

(S100, 0..9)> S100

(S0, =)> S300

(S300, +=)> S301

(S100, “.”)> S101

(S0, /)> S300

(S300, -=)> S301

(S101, 0..9)> S101

(S1, /)> S300

2.3 Построение регулярной грамматики по конечному автомату

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

По конечному автомату A = (X, S, F, S0, д) можно построить регулярную грамматику G = < N, T, P, S >, где:

T = X - конечное непустое множество терминальных символов.

N = S - конечное непустое множество нетерминальных символов

S - стартовый символ грамматики;

P - конечное множество правил грамматики - продукции.

Множество правил подстановки Р строится таким образом: каждой команде автомата (Si, a) > Sj ставится в соответствие правило подстановки Si > а Sj, если Sj ? S, либо Si > а , если Sj ? F, где F- заключительное состояние.

Построение регулярной грамматики по описанному конечному автомату:

По приведённому выше конечному автомату была сформирована следующая регулярная грамматика:

G = (N, T, S, P)

T: ( 0..9, a..z, A..Z, +, -, *, /, %, =, !, ++,--,+=,-=,*=, << , >>,>, <,<=,>=,==,!=,||,&&,;, (, ), [, ], {, }, “.”, “,”, “)

N:

S0 - начало считывания лексемы

S3…S99 - посимвольное считывание ключевого слова

S400, S401 - пунктуация

S3…S45 - cin

S3…S35 - cout

S3…S5 - char

S3…S68 - case

S6…S10 - break

S6…S8 - bool

S11…S15 - else

S11…S13 - endl

S18…S21 - float

S18…S40 - for

S56…S60 -double

S16…S31 - include

S16…S17 - int

S47…S48 - new

S47…S55 - namespace

S22…S39 - system

S22…S26 - string

S22…S67 - switch

S31…S33 -void

S41…S43 -main

S61…S63 - rand

S1 -проверка ключевых слов на правильность написания, добавление их в таблицу

S200 -проверка написания идентификатора и добавление его в таблицу

S300 - начало распознавания лексемы оператора

S300 - начало распознавания лексемы оператора “+,-,=,*,&,/,<,>,!”, добавление лексемы в таблицу

S301 - распознавания лексемы оператора, добавление лексемы в таблицу

“++,--,+=,-=,*=, <=,>=,==,!=,||,&&”

S302 - ошибка в написании оператора

S100 - распознавание лексемы целочисленной константы, запись её в таблицу. Ошибки в написании лексемы

S101 - распознавание лексемы константы с плавающей запятой, запись её в таблицу. Ошибки в написании лексемы

S:S0

P: Множество продукций представлено в таблице (табл. 2).

Таблица 2. Множество продукций

S0> c

S300> +=

S13> l S1

S36> s

S0> b

S300> -=

S11> l

S37> t

S0> e

S0>! S300

S14> s

S38> e

S0> i

S0> & S300

S15> e S1

S39> m

S0> f

S0> > S300

S16> n

S40> r S1

S0> s

S0> 0..9

S17> t S1

S41> a

S0> v

S100> 0..9

S17> c

S42> i

S0> m

S100>. S101

S18> l

S43> n S1

S0> d

S101> 0..9 S101

S18> o

S47> e

S0> r

S0> + S301

S19> o

S47> a

S0> n

S0> - S301

S20> a

S48> w S1

S0>(a..z, A..Z)

S0> * S300

S21> t S1

S49> m

S0> (0..9)

S0> = S300

S22> t

S50> e

S0>( S400

S0> /S300

S22> w

S51> s

S0>) S400

S3> o

S22> y

S52> p

S0>{ S400

S3> v

S23> r

S53> a

S0>} S400

S3> i

S24> i

S54> c

S0>[ S400

S3> a

S25> n

S55> e S1

S0>] S400

S4> a

S26> g S1

S56> o

S0>; S400

S5>r S1

S27> l

S57> u

S0>: S400

S6> o

S28> u

S58> b

S0>, S400

S7> o

S29> d

S59> l

S0>. S400

S7> l S1

S29> d S1

S60> e S1

S0> < S300

S7> r

S30> у S1

S61> a

S300>*=

S8> e

S31> o

S62> n

S300> -=

S9> a

S32> i

S63> d S1

S300> +=

S10> k S1

S33> d S1

S64> i

S300> ++ S301

S11> n S12

S34> u S35

S65> t

S300> -- S301

S12> d S13

S35> е S1

S66> c

S0> > S300

S0> & S300

S0> * S300

S0> ! S300

Таблица 3. Совмещенная таблица продукций и переходов

КА

РГ

КА

РГ

(S0, c )> S3

S0> c S3

(S13, l)> S1

S13> l S1

(S0, b)> S6

S0> b S6

(S11, l)> S14

S11> l S14

(S0, e)> S11

S0> e S11

(S14, s)> S15

S14> s S15

(S0, i)> S16

S0> i S16

(S15, e)> S1

S15> e S1

(S0, f)> S18

S0> f S18

(S16, n)> S17

S16> n S17

(S0, s)> S22

S0> s S22

(S17, t)> S1

S17> t S1

(S0, v)> S31

S0> v S31

(S17, c)> S27

S17> c S27

(S0, m)> S41

S0> m S41

(S18, l)> S19

S18> l S19

(S0, d)> S56

S0> d S56

(S18, o)> S40

S18> o S40

(S0, r)> S61

S0> r S61

(S19, o)> S20

S19> o S20

(S0, n)> S47

S0> n S47

(S20, a)> S21

S20> a S21

(S0,a..z,A..Z)>S2

S0>(a..z,A..ZS2

(S21, t)> S1

S21> t S1

(S0,0..9)> S100

S0> (0..9) S100

(S22, t)> S23

S22> t S23

(S0, “(“ )> S400

S0>(

(S22, w)> S64

S22> w S64

(S0, “)” )> S400

S0>)

(S22, y)> S36

S22> y S36

(S0, { )> S400

S0>{

(S23, r)> S24

S23> r S24

(S0, })> S400

S0>}

(S24, i)> S25

S24> i S25

(S0, [ )> S400

S0>[

(S25, n)> S26

S25> n S26

(S0, ])> S400

S0>]

(S26, g)> S1

S26> g S1

(S0, ;)> S400

S0>;

(S27, l)> S28

S27> l S28

(S0,”:”)>S400

S0>:

(S28, u)> S29

S28> u S29

(S0,”,”)> S400

S0>,

(S29, d)> S30

S29> d S30

(S0, “.”)> S400

S0>.

(S29, d)> S1

S29> d S1

(S0, <)> S300

S0> < S300

(S30, e)> S1

S30> у S1

(S300, *=)> S301

S300>*=

(S31, o)> S32

S31> o S32

(S300, -=)> S301

S300> -=

(S32, i)> S33

S32> i S33

(S300, +=)> S301

S300> +=

(S33, d)> S1

S33> d S1

(S300, ++)> S301

S300> ++

(S34, u)> S35

S34> г S35

(S300, --)> S301

S300> --

(S35, t)> S1

S35> е S1

(S300, +=)> S301

S300> +=

(S36, s)> S37

S36> s S37

(S300, -=)> S301

S300> -=

(S37, t)> S38

S37> t S38

(S0, !)> S300

S0>! S300

(S38, e)> S39

S38> e S39

(S0, &)> S300

S0> & S300

(S39, m)> S1

S39> m S1

(S0, >)> S300

S0> > S300

(S40, r)> S1

S40> r S1

(S0, 0..9)> S100

S0> 0..9

(S41, a)> S42

S41> a S42

(S100, 0..9)> S100

S100> 0..9

(S42, i)> S43

S42> i S43

(S100, “.”)> S101

S100>. S101

(S43, n)> S1

S43> n S1

(S101,0..9)> S101

S101> 0..9

S101

(S47, e)> S48

S47> e S48

(S0, +) > S300

S0> + S300

(S47, a)> S49

S47> a S49

(S0, -)> S300

S0> - S300

(S48, w)> S1

S48> w S1

(S0, *)> S300

S0> * S300

(S49, m)> S50

S49> m S50

(S0, =)> S300

S0> = S300

(S50, e)> S51

S50> e S51

(S0, /)> S300

S0> /S300

(S51, s)> S52

S51> s S52

(S0, > )> S300

S0> > S300

(S0, ! )> S300

S0> ! S300

(S0, & )> S300

S0> & S300

(S0, < )> S300

S0> < S300

(S3, o)> S34

S3> o S34

(S52, p)> S53

S52> p S53

(S3,v)> S4

S3> v S4

(S53, a)> S54

S53> a S54

(S3, i)> S43

S3> i S43

(S54, c)> S55

S54> c S55

(S3, a)> S69

S3> a S69

(S55, e)> S1

S55> e S1

(S4, a)> S5

S4> a S5

(S56, o)> S57

S56> o S57

(S5, r)> S1

S5>r S1

(S57, u)> S58

S57> u S58

(S6, o)> S7

S6> o S7

(S58, b)> S59

S58> b S59

(S7, o)> S7

S7> o S7

(S59, l)> S60

S59> l S60

(S7, l)> S1

S7> l S1

(S60, e)> S1

S60> e S1

(S6, r)> S8

S7> r S8

(S61, a)> S62

S61> a S62

(S8, e)> S9

S8> e S9

(S62, n)> S63

S62> n S63

(S9, a)> S10

S9> a S10

(S63, d)> S1

S63> d S1

(S10, k)> S1

S10> k S1

(S64, i)> S65

S64> i S65

(S11, n)> S12

S11> n S12

(S65, t)> S66

S65> t S66

(S12, d)> S13

S12> d S13

(S66, c)> S67

S66> c S67

3. Построение лексического анализатора

3.1 Определение лексического анализатора

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

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

* применение лексического анализатора упрощает работу с текстом исходной программы на этапе синтаксического разбора и сокращает объем обрабатываемой информации;

* для выделения и разбора лексем применяется простая и эффективная техника анализа, в то время как на этапе синтаксического анализа используются достаточно сложные алгоритмы разбора;

* при конструкции компилятора, когда лексический анализ реализован отдельно от синтаксического, для перехода от одной версии языка программирования к другой достаточно перестроить только лексический анализатор.

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

Таким образом, можно выделить следующие основные функции лексического анализатора:

• исключение из текста исходной программы комментариев;

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

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

• выявление ошибок в написании лексем, сообщение об ошибках (с указанием позиции и типа ошибки).

3.2 Моделирование работы лексического анализатора

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

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

Рис. 1. Блок-схема алгоритма удаления комментариев, незначащие пробелы, пустые строки

Рис. 2. Блок-схема алгоритма записи лексем в таблицу

3.3 Логическое проектирование

3.4 Физическое проектирование

Имя модуля

Заголовок процедуры или функции

Формальные параметры

Выполняемое действие

Project

punctz

wchart

Проверка, является ли символ знаком пунктуации

digit

Проверка, является ли символ десятичной цифрой

o_perat

Проверка, является ли символ знаком операции

o_perat1

int

проверяет правильность написания знака операции

word

wchart

Проверка, является ли символ буквой латинского алфавита или нижним подчёркиванием

delet_problem

-

Начало обработки кода, записанного в richTextBox1, удаление комментариев и пустых строк

programm

-

распределение по классам лексем

constant, punctuation, ident, o_peratr_sravn, o_peratr, keyWord

int

формирование дескрипторного и псевдокодов

button2_Click

object sender EventArgs e

Проверка и вывод ошибок

button1_Click

object sender EventArgs e

Начало работы, проверка на ошибки

В ходе выполнения реализации лексического анализатора были:

создана автоматная модель работы лексического анализатора. Описание модели см. в п. 2.2.2. Граф автомата см. в п. 2.3.4, рис. 1;

на основе автоматной модели создана регулярная грамматика. Описание грамматики см. в п. 2.2.3;

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

• исключение из текста исходной программы комментариев;

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

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

• выявление ошибок в написании лексем, сообщение об ошибках (с указанием позиции и типа ошибки);

• формирование дескрипторного кода и псевдокода.

Результаты работы программы (см. след. стр.):

Рис.3.Интерфейс приложения.

На рис. 3 изображён интерфейс приложения. В текстовую область слева в верху заносится обрабатываемый код. После нажатия кнопки «start processing» запускается обработка. Результаты следующие:

• в текстовой области, ниже выделенной, выводится первичное представление кода - без комментариев, пустых строк и лишних пробелов;

• в таблицах в нижней части интерфейса выводятся лексемы, распределённые по соответствующим классам (ключевые слова, операторы и операторы сравнения, идентификаторы, знаки пунктуации, константы);

• в текстовых областях в правой части интерфейса выводятся дескрипторный код (верхняя) и псевдокод (нижняя) (чтобы точнее определиться с местоположением текстовых областей они подписываются);

• Также можно выполнить полную диагностику кода на наличие ошибок нажатием на кнопку «error processing» (рисунок 4. в нижнем правом текстовом блоке выводиться информация об ошибках).

Обработка лексических ошибок:

На рисунках 5-8 показан вывод сообщения об ошибке. После нажатия копки «start processing» запускается обработка кода, при нахождении ошибки появляется дополнительное окно с информацией о ошибке, а именно:

1. строка ошибки

2. название ошибки

3. лексема с ошибкой

На рисунках 4, 9-13 показан вывод сообщения об всех имеющихся ошибках. После нажатия копки «error processing» запускается анализ кода на наличие ошибок. В конце обработки кода выводиться сообщение о всех имеющихся ошибках в нижнем правом текстовом блоке.

Рисунок 4 информация об ошибках

Рисунок 5 вывод сообщения об ошибке

Рисунок 6 вывод сообщения об ошибке

Рисунок 7 вывод сообщения об ошибке

Рисунок 8 вывод сообщения об ошибке

Рисунок 9 вывод информации об ошибках

Рисунок 10 вывод информации об ошибках

Рисунок 11 вывод информации об ошибках

Рисунок 12 вывод информации об ошибках

Рисунок 13 вывод информации об ошибках

4. Конструирование модели синтаксического анализа

4.1 Связь между КС-грамматиками и синтаксическим анализом

Синтаксический анализ -- это процесс сопоставления линейной последовательности лексем (слов) естественного или формального языка с его формальной грамматикой. Результатом обычно является дерево разбора (синтаксическое дерево). Обычно применяется совместно с лексическим анализом.

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

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

Основу любого синтаксического анализатора всегда составляет распознаватель, построенный на основе какого-либо класса КС-грамматик. Анализатор воспринимает выход лексического анализатора и разбирает его в соответствии с грамматикой входного языка.

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

* Грамматика дает точную и при этом простую для понимания синтаксическую спецификацию языка программирования.

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

* Правильно построенная грамматика придает языку программирования структуру, которая способствует облегчению трансляции исходной программы в объектный код, выявлению ошибок. Для преобразования описаний трансляции, основанных на грамматике языка, в рабочие программы имеется соответствующий программный инструментарий.

* Со временем языки эволюционируют, обогащаясь новыми конструкциями, и выполняют новые задачи. Добавление конструкций в язык окажется более простой задачей, если существующая реализация языка основана на его грамматическом описании.

4.2 Построение КС-грамматики

V> IV| HV | GV | JV | BV | YV | CV | SV | AV | J | B | A | A[id]V

A > | Include| iostream| string| ctime| void| int| for| new| cout| endl |A id| id

G> using namespace std Y| G1 G

G1># include <A>

I>A*id=new A[id]; |A id=const; | A id[const]; | A id[const]={id}; | id[const]|

A id=”id”;

J> JV|(V)|{V}|”V”|<V>|( )

B> A[V] |Y|C |const

Id >K const |K|* id| & id| id C const| id C id Y

C>S=|S|++|--|>>|<<|%

S >+|-|=|<|>|!

Y>,|.|:|;

K> a..z |A..Z

const >0..9|const 0..9

H> for (A id=const; id C const; id C)|A id J|A(V);|A<<”_”<<I

4.3 Построение дерева разбора

Построение порождени для данной синтаксической конструкции.

#include <iostream>

#include <string>

#include <ctime>

using namespace std;

void opF(int* ar, int* gogo) {

*gogo += *ar;

}

int main()

{

srand(time(NULL));

int m = 0;

int arr[5] = { 3,4,2 };

string mas ="awd";

for (int i = 0; i <2; i++)

{

opF(& arr[i], &m);

}

float *m1 = new float[m];

for (int y = 0; y < m; y++) {

m1[y] = rand() % 10;

cout <<"_"<<m1[y];

}}

V=>GV=>

G1 G V=>

# include <A> G V=>

# include <iostream> G V=>

# include <iostream> G1 G V=>

# include <iostream> # include <A> G V=>

# include <iostream> # include <string> G V=>

# include <iostream> # include <string> G1 G V=>

# include <iostream> # include <string> # include <A> G V=>

# include <iostream> # include <string> # include <ctime> G V=>

# include <iostream> # include <string> # include <ctime> using namespace std Y V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; HV=>

# include <iostream> # include <string> # include <ctime> using namespace std ;A id JV=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void id JV=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF JV=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (AV)V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (A id V)V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (intid V)V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *id V)V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar V )V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar YV)V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , V)V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar ,A)V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , A id )V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int id)V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int*id)V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo)JV=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){V}V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){A}V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){id}V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){ id C id Y }V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){ *id C id Y }V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){ *gogo C id Y }V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){ * gogo S= id Y }V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo += id Y }V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id Y}V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar Y}V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar ;}V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}HV=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}A id JV=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int id JV=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main JV=>

# include <iostream> # include <string> # include <ctime> using namespace std ;

Void opF (int *ar , int * gogo){* gogo +=*ar;}int main ()V=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main ()J=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main (){V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main (){HV}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main (){A (V); V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main (){srand(V);V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main (){srand (AV);V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main (){srand (time V);V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main (){srand (time J);V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main (){srand (time (V));V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main (){srand (time (A));V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main (){srand (time (id));V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*ar;}int main (){srand (time (NULL));V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));IV}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL)); A id=const;V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL)); int id=const;V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL)); int m=const;V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ;V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ;IV}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; A id[const]={id}; V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int id[const]={id}; V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [const]={id}; V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3]={id}; V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;IV}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ; A id= ”id”;V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string id= ”id”;V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas= ”id”;V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas= ”awd” ;V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas=”awd” ;HV}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas= ”awd” ;for (A id=const; id C const; id C)V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas=”awd” ;for (int id=const; id C const; id C)V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas=”awd” ;for (int i=const; id C const; id C)V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas=”awd” ;for (int i=0; id C const; id C)V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas=”awd” ;for (int i=0; I C const; id C)V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas=”awd” ;for (int i=0; I S const; id C)V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas=”awd” ;for (int i=0; I < const; id C)V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas=”awd” ;for (int i=0; I < 2; id C)V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas=”awd” ;for (int i=0; I < 2; I C)V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas=”awd” ;for (int i=0; I < 2; I ++)V}=>

# include <iostream> # include <string> # include <ctime> using namespace std ; Void opF (int *ar , int * gogo){* gogo +=*id;}int main (){srand (time (NULL));intm =0 ; int arr [3] = { 3,4,2} ;string mas=”awd” ;for (int i=0; I < 2; I ++)JV}=>


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

  • Разработка учебного транслятора на языке программирования C# в среде объектно-ориентированного программирования Visual Studio 2012. Выделение лексем и построение цепочки символов на этапе синтаксического анализа. Функциональное тестирование программы.

    курсовая работа [406,8 K], добавлен 07.08.2013

  • Содержательная часть языка программирования С++. Правила автоматной грамматики, классификация Хомского. Принцип построения графов, разработка проекта средствами среды программирования Builder C++. Алгоритм синтаксического анализа оператора вывода.

    контрольная работа [228,4 K], добавлен 22.05.2012

  • Описание синтаксиса и семантики входного языка. Описание типов лексем, определение их синтаксиса. Построение диаграммы лексического анализатора, а также его таблицы, тестирование. Построение КС-грамматики входного языка. Описание промежуточного языка.

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

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

    курсовая работа [761,5 K], добавлен 23.02.2012

  • Понятие синтаксического анализа. Программный продукт для обработки данных строкового типа. Построение сканера текстов с использованием утилиты flex, синтаксического анализатора с помощью утилиты bison. Грамматика языка программирования обработки строк.

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

  • Морфологические анализаторы (морфологизаторы) на различных языках программирования. Анализ методов и технологий автоматической обработки ЕЯ-текстов. Разработка модуля графематического анализа и создания таблицы лексем. Программная реализация классов.

    дипломная работа [3,0 M], добавлен 06.03.2012

  • Общая характеристика и оценка возможностей языка программирования си-шарп, его сходные и отличительные черты от С++ и Java. Разработка с помощью данного языка программирования лексического и синтаксического анализатора. Составление таблиц разбора.

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

  • Входная грамматика в структурированной форме. Функции переходов символьного преобразователя. Работа лексического анализатора. Структуры данных, символы действия. Описание семантики перевода. Построение и программная реализация атрибутного преобразователя.

    курсовая работа [128,9 K], добавлен 03.07.2013

  • Розробка операційного автомату. Розробка машинного алгоритму: граф-схема алгоритму; приклад реалізації. Синтез керуючого автомату: основи теорії керуючих автоматів; опис керуючого автомату Мілі. Кодування граф-схеми автомату. Синтез керуючого автомату.

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

  • Описание проектного решения стратегической системы, этапы объектно-ориентированного анализа и проектирования. Описание связей между объектами. Программная реализация, построение модели состояний объекта. Руководство пользователя и описание программы.

    курсовая работа [388,8 K], добавлен 17.11.2011

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