Разработка инструментальных средств создания текстовых предметно-ориентированных языков: компонент проверки синтаксиса

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

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

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

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

К квалификации персонала системы предъявляются следующие требования:

1. Пользователь должен знать данную предметную область.

2. Иметь минимальные навыки работы с вычислительной техникой, навыки работы с аналитическими приложениями.

Режимы работы конечного пользователя обуславливается его рабочим графиком.

И.1.4. Перечень эксплуатационной документации

Перечень документов, с которыми следует ознакомиться перед эксплуатацией:

1. Руководство пользователя.

2. Руководство администратора (см. прил. К).

И.2. Назначения и условия применения

И2.1. Виды деятельности, функции

Языковой инструментарий предназначен для упрощения процесса создания текстовых DSL, в частности за счет следующих показателей, реализуемых в результате применения инструментария:

1. Предоставление визуального представления конструкций языка и программы с помощью выделения их цветом.

2. Оптимизация процесса проверки корректности программы относительно созданного языка.

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

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

Перечень функций, реализованных в системе, приведен в разделе И1.2 текущего документа.

И.2.2. Программные и аппаратные требования к системе

Система должна использоваться на ПК со следующими операционными системами: Windows XP, Windows 7, Windows 8, Windows 10.

В состав технических средств должен входить:

1. IBM-совместимый персональный компьютер (ПЭВМ), включающий в себя:

1.1. Процессор Pentium - 4 с тактовой частотой 1.2 ГГц, не менее.

1.2. Оперативную память объемом, 512 Mб, не менее.

1.3. Жесткий диск объемом 40 Гб, и выше.

1.4. Оптический манипулятор типа «мышь».

2. Локальная сеть. Пропускная способность ЛС до 1Гб/сек.

И.3. Подготовка к работе

И.3.1. Запуск системы

Для работы с языковым инструментарием сначала необходимо открыть папку, в которую была установлена система, и запустить файл EBNF.exe.

И.3.2. Проверка работоспособности системы

Система работоспособна, если при выполнении действий, описанных в пункте И.3.1. настоящего документа, открылось главное окно редактора кода без выдачи сообщения об ошибках на экран пользователя.

И.4. Описание операций

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

Рисунок И.1. Главное окно системы

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

Контекстное меню для браузера проектов (вызывается с помощью нажатия правой кнопкой мыши по пустой области браузера):

1. Создать решение - создает новое решение с заданным именем.

2. Загрузить решение извне - позволяет создать новое решение с заданным именем и загрузить в него все созданные языки из выбранной папки.

3. Загрузить решение извне полностью - позволяет создать новое решение с заданным именем и загрузить в него все созданные языки и программы из выбранной папки.

Контекстное меню для решений (вызывается с помощью нажатия правой кнопкой мыши по выбранному решению):

1. Редактировать - открывает на редактирование все созданные языки в данном решении.

2. Редактировать все - открывает на редактирование все созданные языки и программы в данном решении.

3. Загрузить в репозиторий извне - загружает в данное решение выбранный язык.

4. Загрузить в репозиторий извне все - загружает в данное решение выбранный язык со всеми спроектированными программами.

5. Переименовать - изменяет имя решения на заданное.

6. Удалить - удаляет решение из браузера проектов.

7. Создать модель - создает новый язык.

Контекстное меню для языков (вызывается с помощью нажатия правой кнопкой мыши по выбранному языку).

1. Редактировать - открывает на редактирование данный язык.

2. Редактировать все - открывает на редактирование данный язык и все созданные на его основе программы.

3. Загрузить в репозиторий извне - загружает в данный язык выбранную программу.

4. Переименовать - изменяет имя языка на заданное.

5. Удалить - удаляет язык из браузера проектов.

6. Создать модель - создает новую программу.

Контекстное меню для программ (вызывается с помощью нажатия правой кнопкой мыши по выбранной программе).

1. Редактировать - открывает на редактирование данную программу.

2. Переименовать - изменяет имя программы на заданное.

3. Удалить - удаляет программу из браузера проектов.

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

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

Язык и программа считаются корректно спроектированными, если в области ошибок не появилось ни одного уведомления, а также индикаторы корректности горят зеленым цветом (рис. И.2):

Рисунок И.2. Пример корректного языка

При создании языка и программы строка в которой обнаружена ошибка и индикатор корректности подсвечиваются красным цветом (см. рис. И.3)

Рисунок И.3. Пример некорректной программы

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

Рисунок И.4. Список ожидаемых символов

И.5. Аварийные ситуации

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

Приложение К. Руководство системного программиста

Языковой инструментарий: компоненты описания и проверки синтаксиса Руководство системного программиста

Номер документа

На 3 листах

Действует с «___»________2017 г.

Пермь 2017

К.1. Общие сведения о системе

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

Основные функции системы:

1. Создание решения, языка и программы.

2. Подсветка синтаксиса языка и программы на основе формально заданных правил.

3. Проверка языка на наличие лексических, синтаксических и семантических ошибок.

4. Проверка программы на наличие синтаксических ошибок относительно спроектированного языка.

5. Отображение списка ожидаемых терминальных символов для конструкции языка в момент редактирования программы.

6. Сохранение, загразка, удаление и переименование решений, языков и программ в репозитории.

К.2. Структура программы

Архитектура системы состоит из нескольких компонентов (см. рис. К.1):

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

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

3. Репозиторий - набор XML файлов на жестком диске с определенным расширением, зависящим от уровня сохраняемого объекта: решение, язык, программа.

4. Браузер проектов - позволяет управлять репозиторием: редактировать, сохранять, удалять, добавлять, переименовывать решения, языки и программы.

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

Рисунок К.1. Архитектура системы

Связь между лексическим и синтаксическим анализаторами можно представить на примере диаграмм последовательности для бизнес-процессов редактирования языка и программы (рис. К.2, см. рис. К.3).

Рисунок К.2. Диаграмма последовательности «Редактирование языка»

Рисунок К.3. Диаграмма последовательности «Редактирование программы»

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

К.3. Настройка системы

Требования, предъявляемые к параметрам технических средств:

1. IBM-совместимый персональный компьютер (ПЭВМ), включающий в себя:

1.1. Процессор Pentium - 4 с тактовой частотой 1.2 ГГц, не менее.

1.2. Оперативную память объемом, 512 Mб, не менее.

1.3. Жесткий диск объемом 40 Гб, и выше.

1.4. Оптический манипулятор типа «мышь».

2. Локальная сеть. Пропускная способность ЛС до 1Гб/сек.

Требования к информационной и программной совместимости:

1. Среда разработки MS Visual Studio, так как она предназначена для разработки и исполнения приложений различных типов, в том числе приложение Windows Forms.

2. Операционные системы, которые поддерживают среду разработки:

2.1. WindowsXP.

2.2. Windows 7.

2.3. Windows 8.

2.4. Windows 10.

