Разработка транслятора в среде Java и С+
Тема, цель, актуальность работы
Анализ
проектов, реализованных на языках программирования Java и C# на предмет
взаимодействия между классами.
Результат
работы программы необходимо вывести в файл *.xml.
Актуальность
работы заключается в том, что на сегодняшний день нет известных аналогов
программы. Не стоит сравнивать данный проект с такими программными продуктами
как Telelogic Rapsody или Rational – он является полной противоположностью
названных выше программ, так как анализирует уже «готовый», написанный проект,
в то время как Telelogic Rapsody (Rational) генерирует код по диаграммам.
Данный проект
может использоваться для углубленного изучения языков программирования Java и C# в рамках программы
университета, анализа проектов на предмет взаимодействия классов.
Проект может
существовать как автономное приложение, а также может быть дополнен и доработан
функционально.
C# и Java– два очень похожих между собой
современных языка программирования со сборкой
мусора и компиляцией при выполнении. Оба языка – объектно-ориентированные, с синтаксисом,
унаследованным от C++, но значительно переработанным.
Java – объектно-ориентированный язык программирования,
разрабатываемый компанией Sun
Microsystems и официально выпущенный 23 мая 1995 года. Java – так называют не
только сам язык, но и платформу для создания приложений уровня предприятий на
основе данного языка.
Изначально
язык программирования назывался Oak (русск. Дуб) и разрабатывался Джеймсом
Гослингом для бытовой
электроники, но впоследствии был переименован в Java и стал использоваться для
написания клиентских приложений и серверного программного
обеспечения. Программы на Java транслируются в байт-код,
выполняемый виртуальной
java-машиной (JVM) – программой,
обрабатывающей байтовый код и передающей инструкции оборудованию как интерпретатор,
но с тем отличием, что байтовый код, в отличие от текста, обрабатывается
значительно быстрее. Достоинство подобного
способа выполнения программ – в полной независимости байт-кода от ОС и
оборудования, что позволяет выполнять Java-приложения на любом устройстве,
которое поддерживает виртуальную машину. Другой важной особенностью технологии
Java является гибкая система безопасности благодаря тому, что исполнение программы
полностью контролируется виртуальной машиной.
Длины и диапазоны значений примитивных типов определяются
стандартом. Такая жёсткая стандартизация была
необходима, чтобы сделать язык платформенно-независимым, что является одним из
идеологических требований к Java и одной из причин её успеха. Тем не менее,
одна небольшая проблема с платформенной независимостью всё же осталась.
Некоторые процессоры используют для промежуточного хранения результатов 10-байтовые регистры или другими
способами улучшают точность вычислений.
В языке Java имеются только динамически создаваемые объекты.
Причем переменные объектного типа и объекты
в Java – совершенно разные сущности. Переменные объектного типа являются ссылками, то есть неявными указателями на динамически
создаваемые объекты. Это подчёркивается синтаксисом описания переменных.
C# (произносится си-шарп) – язык
программирования, сочетающий объектно-ориентированные и аспектно-ориентированные концепции. Разработан в 1998–2001 годах группой инженеров под
руководством Андерса
Хейлсберга в компании Microsoft как основной язык
разработки приложений для платформы Microsoft.NET. C# относится к семье языков с C-подобным
синтаксисом, из них его синтаксис наиболее близок к С++ и Java. Язык имеет строгую
статическую типизацию, поддерживает полиморфизм, перегрузку
операторов, указатели на функции-члены классов, атрибуты, события, свойства, исключения, комментарии в формате XML. Переняв многое от
своих предшественников – языков С++, Java, Delphi, Модула и Smalltalk – С#, опираясь на
практику их использования, исключает некоторые модели, зарекомендовавшие себя
как проблематичные при разработке программных систем: так, C# не поддерживает множественное наследование классов (в отличие от C++).
В Java
модификатор protected в описании, помимо доступа из классов-потомков, разрешает
доступ из всех классов, входящих в тот же пакет, что и класс-владелец.
В C# для
объектов, которые должны быть видны в пределах сборки (примерный аналог пакета
Java) введён отдельный модификатор internal, а protected сохраняет свой
изначальный смысл, взятый из C++ – доступ только из классов-потомков.
Допускается комбинировать internal и protected – тогда получится область
доступа, соответствующая protected в Java.
Внутренние классы в C# имеют доступ только к статическим
членам внешнего класса, а для доступа к нестатическим членам нужно явно
указывать экземпляр внешнего класса. Локальные внутренние классы в C# не
поддерживаются, обработка событий в нём не требует таких классов, поскольку
строится на других механизмах. В обоих языках
методы, по аналогии с C++ – функции, определённые в классе. Тело метода
располагается внутри описания класса. Поддерживаются статические методы,
абстрактные методы. В C# также есть явная реализация методов интерфейса, что
позволяет классу реализовывать методы интерфейса отдельно от собственных
методов или давать разные реализации одноимённых методов, принадлежащих двум разным
интерфейсам. C# также поддерживает явное
описание передачи параметров по ссылке (ключевые слова ref и out). При
использовании out компилятор контролирует наличие в методе присваивания
значения. C# позволяет создавать пользовательские типы-значения, используя
ключевое слово struct
. Это прямое наследие языка С++ от которого создатели
Java сознательно отказались.
Java
поддерживает импорт статических имён (import static
)
из классов, позволяющий отдельно импортировать некоторые или все статические
методы и переменные класса и использовать их имена без квалификации в
импортирующем модуле. В C# импортируется только сборка и при каждом
использовании импортируемых статических имён требуется указывать класс.
В Java
константы в операторы switch
должны относиться либо к целочисленному, либо к перечислимому типу. В C#
в switch можно использовать текстовые строки.
Java содержит
конструкцию strictfp, гарантирующую одинаковые результаты операций с
плавающей точкой на всех платформах.
C# содержит
конструкции checked
и unchecked
, позволяющие локально включать и выключать
динамическую проверку арифметического переполнения.
C#
поддерживает оператор перехода goto. Обычное использование – передача
управления на разные метки case
в операторе switch
и выход из вложенного цикла. В Java от
использования goto сознательно отказались.
Java
поддерживает метки в циклах и позволяет использовать их в командах break и
continue, благодаря чему исключается такой повод использования goto, как выход
из вложенного цикла.
C#
поддерживает отдельное понятие именованной типизированной константы и ключевое
слово const
.
В Java констант как таковых нет, вместо них используются статические переменные
класса с модификатором final
– эффект от их использования точно такой
же.
Разработка
транслятора
Разработка лексического анализатора
Большие и
малые буквы английского алфавита: a..z, A..Z
Цифры:
0,1,2,3,4,5,6,7,8,9.
Другие
символы: ‘<’, ‘>’, ‘:’, ‘, ’, ‘’’, ‘;’, ‘{», ‘}’, ‘(», ‘)’
-
зарезервированные слова;
-
знаки операций и разделители;
-
литералы;
-
идентификаторы
1.
Класс
идентификаторы: к этому классу относятся все наборы цепочек, кроме
зарезервированных слов
2.
Класс зарезервированных слов:
2.1
Для C#
using,
class, int, float, char, public, protected, private, return, namespace
2.2
Для Java
using,
class, int, float, char, public, protected, private, return
3.
Класс
знаков операций и разделителей:
() {} :
; = -> . , ‘ *
4.
Класс
литералов:
Литерал –
целочисленная или текстовая константа.
Разработка синтаксического анализатора
В данном проекте
исследуется лишь малая часть возможностей и особенностей вышеуказанных языков.
В связи с этим спроектированные грамматики для этих языков будут включать лишь
те структуры языка, которые нам необходимы
Грамматика С#
1
<программа>:= 2 <предпроцессор> 3 namespace 4 {5 <операторы> 6}
7
<предпроцессор>:= 9 using 10 <предпроцессор>
8
<предпроцессор>:= 11 е
12
<операторы>:= 16 <класс> 17 <операторы>
13
<операторы>:= 18 идентификатор 19 <продолжение1>
20
<операторы>
14
<операторы>:= 21 е
15
<операторы>:= 22 <декларация> 23 <операторы>
24
<класс>:= 25 class 26 идентификатор 27 <наследование> 28 {29 <операторы>
30} 31;
32<наследование>:=
34: 35 идентификатор
33<наследование>:=
36е
37<продолжение1>:=
40. 41 идентификатор 42 <продолжение2> 43;
38<продолжение1>:=
44 <продолжение2> 45;
39<продолжение1>:=
46;
47
<продолжение2>:= 49 (50)
48
<продолжение2>:= 80 е
51
<декларация>:= 52 <тип> 53 идентификатор 55 <продолжение3>
56<продолжение3>:=
58 (59) 60 (61 <операторы> 62 return 63 литерал 64; 81)
57<продолжение3>:=
65<продолжение4>
66
<продолжение4>:= 68, 69 идентификатор 70 <продолжение4>
67
<продолжение4>:= 71;
72
<тип>:= 76 int
73
<тип>:= 77 float
74
<тип>:= 78 char
75
<тип>:= 79 идентификатор
Грамматика java
1
<программа>:= 2 <предпроцессор> 3 <операторы>
7
<предпроцессор>:= 9 using 10 <предпроцессор>
8
<предпроцессор>:= 11 е
12
<операторы>:= 16 <класс> 17 <операторы>
13
<операторы>:= 18 идентификатор 19 <продолжение1>
20
<операторы>
14
<операторы>:= 21 е
15
<операторы>:= 22 <декларация> 23 <операторы>
24
<класс>:= 25 class 26 идентификатор 27 <наследование> 28 {29 <операторы>
30} 31;
32<наследование>:=
34: 35 идентификатор
33<наследование>:=
36е
37<продолжение1>:=
40 -> 41 идентификатор 42
<продолжение2> 43;
38<продолжение1>:=
44 <продолжение2> 45;
39<продолжение1>:=
46;
47
<продолжение2>:= 49 (50)
48
<продолжение2>:= 80 е
51
<декларация>:= 52 <тип> 53 <ссылка> 54 идентификатор 55
<продолжение3>
56<продолжение3>:=
58 (59) 60 (61 <операторы> 62 return 63 литерал 64; 81)
57<продолжение3>:=
65<продолжение4>
66
<продолжение4>:= 68, 69 идентификатор 70 <продолжение4>
67
<продолжение4>:= 71;
72
<тип>:= 76 int
73
<тип>:= 77 float
74
<тип>:= 78 char
75
<тип>:= 79 идентификатор
82<ссылка>:=
84 *
83<ссылка>:=
85 e
Доказательство
принадлежности к LL(1) – грамматике
С#
<предпроцессор>={using | namespace}
<операторы>={class | идентификатор |} | int | float | char}
<наследование>={:
| {}
<продолжение1>={.
| (|;)
<продолжение2>={(|;)
<продолжение3>={(|,
|;)
<продолжение4>={,
|;}
<тип >={int | float | char | идентификатор}
Грамматика java
<предпроцессор>={using | class | идентификатор | int | float | char}
<операторы>={class | идентификатор | int | float | char}
<наследование>={:
| {}
<продолжение1>={->
| (|;)
<продолжение2>={(|;)
<продолжение3>={(|,
|;)
<продолжение4>={,
|;}
<тип >={int | float | char | идентификатор}
<ссылка>={*
| идентификатор}
Таблицы
разбора
Таблица разбора С#
№
|
Ожидаемый терминал
|
Переход
|
Принять
|
В стек
|
Из стека
|
Ошибка
|
1.
|
~
|
2
|
-
|
-
|
-
|
-
|
2.
|
~
|
7
|
-
|
-
|
-
|
-
|
3.
|
namespace
|
4
|
+
|
-
|
-
|
+
|
4.
|
{
|
5
|
+
|
-
|
-
|
+
|
5.
|
~
|
12
|
-
|
+
|
-
|
-
|
6.
|
}
|
0
|
+
|
-
|
+
|
+
|
7.
|
using
|
9
|
-
|
-
|
-
|
-
|
8.
|
~
|
11
|
-
|
-
|
-
|
-
|
9.
|
using
|
10
|
+
|
-
|
-
|
+
|
10.
|
~
|
7
|
-
|
-
|
-
|
-
|
11.
|
~
|
3
|
-
|
-
|
-
|
-
|
12.
|
class
|
16
|
-
|
-
|
-
|
-
|
13.
|
идентификатор
|
18
|
-
|
-
|
-
|
-
|
14.
|
}
|
21
|
-
|
-
|
-
|
-
|
15.
|
~
|
22
|
-
|
-
|
-
|
-
|
16.
|
~
|
24
|
-
|
+
|
-
|
-
|
17.
|
~
|
12
|
-
|
-
|
-
|
-
|
18.
|
идентификатор
|
19
|
+
|
-
|
-
|
+
|
19.
|
~
|
37
|
-
|
+
|
-
|
-
|
20.
|
~
|
12
|
-
|
-
|
-
|
-
|
21.
|
~
|
0
|
-
|
-
|
+
|
-
|
22.
|
~
|
51
|
-
|
+
|
-
|
-
|
23
|
~
|
12
|
-
|
-
|
-
|
-
|
24
|
~
|
25
|
-
|
-
|
-
|
-
|
25
|
class
|
26
|
+
|
-
|
-
|
+
|
26
|
идентификатор
|
27
|
+
|
-
|
-
|
+
|
27
|
~
|
32
|
-
|
+
|
-
|
-
|
28
|
{
|
29
|
+
|
-
|
-
|
+
|
29
|
~
|
12
|
-
|
+
|
-
|
-
|
30
|
)
|
31
|
+
|
-
|
-
|
+
|
31
|
;
|
0
|
+
|
-
|
+
|
+
|
32
|
:
|
34
|
-
|
-
|
-
|
-
|
33
|
~
|
-
|
-
|
-
|
-
|
34
|
:
|
35
|
+
|
-
|
-
|
+
|
35
|
идентификатор
|
0
|
+
|
-
|
+
|
+
|
36
|
~
|
0
|
-
|
-
|
+
|
-
|
37
|
.
|
40
|
-
|
-
|
-
|
-
|
38
|
(
|
44
|
-
|
-
|
-
|
-
|
39
|
;
|
46
|
-
|
-
|
-
|
+
|
40
|
.
|
41
|
+
|
-
|
-
|
+
|
41
|
идентификатор
|
42
|
+
|
-
|
-
|
+
|
42
|
~
|
47
|
-
|
+
|
-
|
-
|
43
|
;
|
0
|
+
|
-
|
+
|
+
|
44
|
~
|
47
|
-
|
+
|
-
|
-
|
45
|
;
|
0
|
+
|
-
|
+
|
+
|
46
|
;
|
0
|
+
|
-
|
+
|
+
|
47
|
(
|
49
|
-
|
-
|
-
|
-
|
48
|
~
|
80
|
-
|
-
|
-
|
-
|
49
|
(
|
50
|
+
|
-
|
-
|
+
|
50
|
)
|
0
|
+
|
-
|
+
|
+
|
51
|
~
|
52
|
-
|
-
|
-
|
-
|
52
|
~
|
72
|
-
|
+
|
-
|
-
|
53
|
идентификатор
|
55
|
+
|
-
|
-
|
+
|
54
|
|
|
|
|
|
|
55
|
~
|
56
|
-
|
-
|
-
|
-
|
56
|
(
|
58
|
-
|
-
|
-
|
-
|
57
|
~
|
65
|
-
|
-
|
-
|
-
|
58
|
(
|
59
|
+
|
-
|
-
|
+
|
59
|
)
|
60
|
+
|
-
|
-
|
+
|
60
|
{
|
61
|
+
|
-
|
-
|
+
|
61
|
~
|
12
|
-
|
+
|
-
|
-
|
62
|
return
|
63
|
+
|
-
|
-
|
+
|
63
|
литерал
|
64
|
+
|
-
|
-
|
+
|
64
|
;
|
81
|
+
|
-
|
-
|
+
|
65
|
~
|
66
|
-
|
-
|
-
|
-
|
66
|
,
|
68
|
-
|
-
|
-
|
-
|
67
|
;
|
71
|
-
|
-
|
-
|
+
|
68
|
,
|
69
|
+
|
-
|
-
|
+
|
69
|
идентификатор
|
70
|
+
|
-
|
-
|
+
|
70
|
~
|
66
|
-
|
-
|
-
|
-
|
71
|
;
|
0
|
+
|
-
|
+
|
+
|
72
|
int
|
76
|
-
|
-
|
-
|
-
|
73
|
float
|
77
|
-
|
-
|
-
|
-
|
74
|
char
|
78
|
-
|
-
|
-
|
-
|
75
|
идентификатор
|
79
|
-
|
-
|
-
|
+
|
76
|
int
|
0
|
+
|
-
|
+
|
+
|
77
|
float
|
0
|
+
|
-
|
+
|
+
|
78
|
char
|
0
|
+
|
-
|
+
|
+
|
79
|
идентификатор
|
0
|
+
|
-
|
+
|
+
|
80
|
~
|
0
|
-
|
-
|
+
|
-
|
81
|
}
|
0
|
+
|
-
|
+
|
+
|
Таблица разбора java
№
|
Ожидаемый терминал
|
Переход
|
Принять
|
В стек
|
Из стека
|
Ошибка
|
1.
|
~
|
2
|
-
|
-
|
-
|
-
|
2.
|
~
|
-
|
-
|
-
|
-
|
3.
|
~
|
12
|
-
|
-
|
-
|
-
|
7.
|
using
|
9
|
-
|
-
|
-
|
-
|
8.
|
~
|
11
|
-
|
-
|
-
|
-
|
9.
|
using
|
10
|
+
|
-
|
-
|
+
|
10.
|
~
|
7
|
-
|
-
|
-
|
-
|
11.
|
~
|
3
|
-
|
-
|
-
|
-
|
12.
|
class
|
16
|
-
|
-
|
-
|
-
|
13.
|
идентификатор
|
18
|
-
|
-
|
-
|
-
|
14.
|
}
|
21
|
-
|
-
|
-
|
-
|
15.
|
~
|
22
|
-
|
-
|
-
|
-
|
16.
|
~
|
24
|
-
|
+
|
-
|
-
|
17.
|
~
|
12
|
-
|
-
|
-
|
-
|
18.
|
идентификатор
|
19
|
+
|
-
|
-
|
+
|
19.
|
~
|
37
|
-
|
+
|
-
|
-
|
20.
|
~
|
12
|
-
|
-
|
-
|
-
|
21.
|
~
|
0
|
-
|
-
|
+
|
-
|
22.
|
~
|
51
|
-
|
+
|
-
|
-
|
23
|
~
|
12
|
-
|
-
|
-
|
-
|
24
|
~
|
25
|
-
|
-
|
-
|
-
|
25
|
class
|
26
|
+
|
-
|
-
|
+
|
26
|
идентификатор
|
27
|
+
|
-
|
-
|
+
|
27
|
~
|
32
|
-
|
+
|
-
|
-
|
28
|
{
|
29
|
+
|
-
|
-
|
+
|
29
|
~
|
12
|
-
|
+
|
-
|
-
|
30
|
)
|
31
|
+
|
-
|
-
|
+
|
31
|
;
|
0
|
+
|
-
|
+
|
+
|
32
|
:
|
34
|
-
|
-
|
-
|
-
|
33
|
~
|
36
|
-
|
-
|
-
|
-
|
34
|
:
|
35
|
+
|
-
|
-
|
+
|
35
|
идентификатор
|
0
|
+
|
-
|
+
|
+
|
36
|
~
|
0
|
-
|
-
|
+
|
-
|
37
|
->
|
40
|
-
|
-
|
-
|
-
|
38
|
(
|
44
|
-
|
-
|
-
|
-
|
39
|
;
|
46
|
-
|
-
|
-
|
+
|
40
|
->
|
41
|
+
|
-
|
-
|
+
|
41
|
идентификатор
|
42
|
+
|
-
|
-
|
+
|
42
|
~
|
47
|
-
|
+
|
-
|
-
|
43
|
;
|
0
|
+
|
-
|
+
|
+
|
44
|
~
|
47
|
-
|
+
|
-
|
-
|
45
|
;
|
0
|
+
|
-
|
+
|
+
|
46
|
;
|
0
|
+
|
-
|
+
|
+
|
47
|
(
|
49
|
-
|
-
|
-
|
-
|
48
|
~
|
80
|
-
|
-
|
-
|
-
|
49
|
(
|
50
|
+
|
-
|
-
|
+
|
50
|
)
|
0
|
+
|
-
|
+
|
+
|
51
|
~
|
52
|
-
|
-
|
-
|
-
|
52
|
~
|
72
|
-
|
+
|
-
|
-
|
53
|
~
|
82
|
-
|
-
|
+
|
-
|
54
|
идентификатор
|
55
|
+
|
-
|
-
|
+
|
55
|
~
|
56
|
-
|
-
|
-
|
56
|
(
|
58
|
-
|
-
|
-
|
-
|
57
|
~
|
65
|
-
|
-
|
-
|
-
|
58
|
(
|
59
|
+
|
-
|
-
|
+
|
59
|
)
|
60
|
+
|
-
|
-
|
+
|
60
|
{
|
61
|
+
|
-
|
-
|
+
|
61
|
~
|
12
|
-
|
+
|
-
|
-
|
62
|
return
|
63
|
+
|
-
|
-
|
+
|
63
|
литерал
|
64
|
+
|
-
|
-
|
+
|
64
|
;
|
81
|
+
|
-
|
-
|
+
|
65
|
~
|
66
|
-
|
-
|
-
|
-
|
66
|
,
|
68
|
-
|
-
|
-
|
-
|
67
|
;
|
71
|
-
|
-
|
-
|
+
|
68
|
,
|
69
|
+
|
-
|
-
|
+
|
69
|
идентификатор
|
70
|
+
|
-
|
-
|
+
|
70
|
~
|
66
|
-
|
-
|
-
|
-
|
71
|
;
|
0
|
+
|
-
|
+
|
+
|
72
|
int
|
76
|
-
|
-
|
-
|
-
|
73
|
float
|
77
|
-
|
-
|
-
|
-
|
74
|
char
|
78
|
-
|
-
|
-
|
-
|
75
|
идентификатор
|
79
|
-
|
-
|
-
|
+
|
76
|
int
|
0
|
+
|
-
|
+
|
+
|
77
|
float
|
0
|
+
|
-
|
+
|
+
|
78
|
char
|
0
|
+
|
-
|
+
|
+
|
79
|
идентификатор
|
0
|
+
|
-
|
+
|
+
|
80
|
~
|
0
|
-
|
-
|
+
|
-
|
81
|
}
|
0
|
+
|
-
|
+
|
+
|
82
|
*
|
84
|
-
|
-
|
-
|
-
|
83
|
~
|
85
|
-
|
-
|
-
|
-
|
84
|
*
|
0
|
+
|
-
|
+
|
+
|
85
|
~
|
0
|
-
|
-
|
+
|
-
|
Разработка программы
Диаграмма прецедентов
Диаграмма классов
Анализ результатов работы программы и выводы
Оба
анализируемых языка – объектно-ориентированные, с синтаксисом,
унаследованным от C++, но значительно переработанным. Следовательно, они имеют
много общего, например, при анализе проектов, мы используем один общий класс
разделителей и знаков операций.
Классы
зарезервированных слов для каждого языка отличаются. В данном проекте
исследуется лишь малая часть возможностей и особенностей вышеуказанных языков.
В связи с этим, классы зарезервированных слов для этих языков будут включать
лишь те ключевые слова и операторы, которые нам необходимы.
Проект
позволяет проанализировать взаимодействие между классами и вывести результат в
файл *.xml. Достаточно много времени было потрачено именно на вывод
результата в *.xml, так как ранее с подобными задачами не сталкивались.
При
реализации были выполнены критерии ООП и модульности, расставлены комментарии
(по атрибутам, методам, по параметрам методов, классам).
Проект может
существовать как автономное приложение, однако, на мой взгляд, его можно
дополнить и доработать функционально, расширить классы зарезервированных слов,
внести изменения в LL(1) – грамматику и т.д.
На данном
этапе разработки программа работает корректно, четко выполняет поставленные
требования.
Список
используемой литературы
1. Р. Хантер Проектирование
и конструирование компиляторов
2. http://javaportal.ru/
5.
Конспект лекций по ТОПТ