Приложение Л. Тестирование методом сценариев

Таблица Л.1. Результаты тестирования

Порядок действий

Реакция системы

Результат (пройден/не пройден)

Состояние системы:

Открыта и готова к использованию

Функция «Создание решения»

1. Нажать правой кнопкой мыши по пустой области в браузере проектов.

2. Выбрать пункт контекстного меню «Создать решение».

3. Ввести название решения:

a. Решение с данным названием уже существует.

b. Название уникально.

4. Закрыть диалоговое окно ввода названия:

a. Нажать «ОК».

b. Нажать на «крестик» в правом верхнем углу.

5. Закрыть диалоговое окно с предупреждением о наличии решения с таким же названием:

a. Нажать «ОК».

b. Нажать на «крестик» в правом верхнем углу

(1, 2, 3-a, 4-a, 5-a) - Существующее решение перезаписалось

(1,2,3(a/b),4-b) - Состояние системы не изменилось, узел не создался.

(1, 2, 3-a, 4-a, 5-b) - Состояние системы не изменилось, узел не создался.

(1, 2, 3-b, 4-a) - Создался новый узел с решением

Пройден

Функция «Создание языка»

1. Нажать правой кнопкой мыши по решению.

a. В решении нет языков.

b. В решении есть созданные языки.

2. Выбрать пункт контекстного меню «Создать язык».

3. Ввести название языка.

a. Язык с данным названием уже существует.

b. Название языка уникально в пределах решения.

4. Закрыть диалоговое окно ввода названия:

a. Нажать «ОК»

b. Нажать на «крестик» в правом верхнем углу.

5. Закрыть диалоговое окно с предупреждением о наличии языка с таким же названием:

a. Нажать кнопку «Заменить».

b. Нажать на «крестик» в правом верхнем углу

(1-b, 2, 3-a, 4-a, 5-a) - Существующий язык перезаписался.

(1(a/b),2,3(a/b),4-b) - Состояние системы не изменилось, узел для языка не создался.

(1-b, 2, 3-a, 4-a, 5-b) - Состояние системы не изменилось, узел не создался.

(1(a/b), 2, 3-b, 4-a) - Создался новый узел с языком в выбранном решении

Пройден

Функция «Создание программы»

1. Нажать правой кнопкой мыши по языку.

a. В языке нет программ.

b. В языке есть созданные программы.

2. Выбрать пункт контекстного меню «Создать программу».

3. Ввести название программы.

a. Программа с данным названием уже существует.

b. Название программы уникально в пределах решения.

4. Закрыть диалоговое окно ввода названия:

a. Нажать «ОК»

b. Нажать на «крестик» в правом верхнем углу.

5. Закрыть диалоговое окно с предупреждением о наличии программы с таким же названием:

a. Нажать кнопку «Заменить».

b. Нажать на «крестик» в правом верхнем углу

(1-b, 2, 3-a, 4-a, 5-a) - Существующая программа перезаписалась.

(1(a/b),2,3(a/b),4-b) - Состояние системы не изменилось, узел для программы не создался.

(1-b, 2, 3-a, 4-a, 5-b) - Состояние системы не изменилось, узел не создался.

(1(a/b), 2, 3-b, 4-a) - Создался новый узел с программой в выбранном языке

Пройден

Функция «Редактирование языка, программы»

1. Нажать правой кнопкой мыши по языку/программе.

2. Выбрать пункт контекстного меню «Редактировать».

a. Выбранный язык/программа уже открыт.

b. Вкладка для языка/программы еще не создана

(1, 2-a) - Вкладка, содержащая нужный язык/программу, стала активной.

(1,2-b) - Создалась новая вкладка, выбранный язык/программа открыт для редактирования

Пройден

Функция «Редактирование всех языков и программ решения»

1. Нажать правой кнопкой мыши по решению.

2. Выбрать пункт контекстного меню «Редактировать все».

a. Какой-либо из объектов решения уже открыт.

b. Ни один объект решения еще не открыт

(1, 2-a) - Для открытых объектов новые вкладки не создались. Активной вкладкой стал последний открытый объект.

(1,2-b) - Создались новые вкладки для всех объектов решения

Пройден

Функция «Редактирование всех программ языка»

1. Нажать правой кнопкой мыши по языку.

2. Выбрать пункт контекстного меню «Редактировать все».

a. Какая-либо из программ уже открыта.

b. Ни одна из программ языка еще не открыт

(1, 2-a) - Для открытых программ новые вкладки не создались. Активной вкладкой стала последняя открытая программа.

(1,2-b) - Создались новые вкладки для всех программ языка

Пройден

Функция «Загрузка из репозитория»

1. Нажать правой кнопкой мыши по нужному объекту:

a. Решение.

b. Язык.

2. Выбрать пункт контекстного меню «Загрузить в репозиторий».

3. В диалоговом окне выбрать нужный объект:

a. Данный объект уже существует в рамках решения.

b. Данный объект уже существует в рамках языка.

c. Объект уникален и не содержит ошибок.

d. Объект содержит ошибки.

4. В диалоговом окне уведомления о наличии объекта в системе нажать кнопку:

a. Заменить.

b. Отмена.

5. В диалоговом окне уведомления о наличии ошибок нажать кнопку:

a. Открыть модель.

b. Отмена

(1-a, 2, 3-a, 4-a) - Выбранный язык заменил язык, имеющийся в браузере проектов.

(1-a, 2, 3-a, 4-b) - Состояние системы не изменилось.

(1-a, 2, 3-c) - Создался новый узел, содержащий выбранный язык в браузере проектов.

(1-a, 2, 3-d, 5-a) - Создался новый узел, содержащий выбранный язык в браузере проектов.

(1-a, 2, 3-d, 5-b) - Состояние системы не изменилось.

(1-b, 2, 3-b, 4-a) - Выбранная программа заменила программу, имеющуюся в браузере проектов.

(1-b, 2, 3-b, 4-b) - Состояние системы не изменилось.

(1-b, 2, 3-с) - Выбранная программа создалась в браузере проектов.

(1-b, 2, 3-d, 5-a) - Выбранная программа создалась в браузере проектов.

(1-b, 2, 3-d, 5-b) - Состояние системы не изменилось

Пройден

Функция «Переименование решения, языка, программы»

1. Нажать правой кнопкой мыши по нужному объекту:

a. Решение.

b. Язык.

c. Программа.

2. Выбрать пункт контекстного меню «Переименовать».

3. В диалоговом окне ввести название:

a. Объект с таким именем уже существует.

b. Имя уникальное.

4. В диалоговом окне изменения имени нажать кнопку:

a. ОК.

b. Отмена

(1(a/b/c), 2, 3-a) - Объект не переименован.

(1(a/b/c), 2, 3-b, 4-a) - Объект переименован.

(1(a/b/c), 2, 3-b, 4-b) - Объект не переименован

Пройден

Функция «Сохранение и выход»

1. Открыть для редактирования объект:

a. Язык.

b. Программа.

2. Нажать кнопку «Выйти без сохранения»:

a. Объект не был изменен.

b. Объект редактировался.

3. Нажать кнопку «Сохранить и выйти»:

a. Объект не был изменен.

b. Объект редактировался.

4. Нажать на кнопку «Сохранить»:

a. Объект не был изменен.

b. Объект редактировался

(1(a/b), 2(a/b)) - Изменения в объекте не сохранились, вкладка закрылась.

(1(a/b), 3(a/b)) - Изменения в объекте сохранились, вкладка закрылась.

(1(a/b), 4(a/b)) - Изменения в объекте сохранились, вкладка не закрылась

Пройден

Приложение М. Программный код

using System;

using System.Collections.Generic;

using System.Linq;

using System.Text;

using System.Xml;

using System.IO;

namespace EBNF

{

/// Представление терминальных и нетерминальных символов

internal abstract class CSymbol

{

}

/// Представление терминала

internal class CTerminal : CSymbol

{

internal string Symbol;

internal CTerminal(string Symbol)

{

this.Symbol = Symbol;

}

}

/// Представление нетерминала

internal abstract class CNonterminal : CSymbol

{

}

/// Типы предопределённых нетерминалов

internal enum EPredefined

{

/// Пропуск

eSpace,

/// Цифра

eDigit,

/// Буква

eLetter,

/// Идентификатор

eIdentifier

}

/// Предопределённый нетерминал

internal class CPredefined : CNonterminal

{

internal EPredefined type;

internal bool CanEmpty;

/// Создание предопределённого нетерминала заданного типа

internal CPredefined(EPredefined type, bool CanEmpty)

{

this.type = type;

this.CanEmpty = CanEmpty;

}

}

/// Определяемый пользователем нетерминал

internal class CDefined : CNonterminal

{

/// Данный нетерминал не является стартовым

internal bool NonStart;

/// Индекс элемента в списке TextStructure класса CSequence, к которому отностися нетерминал.

internal int it;

/// Индекс элемента, следующего за правилом, определяющим нетерминал, либо индекс конца правила первого появления, если нетерминал ещё не определён

internal int ier;

internal List<CSymbol> Sequence;

/// Меню для данного нетерминала

internal List<string>[] menus;

/// Список связей. Используется для определения циклических определений нетерминалов.

internal List<CDefined> links;

/// Добавляет в список связей нетерминал, если его ещё нет в этом списке

internal void AddLink(CDefined d)

{

for (int i = 0; i < links.Count; i++)

if (links[i] == d)

return;

links.Add(d);

}

/// Удаляет из списка связей нетерминалы с пустыми списками связей

internal bool RemoveLinks()

{

bool ret = false;

for (int i = links.Count - 1; i >= 0; i--)

if (links[i].links.Count == 0)

{

links.RemoveAt(i);

ret = true;

}

return ret;

}

/// Добавить пункт в меню

internal static void Add2Menu(List<string> menu, string item)

{

for (int i = 0; i < menu.Count; i++)

if (menu[i] == item)

return;

menu.Add(item);

}

/// Объединяет 2 меню

internal static void Add2Menu(List<string> menu, List<string> items)

{

if (items == null)

return;

int i;

for (int k = 0; k < items.Count; k++)

{

for (i = 0; i < menu.Count; i++)

if (menu[i] == items[k])

break;

if (i >= menu.Count)

menu.Add(items[k]);

}

}

/// Создаёт меню для данного нетерминала

internal void MakeMenu()

{

menus = new List<string>[Sequence.Count];

List<int> iGroop = new List<int>(); //Начала вложенных групп

iGroop.Add(0);

menus[0] = new List<string>();

bool ToCombine = true;

List<bool> combines = new List<bool>();

for (int i = 0; i < Sequence.Count; i++)

{

CSymbol symb = Sequence[i];

List<string> menu; //Текущее меню

if (symb is CTerminal)

{

if (ToCombine)

{//Объединить с меню начала группы

Add2Menu(menus[iGroop[iGroop.Count - 1]], (symb as CTerminal).Symbol);

menus[i] = menus[iGroop[iGroop.Count - 1]];

}

else

{//Создать индивидуальное для терминала меню

menus[i] = new List<string>();

menus[i].Add((symb as CTerminal).Symbol);

}

ToCombine = false;

}

else if (symb is CDefined)

{

CDefined d = symb as CDefined;

if (d.menus == null)

d.MakeMenu();

if (ToCombine)

{

menu = menus[i] = menus[iGroop[iGroop.Count - 1]];

ToCombine = false;

}

else menu = menus[i] = new List<string>();

if (d.menus[0] != null)

for (int j = 0; j < d.menus[0].Count; j++)

menu.Add(d.menus[0][j]);

}

else if (symb is CMetaSymbol)

switch ((symb as CMetaSymbol).type)

{

case EMetaType.eEndOption:

case EMetaType.eEndRepeator:

if (combines.Count > 0 && combines[combines.Count - 1])

Add2Menu(menus[iGroop[iGroop.Count - 2]], menus[iGroop[iGroop.Count - 1]]);

iGroop.RemoveAt(iGroop.Count - 1);

ToCombine = combines[combines.Count - 1];

combines.RemoveAt(combines.Count - 1);

break;

case EMetaType.eStartOption:

case EMetaType.eStartRepeator:

menus[i] = new List<string>();

iGroop.Add(i);

combines.Add(ToCombine);

ToCombine = true;

break;

default: //Разделитель

ToCombine = true;

break;

}

else if (!(symb as CPredefined).CanEmpty)

ToCombine = false; //Предопределённый идентификатор, который не может быть пустым

}

List<string> CurrentMenu = null;

List<List<string>> GroupMenus = new List<List<string>>(); //Меню на выходе вложенных групп

GroupMenus.Add(null); //Для основной последовательности

for (int i = Sequence.Count - 1; i >= 0; i--)

{

CSymbol symb = Sequence[i];

if (symb is CPredefined)

{

if ((symb as CPredefined).CanEmpty)

menus[i] = CurrentMenu; //Для предопределённого нетерминала, который может быть пустым

else

CurrentMenu = menus[i];

}

else if (symb is CDefined || symb is CTerminal)

CurrentMenu = menus[i]; //Текущее меню - меню данного символа

else switch ((symb as CMetaSymbol).type)

{

case EMetaType.eEndOption: //Добавляется в начало группы текущее меню

case EMetaType.eEndRepeator:

Add2Menu(menus[(symb as CMetaSymbol).iGoto], CurrentMenu);

GroupMenus.Add(CurrentMenu);

break;

case EMetaType.eSeparator:

CurrentMenu = GroupMenus[GroupMenus.Count - 1];

break;

case EMetaType.eStartOption: //Текущее меню - меню конца группы

case EMetaType.eStartRepeator:

GroupMenus.RemoveAt(GroupMenus.Count - 1);

CurrentMenu = menus[i];

break;

}

}

//Обнулить меню с нулевым количеством пунктов

for (int i = 0; i < menus.GetLength(0); i++)

if (menus[i] != null && menus[i].Count == 0)

menus[i] = null;

}

/// Создаётся определяемый пользователем нетерминал

internal CDefined(int it)

{

this.it = it;

NonStart = false;

Sequence = new List<CSymbol>(32);

menus = null;

}

}

/// Типы метасимволов, присутствующих в описании нетерминала

internal enum EMetaType

{

/// Начало группы опций

eStartOption,

/// Конец группы опций

eEndOption,

/// Начало группы повторений

eStartRepeator,

/// Конец группы повторения

eEndRepeator,

eSeparator

}

/// Класс, представляющий метасимвол в описании нетерминала

internal class CMetaSymbol : CSymbol

{

internal EMetaType type;

/// Индекс символа в определении, на который происходит переход при выполнении условия перехода:

/// в конце группы - индекс метасимвола начала группы,

/// в разделителе и в начале группы - индекс конца группы.

internal int iGoto;

/// Создание объекта представляющего метасимвол в описании нетерминала

internal CMetaSymbol(EMetaType type)

{

this.type = type;

}

/// Создание объекта представляющего метасимвол в описании нетерминала

internal CMetaSymbol(EMetaType type, int iGoto)

{

this.type = type;

this.iGoto = iGoto;

}

}

/// Элементы разметки текста описания языка

internal enum ETextPiece

{

incorrect,

terminal,

extention,

nonterminal,

metasymbol

}

/// Элемент разметки текста метамодель

internal class CTextStructure

{

/// Индекс символа в тексте, с которого начинается элемент

internal int ind;

internal ETextPiece type;

internal CTextStructure(int ind, ETextPiece type)

{

this.ind = ind;

this.type = type;

}

}

/// Последовательность символов, которая представляет язык

public class CSentence

{

/// Стартовый символ

internal string StartSymbol;

/// Упорядоченный список нетерминалов

private Dictionary<string, CNonterminal> Nonterminals;

/// Структура текста языка с целью раскраски

internal List<CTextStructure> TextStructure;

/// Список ошибок

internal List<string> SemanticErrors;

/// Обнаружена синтаксическая ошибка для текущего определения

private bool error;

internal bool LanguageFault;

/// Начало правила в тексте. На случай, если правило ошибочно.

private int iTS;

static char[] cServiceSymbols = { ';', '<', '\\', ':', '[', ']', '{', '}', '|' };

private int MissSpaces(int i, string s)

{

int ret = i;

while (ret < s.Length && (s[ret] == ' ' || s[ret] == '\r' || s[ret] == '\n' || s[ret] == '\t'))

ret++;

return ret;

}

/// Поиск начала или конца метасимвола

private int SearchBoundMetasymbol(int i, string s, char c)

{

int ret = i;

if (i >= s.Length)

return -1;

while (ret >= 0 && s[ret] != c)

{

ret = s.IndexOf(c, ret);

if (ret > 0 && s[ret - 1] == '\\')

{

ret++;

if (ret == s.Length)

return -1; }

}

return ret;

}

/// Считывает текст на участке обрабатываемого текста.

private string GetText(int i, int k, string s, ETextPiece type)

{

char[] cs = new char[k - i];

int l = 0;

for (int j = i; j < k; j++)

{

if (s[j] == '\\')

{

TextStructure.Add(new CTextStructure(j, ETextPiece.metasymbol));

TextStructure.Add(new CTextStructure(j + 1, ETextPiece.extention));

if (j < k - 2 && s[j + 2] != '\\')

TextStructure.Add(new CTextStructure(j + 2, type));

j++;

}

if (j < k)

cs[l++] = s[j];

}

return new string(cs, 0, l).Trim();

}

/// Добавление в конец TextStructure ошибки, если последней записью TextStructure уже не была

private void AddError()

{

//Удалить всю разметку до начала правила

while (TextStructure.Count > 0 && iTS <= TextStructure[TextStructure.Count - 1].ind)

TextStructure.RemoveAt(TextStructure.Count - 1);

TextStructure.Add(new CTextStructure(iTS, ETextPiece.incorrect));

LanguageFault = true;

}

private string GetText(ref int i, string s)

{

int k = i;

int i0 = i;

if (s[i] != '\\')

TextStructure.Add(new CTextStructure(i, ETextPiece.terminal));

while (true)

{

k = s.IndexOfAny(cServiceSymbols, k);

if (k < 0)

{

i = s.Length;

return GetText(i0, i, s, ETextPiece.terminal);

}

if (s[k] == '\\')

{

if (k == s.Length - 1)

{

i = s.Length;

return GetText(i0, i, s, ETextPiece.terminal);

}

k += 2;

}

else if (s[k] == ':')

{

if (k < s.Length - 3 && s[k + 1] == ':' && s[k + 2] == '=')

{//Обнаружен символ определения "::="

TextStructure.Add(new CTextStructure(k, ETextPiece.incorrect));

k += 3;

error = true;

TextStructure.Add(new CTextStructure(k, ETextPiece.terminal));

}

else k++;

}

else

{

i = k;

return GetText(i0, k, s, ETextPiece.terminal);

}

}

}

/// Описание группы

private class CGroupDescription

{

internal bool Repeator;

/// Индекс начала группы в последовательности

internal int ind;

/// Индексы принадлежащих группе разделителей (|) в последовательности

internal List<int> iSeparators;

/// Создание описания группы

internal CGroupDescription(bool Repeator, int ind)

{

this.Repeator = Repeator;

this.ind = ind;

iSeparators = new List<int>();

}

}

/// Создаёт меню для каждого нетерминала

internal void MakeMenu()

{

if ((Nonterminals[StartSymbol] as CDefined).menus != null)

return;

(Nonterminals[StartSymbol] as CDefined).MakeMenu();

foreach (CNonterminal nt in Nonterminals.Values)

if (nt is CDefined)

{

CDefined d = nt as CDefined;

if (d.menus == null)

d.MakeMenu();

}

}

private void MarkIncorrectRule(int iS, int iF)

{

for (int j = 0; j < TextStructure.Count; j++)

if (TextStructure[j].ind >= iS)

{

ETextPiece type = TextStructure[j].type;

while (j < TextStructure.Count && TextStructure[j].ind < iF)

{

type = TextStructure[j].type;

TextStructure.RemoveAt(j);

}

TextStructure.Insert(j, new CTextStructure(iS, ETextPiece.incorrect));

if (++j >= TextStructure.Count || TextStructure[j].ind > iF)

TextStructure.Insert(j, new CTextStructure(iF, type));

return;

}

TextStructure.Add(new CTextStructure(iS, ETextPiece.incorrect));

}

/// Анализ метамодели

internal CSentence(string s)

{

int k; //Индекс следующего найденного символа в тексте

CGroupDescription Group;

CNonterminal Nonterminal;

List<CSymbol> Definishing; //Определение нетерминала

SemanticErrors = new List<string>();

TextStructure = new List<CTextStructure>();

TextStructure.Add(new CTextStructure(0, ETextPiece.nonterminal));

List<CGroupDescription> Groups = new List<CGroupDescription>();

Nonterminals = new Dictionary<string, CNonterminal>();

Nonterminals.Add("пропуск", new CPredefined(EPredefined.eSpace, true)); Nonterminals.Add("цифра", new CPredefined(EPredefined.eDigit, false));

Nonterminals.Add("буква", new CPredefined(EPredefined.eLetter, false));

Nonterminals.Add("идентификатор", new CPredefined(EPredefined.eIdentifier, false));

LanguageFault = false;

for (int iS = MissSpaces(0, s); iS < s.Length; iS = MissSpaces(iS, s))

{

iTS = iS; //Начало правила. На случай, если правило ошибочно.

Groups.Add(new CGroupDescription(false, 0)); //Самая внешняя группа (не выделенная скобками) рассматривается как группа опций

k = SearchBoundMetasymbol(iS, s, '<');

if (k > iS || k < 0)

{

AddError();

iS = k;

if (k < 0)

break;

}

iTS = k;

//Поиск конца описываемого нетерминала

TextStructure.Add(new CTextStructure(k, ETextPiece.metasymbol));

iS = k + 1;

k = SearchBoundMetasymbol(iS, s, '>');

if (k < 0)

{//Нет конца нетерминала

AddError();

iS = s.Length;

break;

}

error = false;

List<string> NewNonterminals = new List<string>(); //Список новых нетерминалов в правиле. Если есть синтаксическая ошибка, то они удаляются.

TextStructure.Add(new CTextStructure(iS, ETextPiece.nonterminal));

string DetermedName = GetText(iS, k, s, ETextPiece.nonterminal);

TextStructure.Add(new CTextStructure(k, ETextPiece.metasymbol));

CDefined Determing = null; //Определяемый нетерминал

int itDetermed = TextStructure.Count; //Индекс структуры текста начала определяемого нетерминала

if (!Nonterminals.TryGetValue(DetermedName, out Nonterminal))

{

Nonterminal = new CDefined(iTS);

Nonterminals.Add(DetermedName, Nonterminal);

NewNonterminals.Add(DetermedName);

}

if ((Nonterminal is CDefined) && (Nonterminal as CDefined).Sequence.Count == 0)

{//Нетерминал пока неопределён (последовательность пуста)

Determing = Nonterminal as CDefined;

Determing.it = iTS;

Definishing = Determing.Sequence;

}

else

{

Definishing = new List<CSymbol>(16);

if (!(Nonterminal is CPredefined))

SemanticErrors.Add("Нетерминал <" + DetermedName + "> определён повторно.");

}

iS = MissSpaces(k + 1, s);

for (k = SearchBoundMetasymbol(iS, s, ':'); k >= 0 && k < s.Length - 3 && (s[k + 1] != ':' || s[k + 2] != '=');

k = SearchBoundMetasymbol(k + 1, s, ':')) ;

if (iS < s.Length && k == iS)

{//Метасимвол определения найден

k += 3;

iS = MissSpaces(k, s);

}

else

{//Метасимвол отсутствует или ошибка

error = true;

iS = MissSpaces(k < 0 || k >= s.Length - 3 ? s.Length : k + 3, s);

}

//Чтение определения нетерминала

while (iS < s.Length && s[iS] != ';')

{

switch (s[iS])

{

case '<':

TextStructure.Add(new CTextStructure(iS, ETextPiece.metasymbol));

iS++;

TextStructure.Add(new CTextStructure(iS, ETextPiece.nonterminal));

k = SearchBoundMetasymbol(iS, s, '>');

string name = k < 0 ? null : GetText(iS, k, s, ETextPiece.nonterminal);

if (name == null)

{

error = true;

iS = s.Length;

}

else

{

TextStructure.Add(new CTextStructure(k, ETextPiece.metasymbol));

iS = k + 1;

if (!Nonterminals.TryGetValue(name, out Nonterminal))

{

Nonterminal = new CDefined(iTS);

Nonterminals.Add(name, Nonterminal);

NewNonterminals.Add(name);

}

Definishing.Add(Nonterminal);

}

break;

case '\\':

Definishing.Add(new CTerminal(GetText(ref iS, s)));

error |= iS < s.Length && s[iS] == '\\';

break;

case '|':

TextStructure.Add(new CTextStructure(iS, ETextPiece.metasymbol));

if (Definishing.Count == 0 || (Definishing[Definishing.Count - 1] is CMetaSymbol

&& ((Definishing[Definishing.Count - 1] as CMetaSymbol).type == EMetaType.eSeparator || (Definishing[Definishing.Count - 1] as CMetaSymbol).type == EMetaType.eStartOption

|| (Definishing[Definishing.Count - 1] as CMetaSymbol).type == EMetaType.eStartRepeator)))

error = true;

else

{

Groups[Groups.Count - 1].iSeparators.Add(Definishing.Count);

Definishing.Add(new CMetaSymbol(EMetaType.eSeparator));

}

iS++;

break;

case '[':

TextStructure.Add(new CTextStructure(iS, ETextPiece.metasymbol));

Groups.Add(new CGroupDescription(false, Definishing.Count));

Definishing.Add(new CMetaSymbol(EMetaType.eStartOption));

iS++;

break;

case ']':

TextStructure.Add(new CTextStructure(iS, ETextPiece.metasymbol));

if (Groups.Count > 1 && !Groups[Groups.Count - 1].Repeator)

{

Group = Groups[Groups.Count - 1];

for (int i = 0; i < Group.iSeparators.Count; i++)

(Definishing[Group.iSeparators[i]] as CMetaSymbol).iGoto = Definishing.Count;

(Definishing[Group.ind] as CMetaSymbol).iGoto = Definishing.Count;

Definishing.Add(new CMetaSymbol(EMetaType.eEndOption, Group.ind));

Groups.RemoveAt(Groups.Count - 1);

}

else

error = true;

iS++;

break;

case '{':

TextStructure.Add(new CTextStructure(iS, ETextPiece.metasymbol));

Groups.Add(new CGroupDescription(true, Definishing.Count));

Definishing.Add(new CMetaSymbol(EMetaType.eStartRepeator));

iS++;

break;

case '}':

TextStructure.Add(new CTextStructure(iS, ETextPiece.metasymbol));

if (Groups.Count > 1 && Groups[Groups.Count - 1].Repeator)

{

Group = Groups[Groups.Count - 1];

for (int i = 0; i < Group.iSeparators.Count; i++)

(Definishing[Group.iSeparators[i]] as CMetaSymbol).iGoto = Group.ind;

(Definishing[Group.ind] as CMetaSymbol).iGoto = Definishing.Count;

Definishing.Add(new CMetaSymbol(EMetaType.eEndRepeator, Group.ind));

Groups.RemoveAt(Groups.Count - 1);

}

else

error = true;

iS++;

break;

case '>':

error = true; iS++;

break;

default:

TextStructure.Add(new CTextStructure(iS, ETextPiece.terminal));

Definishing.Add(new CTerminal(GetText(ref iS, s)));

error |= iS < s.Length && s[iS] == '\\';

break;

}

iS = MissSpaces(iS, s);

}

if (iS == s.Length || Groups.Count > 1)

error = true; if (iS < s.Length)

{

TextStructure.Add(new CTextStructure(iS, ETextPiece.metasymbol));

iS++;

}

if (Determing != null)

Determing.ier = iS;

Group = Groups[0];

for (int i = 0; i < Group.iSeparators.Count; i++)

(Definishing[Group.iSeparators[i]] as CMetaSymbol).iGoto = Definishing.Count; //Переход на конец группы опций

Groups.Clear();

if (error)

AddError();

if (Determing != null && Definishing == Determing.Sequence)

Determing.Sequence.Clear(); //Последовательность удаляется, если она была вновь создана

for (int i = 0; i < NewNonterminals.Count; i++)

Nonterminals.Remove(NewNonterminals[i]);

while (TextStructure.Count > 0 && TextStructure[TextStructure.Count - 1].ind >= iTS)

TextStructure.RemoveAt(TextStructure.Count - 1);

TextStructure.Add(new CTextStructure(iTS, ETextPiece.incorrect));

}

else

{

if (Nonterminals.TryGetValue(DetermedName, out Nonterminal))

{

if (Nonterminal is CPredefined)

CDefined def = new CDefined(itDetermed);

def.Sequence = Definishing;

Nonterminals[DetermedName] = def;

}

}

for (int i = 0; i < NewNonterminals.Count; i++)

{

CDefined D = Nonterminals[NewNonterminals[i]] as CDefined;

D.ier = iS;

}

}

}

while (TextStructure.Count > 0 && TextStructure[TextStructure.Count - 1].ind >= s.Length && s.Length > 0)

TextStructure.RemoveAt(TextStructure.Count - 1);

for (int i = TextStructure.Count - 2; i >= 0; i--)

{

if (TextStructure[i].type == TextStructure[i + 1].type)

TextStructure.RemoveAt(i + 1);

if (i < TextStructure.Count - 1 && TextStructure[i].ind == TextStructure[i + 1].ind)

TextStructure.RemoveAt(i); //Если приходится несколько разметок на 1 символ, то оставляется последняя

}

//Построение дерева

foreach (string name in Nonterminals.Keys)

{

Nonterminals.TryGetValue(name, out Nonterminal);

if (Nonterminal is CDefined)

{

CDefined D = Nonterminal as CDefined;

if (D.Sequence.Count == 0)

{

SemanticErrors.Add("Нетерминал <" + name + "> неопределён.");

MarkIncorrectRule(D.it, D.ier);

}

else

for (int i = 0; i < D.Sequence.Count; i++)

{

CSymbol symbol = D.Sequence[i];

if (symbol is CDefined)

(symbol as CDefined).NonStart = true;

}

}

}

List<string> StartNonterminals = new List<string>(); //Список стартовых нетерминалов

bool b;

foreach (string name in Nonterminals.Keys)

{

Nonterminals.TryGetValue(name, out Nonterminal);

if (Nonterminal is CDefined)

{

CDefined d = Nonterminal as CDefined;

if (!d.NonStart)

StartNonterminals.Add(name);

d.links = new List<CDefined>();

List<CSymbol> sequence = d.Sequence;

b = true;

int il = 0;

for (int i = 0; i < sequence.Count; i++)

if (b)

{

if (sequence[i] is CDefined)

d.AddLink(sequence[i] as CDefined); //Непредопределённый идентификатор

else if ((sequence[i] is CPredefined && !(sequence[i] as CPredefined).CanEmpty) || sequence[i] is CTerminal)

{

b = false; d.links.RemoveRange(il, d.links.Count - il

else if (sequence[i] is CMetaSymbol)

{

CMetaSymbol mt = sequence[i] as CMetaSymbol;

if (mt.type == EMetaType.eSeparator)

il = d.links.Count;

else

i = mt.iGoto;

}

}

else if (sequence[i] is CMetaSymbol)

{//Пропускаем всё до разделителя нижнего уровня

CMetaSymbol mt = sequence[i] as CMetaSymbol;

if (mt.type == EMetaType.eSeparator)

b = true;

else

i = mt.iGoto;

}

}

}

do

{//Удаление из списка связей непредопределённых нетерминалов без связей

b = false;

foreach (CNonterminal nt in Nonterminals.Values)

if (nt is CDefined)

b |= (nt as CDefined).RemoveLinks();

} while (b);

foreach (string name in Nonterminals.Keys)

{

Nonterminals.TryGetValue(name, out Nonterminal);

if (Nonterminal is CDefined && (Nonterminal as CDefined).links.Count > 0)

{

SemanticErrors.Add("Нетерминал '" + name + "' циклически определяется через себя.");

CDefined d = (Nonterminal as CDefined);

MarkIncorrectRule(d.it, d.ier);

}

}

if (StartNonterminals.Count == 0)

SemanticErrors.Add("Последовательность не содержит ни одного стартового символа");

else if (StartNonterminals.Count > 1)

{

string err = "Последовательность содержит следующие стартовые символы: <" + StartNonterminals[0];

for (int i = 1; i < StartNonterminals.Count; i++)

err += ">, <" + StartNonterminals[i];

err += ">";

for (int i = 0; i < StartNonterminals.Count; i++)

{

Nonterminals.TryGetValue(StartNonterminals[i], out Nonterminal);

MarkIncorrectRule(((CDefined)Nonterminal).it, ((CDefined)Nonterminal).ier);

}

SemanticErrors.Add(err);

}

else StartSymbol = StartNonterminals[0];

LanguageFault |= SemanticErrors.Count > 0;

}

//---------------------------------------Модель----------------------------------------//

internal bool CompileError;

internal List<CTextStructure> CompiledText;

private List<CTextStructure> WText;

private int iSW;

private class CCompileState

{

/// <summary>

internal CDefined Defined;

internal int ind;

internal List<int> GroupText;

/// Создаёт состояние для нетерминала

internal CCompileState(CDefined Defined, int iS)

{

this.Defined = Defined;

this.ind = 0;

GroupText = new List<int>();

GroupText.Add(iS);

}

/// Копирование группы

internal CCompileState(CCompileState src)

{

Defined = src.Defined;

ind = src.ind;

GroupText = new List<int>();

for (int i = 0; i < src.GroupText.Count; i++)

GroupText.Add(src.GroupText[i]);

}

}

/// Поиск

private bool WhenNoItem(List<CCompileState> states, ref CDefined Defined, ref List<CSymbol> Sequence, ref CCompileState CurrentState, ref int iS)

{

if (iS > iSW)

{

WText.Clear();

for (int i = 0; i < CompiledText.Count; i++)

WText.Add(CompiledText[i]);

iSW = iS;

}

while (states.Count > 0)

{

for (CurrentState.ind++; CurrentState.ind < Sequence.Count; CurrentState.ind++)

if (Sequence[CurrentState.ind] is CMetaSymbol)

{

CMetaSymbol MetaSymbol = Sequence[CurrentState.ind] as CMetaSymbol;

switch (MetaSymbol.type)

{

case EMetaType.eStartRepeator:

case EMetaType.eStartOption: CurrentState.ind = (Sequence[CurrentState.ind] as CMetaSymbol).iGoto;

break;

case EMetaType.eSeparator:

CurrentState.ind++;

iS = CurrentState.GroupText[CurrentState.GroupText.Count - 1];

int i = CompiledText.Count;

while (i > 0 && CompiledText[i - 1].ind >= iS)

i--;

CompiledText.RemoveRange(i, CompiledText.Count - i);

return false;

default:

CurrentState.ind++;

iS = CurrentState.GroupText[CurrentState.GroupText.Count - 1];

CurrentState.GroupText.RemoveAt(CurrentState.GroupText.Count - 1);

return false;

}

}

else if (states.Count == 1 && CurrentState.GroupText.Count == 1 && !((Sequence[CurrentState.ind] is CPredefined)

&& (Sequence[CurrentState.ind] as CPredefined).CanEmpty))

{

if (iSW > iS)

{

iS = iSW;

CompiledText = WText;

}

return true;

}

states.RemoveAt(states.Count - 1);

if (states.Count == 0)

return true;

CurrentState = states[states.Count - 1];

Defined = CurrentState.Defined;

Sequence = Defined.Sequence;

}

return false;

}

/// Обозначить строку с ошибкой

private void SetProgramError(string s, int iS)

{

CompileError = true;

if (iSW > iS)

{

iS = iSW;

CompiledText = WText;

}

int iSL = iS; //Начало строки с ошибкой

while (iSL > 0 && s[iSL - 1] != '\r' && s[iSL - 1] != '\n')

iSL--;

while (CompiledText.Count > 0 && CompiledText[CompiledText.Count - 1].ind >= iSL)

CompiledText.RemoveAt(CompiledText.Count - 1);

CompiledText.Add(new CTextStructure(iSL, ETextPiece.incorrect));

int iSF = iS; //Конец строки с ошибкой

while (iSF < s.Length && ((s[iSF] != '\r' && s[iSF] != '\n') || iSF == iSL))

iSF++;

CompiledText.Add(new CTextStructure(iSF, ETextPiece.terminal)); //Вернуться к чёрному цвету

}

/// Добавить маркер в разметку текста

private void AddMarker(int iS, ETextPiece type)

{

if (CompiledText.Count > 0 && CompiledText[CompiledText.Count - 1].ind == iS)

{

CompiledText[CompiledText.Count - 1].type = type;

if (CompiledText.Count > 1 && CompiledText[CompiledText.Count - 2].type == type)

CompiledText.RemoveAt(CompiledText.Count - 1);

}

else if (CompiledText.Count == 0 || CompiledText[CompiledText.Count - 1].type == type)

return;

CompiledText.Add(new CTextStructure(iS, type));

}

/// Анализ модели

internal List<string> Compile(string s, int iCaret)

{

CompiledText = new List<CTextStructure>();

CompiledText.Add(new CTextStructure(0, ETextPiece.terminal));

if (LanguageFault)

{

CompileError = true;

return null;

}

MakeMenu(); //Меню для нетерминалов

WText = new List<CTextStructure>();

iSW = -1;

List<string> ret = null;

CompileError = false;

int iS = 0;

List<CCompileState> states = new List<CCompileState>(256); //Список вложенных состояний компиляции

CDefined CurrentNonterminal = Nonterminals[StartSymbol] as CDefined; //Текущий нетерминал

List<CSymbol> Sequence = CurrentNonterminal.Sequence; //Текущая последовательность

CCompileState CurrentState = new CCompileState(CurrentNonterminal, 0);

states.Add(CurrentState);

while (iS < s.Length)

{

while (states.Count != 0)

{

if (CurrentState.ind < Sequence.Count)

{

if (iS == iCaret && CurrentNonterminal.menus[CurrentState.ind] != null)

ret = CurrentNonterminal.menus[CurrentState.ind];

CSymbol CurrentSymbol = Sequence[CurrentState.ind];

if (CurrentSymbol is CTerminal)

{//Проверка наличия терминала в тексте

string st = (CurrentSymbol as CTerminal).Symbol;

bool CaretHere = iS == iCaret; //Каретка установлена на данном символе

int iT = 0;

int iSc = iS;

while (iT < st.Length && iSc < s.Length && st[iT] == s[iSc])

{

iT++;

iSc++;

}

if (iT >= st.Length)

{//Терминал присутствует в тексте

AddMarker(iS, ETextPiece.extention); //Выделение терминала синим цветом

CurrentState.ind++;

iS = iSc;

}

else

{

if (WhenNoItem(states, ref CurrentNonterminal, ref Sequence, ref CurrentState, ref iS))

{

SetProgramError(s, iS);

return ret;

}

}

}

else if (CurrentSymbol is CDefined)

{

CurrentNonterminal = CurrentSymbol as CDefined;

CurrentState = new CCompileState(CurrentNonterminal, iS);

states.Add(CurrentState);

if (states.Count > 512)

{

SetProgramError(s, iS);

return ret;

}

Sequence = CurrentNonterminal.Sequence;

}

else if (CurrentSymbol is CPredefined)

{

switch ((CurrentSymbol as CPredefined).type)

{

case EPredefined.eSpace: while (iS < s.Length && (uint)s[iS] <= 0x20)

{

if (iS == iCaret && CurrentState.ind < Sequence.Count && CurrentNonterminal.menus[CurrentState.ind] != null)

ret = CurrentNonterminal.menus[CurrentState.ind];

iS++;

}

CurrentState.ind++;

break;

case EPredefined.eDigit:

if (iS < s.Length && char.IsDigit(s[iS]))

{

AddMarker(iS, ETextPiece.terminal);

iS++;

CurrentState.ind++;

}

else if (WhenNoItem(states, ref CurrentNonterminal, ref Sequence, ref CurrentState, ref iS))

{

SetProgramError(s, iS);

return ret;

}

break;

case EPredefined.eLetter:

if (iS < s.Length && char.IsLetter(s[iS]))

{

AddMarker(iS, ETextPiece.terminal); iS++;

CurrentState.ind++;

}

else if (WhenNoItem(states, ref CurrentNonterminal, ref Sequence, ref CurrentState, ref iS))

{

SetProgramError(s, iS);

return ret;

}

break;

default:

if (iS < s.Length && char.IsLetter(s[iS]))

{

AddMarker(iS, ETextPiece.terminal);

iS++;

while (iS < s.Length && (((ushort)s[iS] > 0x20 && (ushort)s[iS] < 0x7F)

|| ((ushort)s[iS] >= 0x410 && (ushort)s[iS] < 0x450 || s[iS] == 'Ё' || s[iS] == 'ё')))

iS++;

CurrentState.ind++;

}

else if (WhenNoItem(states, ref CurrentNonterminal, ref Sequence, ref CurrentState, ref iS))

{

SetProgramError(s, iS);

return ret;

}

break;

}

}

else switch ((CurrentSymbol as CMetaSymbol).type)

{//Метасимвол

case EMetaType.eEndOption:

CurrentState.ind++;

CurrentState.GroupText.RemoveAt(CurrentState.GroupText.Count - 1);

break;

case EMetaType.eStartOption:

++CurrentState.ind;

CurrentState.GroupText.Add(iS);

break;

case EMetaType.eStartRepeator:

++CurrentState.ind;

CurrentState.GroupText.Add(iS);

break;

case EMetaType.eEndRepeator:

if (iS > CurrentState.GroupText[CurrentState.GroupText.Count - 1])

{

CurrentState.GroupText[CurrentState.GroupText.Count - 1] = iS;

CurrentState.ind = (CurrentSymbol as CMetaSymbol).iGoto;

}

else

{

CurrentState.ind++;

CurrentState.GroupText.RemoveAt(CurrentState.GroupText.Count - 1);

}

break;

default:

if (iS > CurrentState.GroupText[CurrentState.GroupText.Count - 1])

{//Найден элемент в группе. Зафиксируем продвижение.

CurrentState.GroupText[CurrentState.GroupText.Count - 1] = iS;

CurrentState.ind = (CurrentSymbol as CMetaSymbol).iGoto;

}

else CurrentState.ind++;

break;

}

}

else if (states.Count > 0)

{

states.RemoveAt(states.Count - 1);

if (states.Count > 0)

{

CurrentState = states[states.Count - 1];

CurrentState.ind++;

CurrentNonterminal = CurrentState.Defined;

Sequence = CurrentNonterminal.Sequence;

}

}

}

if (iS < s.Length)

{//Обнаружена ошибка

SetProgramError(s, iS);

return ret;

}

}

if (s.Length == 0 && ret == null)

ret = CurrentNonterminal.menus[0];

if (!CompileError && states.Count > 0)

SetProgramError(s, iS);

return ret;

}

static void Main()

{

string text = File.ReadAllText("json.language", Encoding.Default);

CSentence sentence = new CSentence(text);

string CompiledText = File.ReadAllText("options.json", Encoding.Default);

sentence.Compile(CompiledText, 0);

CompiledText = File.ReadAllText("errors.json", Encoding.Default);

sentence.Compile(CompiledText, 0);

text = File.ReadAllText("pascal_minus.language", Encoding.Default);

sentence = new CSentence(text);

CompiledText = File.ReadAllText("test.pascal_minus", Encoding.Default);

sentence.Compile(CompiledText, 0);

text = File.ReadAllText("Errors1.language", Encoding.Default);

sentence = new CSentence(text);

text = File.ReadAllText("Errors2.language", Encoding.Default);

sentence = new CSentence(text);

text = File.ReadAllText("Errors3.language", Encoding.Default);

sentence = new CSentence(text);

...

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

  • Разработка текстового редактора с подсветкой синтаксиса языков программирования. Загрузка из XML-файла настроек для подсветки синтаксиса и конструкций языка. Формат файлов конфигурации и проверки. Разбор текста и применение к нему стилей, тестовый пример.

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

  • Формат файла конфигурации, содержащего данные для подсветки синтаксиса. Его проверка при помощи XML Schema. Реализация функций для чтения данных подсветки и по загрузке таблицы стилей, ключевых слов и типов. Разбор текста и применение к нему стилей.

    курсовая работа [122,3 K], добавлен 30.05.2015

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

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

  • Краткая характеристика предметно-ориентированных языков, различия между "внутренними" и "внешними" DSL. Особенности работы транслятора (компилятора). Листинг программы для разработки простейшего калькулятора с использованием программной среды Java.

    лабораторная работа [57,8 K], добавлен 31.03.2017

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

    лекция [270,1 K], добавлен 19.10.2014

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

    учебное пособие [346,8 K], добавлен 09.02.2009

  • Обзор разнообразных методов теории линейных систем: методов корреляционного и регрессионного анализа, косинор-анализа. Особенности применения факторного анализа. Программная реализация метода главных компонент. Разработка нелинейных регрессионных моделей.

    дипломная работа [390,2 K], добавлен 03.09.2016

  • История разработки языка программирования Си. Программа на Си как одна или несколько единиц компиляции (файлов), стадии работы компилятора. Идентификаторы и ключевые слова, типы констант. Форма Бекуса-Наура описания синтаксиса формальных языков.

    презентация [257,7 K], добавлен 05.01.2014

  • Характеристики и свойства языков программирования. Исследование эволюции объектно-ориентированных языков программирования. Построение эволюционной карты механизмов ООП. Разработка концептуальной модели функционирования пользовательского интерфейса.

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

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

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

  • Ознакомление с ситуацией распространения на рынке языков программирования. Определение плюсов и минусов Pascal, C++, VBA. Сравнение и анализ синтаксиса программ на основе одной задачи. Выявление лучшего языка для освоения первоначальных навыков.

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

  • Классификация и возможности текстовых редакторов. Среда текстового редактора Microsoft Word 2003. Процесс редактирования текста, его копирование и перемещение. Проверка орфографии и синтаксиса, автотекст и автозамена. Пример гипертекстового документа.

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

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

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

  • Обзор средств разработки и технологий: особенности языка программирования Visual Basic и подсистемы WIN32 API. Методы, приемы решения задачи автоматического размещения текстовых надписей на рисунке. Механизм создания полигонального объекта. Код программы.

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

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

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

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

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

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

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

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

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

  • Разработка алгоритмов и программных средств поддержки взаимодействия компетентностно-ориентированных моделей в обучающих ИЭС (АТ-ТЕХНОЛОГИЯ). Анализ функциональных возможностей базовой версии компонента выявления текущего уровня компетенций обучаемого.

    отчет по практике [1,6 M], добавлен 28.04.2015

  • Характеристика средств обработки текстовой информации, способы редактирования и форматирования документов. Порядок создания списков и таблиц, проверка орфографии и синтаксиса текста. Выбор формата файла. Работа в табличном процессоре Microsoft Excel.

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

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