Project

General

Profile

Транслятор с языка Sim-nML » History » Version 1

Alexander Kamkin, 09/30/2011 02:12 PM

1 1 Alexander Kamkin
h1. Транслятор с языка Sim-nML
2
3
Данный документ содержит описание схемы трансляции спецификаций микропроцессоров на языке Sim-nML в набор Java классов, которые могут быть использованы инструментом MicroTESK для автоматизированной генерации тестовых программ.
4
5
h2. Язык Sim-nML
6
7
Язык Sim-nML является расширением языка nML.
8
Грамматика языка доступна по адресу: http://www.cse.iitk.ac.in/users/simnml/docs/parser.pdf
9
Описание языка доступно по адресу: http://www.cse.iitk.ac.in/users/simnml/docs/simnml.pdf
10
11
h2. Java классы, создаваемые при трансляции
12
13
Список Java классов, которые создаются при трансляции:
14
1.Класс ProcessorName, который наследуется от класса Processor. Содержит большую часть информации о специфицируемом процессоре.
15
TODO: уточнить, каким образом формируется имя этого класса. Возможен вариант получаеть это имя из имени файла со спецификацией на Sim-nML, или же можно требовать задавания этого имени от пользователя в качестве одного из параметров метода, который осуществляет трансляцию, или же можно использовать какие-то специальные аннотации в самой спецификации.
16
Правила грамматики для «общих» нетерминальных символов
17
Бинарная операция
18
Правила грамматики для определения бинарных операций.
19
BinOp
20
:
21
''+''
22
23
|
24
''-''
25
26
|
27
''*''
28
29
|
30
''/''
31
32
|
33
''%''
34
35
|
36
DOUBLE_STAR
37
38
|
39
LEFT_SHIFT
40
41
|
42
RIGHT_SHIFT
43
44
|
45
ROTATE_LEFT
46
47
|
48
ROTATE_LEFT
49
50
|
51
ROTATE_RIGHT
52
53
|
54
''<''
55
56
|
57
''>''
58
59
|
60
LEQ
61
62
|
63
GEQ
64
65
|
66
EQ
67
68
|
69
NEQ
70
71
|
72
''&''
73
74
|
75
''^''
76
77
|
78
''|''
79
80
|
81
AND
82
83
|
84
OR
85
Числовая константа
86
Правила грамматики для определения числовых констант.
87
ConstNumExpr
88
:
89
ConstExprVal
90
91
|
92
ConstNumExpr BinOp ConstExprVal
93
ConstExprVal
94
:
95
CARD_CONST
96
97
|
98
FIXED_CONST
99
100
|
101
HEX_CONST
102
103
|
104
''!'' ConstNumExpr
105
106
|
107
''~'' ConstNumExpr
108
109
|
110
''+'' ConstNumExpr %prec ''~''
111
112
|
113
''-'' ConstNumExpr %prec ''~''
114
115
|
116
''('' ConstNumExpr '')''
117
TODO: предлагается все числовые константные выражения сразу вычислять, в оттранслированный Java код вставлять уже только значения выражений.
118
Выражение
119
Правила грамматики для определения выражений
120
Bit_Expr
121
:
122
ID
123
124
|
125
Bit_Expr ''+'' Bit_Expr
126
127
|
128
Bit_Expr ''-'' Bit_Expr
129
130
|
131
Bit_Expr ''*'' Bit_Expr
132
133
|
134
Bit_Expr ''/'' Bit_Expr
135
136
|
137
Bit_Expr ''%'' Bit_Expr
138
139
|
140
Bit_Expr DOUBLE_STAR Bit_Expr
141
142
|
143
''('' Bit_Expr '')''
144
145
|
146
FIXED_CONST
147
148
|
149
CARD_CONST
150
151
|
152
STRING_CONST
153
154
|
155
BINARY_CONST
156
157
|
158
HEX_CONST
159
OR правило
160
OrRule
161
:
162
Identifier_Or_List
163
Identifier_Or_List
164
:
165
ID
166
167
|
168
Identifier_Or_List ''|'' ID
169
AND правило
170
AndRule
171
:
172
''('' ParamList '')''
173
ParamList
174
:
175
176
177
|
178
ParamListPart
179
180
|
181
ParamList '','' ParamListPart
182
ParamListPart
183
:
184
ID '':'' TypeExpr
185
186
|
187
ID '':'' ID
188
189
Атрибуты
190
В языке Sim-nML атрибуты используются для описания свойств инструкций и режимов адресации. Описание каждого такого объекта может содержать произвольное число атрибутов. Атрибуты можно разделить на два класса: предопределенные атрибуты и пользовательские атрибуты. Описание предопределенных атрибутов приведено ниже.
191
Правила грамматики для атрибутов:
192
AttrDefList
193
:
194
195
196
|
197
AttrDefList AttrDef
198
AttrDef
199
:
200
ID ''='' AttrDefPart
201
202
|
203
SYNTAX ''='' ID ''.'' SYNTAX
204
205
|
206
SYNTAX ''='' AttrExpr
207
208
|
209
IMAGE ''='' ID ''.'' IMAGE
210
211
|
212
IMAGE ''='' AttrExpr
213
214
|
215
ACTION ''='' ID ''.'' ACTION
216
217
|
218
ACTION ''='' ''{'' Sequence ''}''
219
220
|
221
USES ''='' UsesDef
222
AttrDefPart
223
:
224
Expr
225
226
|
227
''{'' Sequence ''}''
228
Атрибут syntax
229
Атрибут syntax используется для описания ассемблерного кодирования инструкции или режима адресации. Значения данного атрибута должны иметь строковый тип. Можно выделить следующие основные варианты определения атрибута syntax:
230
1)Строковая константа — значение определяется посредством строковой константы. Например, “nop”.
231
2)Атрибут параметра — значение атрибута определяется как значение этого же атрибута syntax у одного из параметров описываемого объекта. Например, x.syntax.
232
3)Форматированная строка — значение атрибута определяется с помощью специальной конструкции format. Данная конструкция является аналогом оператора printf в языке программирования С. Например, format(“%5b”, r).
233
// TODO: добавить полное формальное описание конструкции format + описание транслчции данной конструкции в строковое выражение Java
234
Трансляция:
235
При трансляции данного атрибута в классе, соответствующем описываемому объекту создается метод со следующей сигнатурой:
236
public String syntax()
237
Для случая 1 из приведенного выше списка тело метода просто возвращает данную строковую константу. Для случая 2 метод возвращает результат вызова метода syntax соответствующего аргумента данного объекта. Такой аргумент должен содержаться в качестве поля в классе, соответствующем описываемому объекту. Для случая 3 метод возвращает результат трансляции конструкции format в строковое выражение языка Java.
238
Атрибут image
239
Атрибут image используется для описания бинарного кодирования описываемого объекта. Значения данного атрибута должны иметь строковый тип, причем допустимы только строки, содержащие символы «0», «1» и пробел. Пробелы используются для улучшения читаемости. Варианты определения атрибута image совпадают с вариантами определения атрибута syntax.
240
Трансляция:
241
Полностью аналогична трансляции атрибута syntax.
242
Атрибут action
243
Атрибут action используется для описания семантики выполнения инструкций. 
244
Трансляция:
245
// TODO: при трансляции атрибута action обратить внимание на то, что в некоторых спецификациях данные между соседними в дереве инструкциями передают с использованием переменных (var). Это надо корректно учитывать, так как по умолчанию при трансляции таких объектов предлагается создавать локальные переменные соответствующих методов. С другой стороны, использование переменных для передачи данных между операциями противоречит описанию языка, в котором сказано, что состояние переменных не сохраняется при переходе от одной инструкции к другой.
246
Атрибут uses
247
В текущей версии инструмента данный атрибут не рассматриваем.
248
Основные конструкции языка
249
250
h3. Конструкция let
251
252
Конструкция let используется для объявления констант. Константы обладают следующими свойтсвами:
253
1.Константы получают глобальную область видимости.
254
2.Константа может быть определена только один раз.
255
Правила грамматики для конструкции let:
256
LetDef 
257
:
258
LET ID ''='' LetExpr
259
LetExpr
260
:
261
ConstNumExpr
262
263
|
264
STRING_CONST
265
266
|
267
IF ConstNumExpr THEN LetExpr OptionalElseLetExpr ENDIF
268
269
|
270
SWITCH ''('' ConstNumExpr '')'' ''{'' CaseLetExprList ''}''
271
OptionalElseLetExpr
272
:
273
274
275
|
276
ELSE LetExpr
277
CaseLetExprList
278
:
279
CaseLetExprList1
280
281
|
282
CaseLetExprList1 DEFAULT '':'' LetExpr
283
CaseLetExprList1
284
:
285
CaseLetExprStat
286
287
|
288
CaseLetExprList1 CaseLetExprStat
289
CaseLetExprStat
290
:
291
CASE ConstNumExpr '':'' LetExpr
292
293
Примеры:
294
let REGS = 5
295
let byte_order = “big”
296
let PC = “NIA”
297
let SP = “GPR[29]”
298
Проблемы:
299
Не ясна семантика if и switch в том случае, когда определяемая величина не получает никакого значения, например
300
let c = if 0 then 0 endif
301
Ограничения:
302
На первом этапе разработки прототипа предлагается ограничить поддержку конструкции let только простыми вариантами (без if и switch). Сложные вариаты let практически не используются на практике (ни один из примеров спецификаций представленных на сайте языка не содержал таких конструкций), их ценность представляется сомнительной.
303
Трансляция:
304
Если LetExpr является ConstNumExpr, то вычисляется значение этого выражения. Для каждой определенной в спецификации константы определяется поле к классе ProcessorName следующего вида
305
	public static final <type> ID = LetExpr;
306
где <type> может принимать следующие значения:
307
String – в случае, если LetExpr является STRING_CONST
308
int – в случае, если LetExpr является числовым выражением и вычисленное  значение есть целое.число, убирающееся в int.
309
long – в случае, если LetExpr является числовым выражением и вычисленное  значение есть целое.число, не убирающееся в int.
310
float – в случае, если  LetExpr является числовым выражением и его вычисленное значение есть число с фиксированной или плавающей точкой, убирающееся в тип float.
311
double – в случае, если  LetExpr является числовым выражением и его вычисленное значение есть число с фиксированной или плавающей точкой, не убирающееся в тип float.
312
Ошибочные ситуации:
313
наличие целых чисел, которые «не убираются» в long
314
наличие чисел с плавающей точкой, которые «не убираются» в double
315
Конструкция type
316
Конструкция type используется для определения синонимов новых типов. Синонимы определяются на основе существующих стандартных типов:
317
bool: определяет булевский тип, имеющий два предопределенных значений false и true. При применении преобразования типов (смотри coerces) false отображается в 0, true – в 1. При обратном преобразовании 0 отображается в false, любое ненулевое значение отображается в true.
318
int(n):определяет интервал целых чисел 
319
card(n): определяет интервал натуральных чисел 
320
float: определяет число с плавающей точкой согласно стандарту IEEE754 // TODO: несоответствие грамматики и описания
321
fix(n, m):определяет число с фиксированной точкой, в котором n бит отводятся под мантису и m бит под экспоненту.// TODO: уточнить, что описано в документации
322
[n..m]: определяет интервал натуральных чисел (ограничение)
323
enum(): определяет перечислимый тип, где именованные константы принимают значения от 0 до n-1.Будет совпадать с типом card(ceiling())
324
Правила грамматики для конструкции type:
325
TypeSpec
326
:
327
TYPE ID ''='' TypeExpr
328
TypeExpr
329
:
330
BOOL
331
332
|
333
INT ''('' ConstNumExpr '')''
334
335
|
336
CARD ''('' ConstNumExpr '')''
337
338
|
339
FIX ''('' ConstNumExpr '','' ConstNumExpr '')''
340
341
|
342
FLOAT ''('' ConstNumExpr '','' ConstNumExpr'')''
343
344
|
345
''['' ConstNumExpr DOUBLE_DOT ConstNumExpr '']''
346
347
|
348
ENUM ''('' IdentifierList '')''
349
IdentifierList
350
:
351
ID
352
353
|
354
ID ''='' CARD_CONST
355
356
|
357
IdentifierList '','' ID
358
359
|
360
IdentifierList '','' ID ''='' CARD_CONST
361
362
Примеры:
363
type bit
364
 =
365
card ( 1 )
366
type byte
367
 =
368
card ( 8 )
369
type address
370
 =
371
card ( REGS )
372
type breakcode
373
 =
374
card (20 )
375
376
Проблемы:Моделирование чисел с фиксированной точкой.
377
Ограничения: в текущей реализации не рассматриваем случаи, когда определяется интервал, по мощности превосходящий максимальный соответствующий стандартный тип а Java. Например, исключаем из рассмотрения card (128).
378
Трансляция: 
379
Для каждого такого типа-синонима создается новый класс с именем ID, единственным полем которого будет переменная объемлющего типа, а методы будут обеспечивать корректность работы с этой переменной, контролируя невыход их множества допустимых значений. В случае нарушения данных ограничений метод должен выбрасывать исключение.
380
Необходимо учесть, что при трансляции операторов присваивания таким переменным, надо использовать методы set из соответствующих классов. Причем эти методы set должны в качестве параметров принимать так же номер строки и позицию в nml файле, по которой находится данный оператор присваивания. Эти данные используются отладки спецификаций в случае ошибок.
381
Перечисления транслируются в стандартные Java перечисления. Например, пусть есть перечисление:
382
type <name> = enum(id1 = val1, id2 = val2, …, idn = valn)
383
Оно транслируется в отдельный файл <name>.java, который содержит Java перечисление следующего вида:
384
public enum <name> {
385
	id1(val1), id2(val2), …, idn(valn)
386
}
387
Ошибочные ситуации:
388
389
h3. Конструкция mem
390
391
Конструкция mem используется для описания памяти моделируемого микропроцессора. Общий вид такого определения представлен ниже:
392
mem M [N, type] [optional-properties]
393
В этом определении, M – имя данного объекта памяти, N – количество ячеек памяти, и type – тип каждой такой ячейки памяти. Если тип не указан, то по умолчанию тип полагается равным card(8). Доступ к данным ячейкам памяти осуществляется по средствам оператора индексирования:M[0], M[1], … , M[n-1]. Опциональные параметры могут быть следующими:
394
alias – описывает новую память как синоним какойто части уже описанной памяти. В этом случае оба имени будут ссылать на одни и те же ячейки памяти, но могут интерпретировать их по разному. Например:
395
mem A[6, int(32)]
396
mem M[3, card(32)] alias = A[3]
397
В этом случае ячейки памяти, доступные по обращениям A[3], A[4], A[5], теперь могут быть доступны и по обращениям M[0], M[1], M[2] соответственно. Отличие заключается в том, что в случае обращений с использованием имени A содержимое ячейки интерпретируется как 32-ух разрядное знаковое число, в случае же, когда обращение идет по имени M, содержимое интерпретируется, как беззнаковое число.
398
Правила грамматики для конструкции mem:
399
Bit_Optr : BIT_LEFT Bit_Expr DOUBLE_DOT Bit_Expr BIT_RIGHT
400
MemorySpec
401
:
402
MEM ID ''['' SizeType '']'' OptionalMemVarAttr
403
SizeType
404
:
405
TypeExpr
406
407
|
408
ConstNumExpr
409
410
|
411
ConstNumExpr '','' TypeExpr
412
OptionalMemVarAttr
413
:
414
415
416
|
417
ALIAS ''='' MemLocation
418
MemLocation
419
:
420
ID Opt_Bit_Optr
421
422
|
423
ID ''['' NumExpr '']'' Opt_Bit_Optr
424
Opt_Bit_Optr
425
:
426
427
428
|
429
Bit_Optr
430
Bit_Optr
431
:
432
BIT_LEFT Bit_Expr DOUBLE_DOT Bit_Expr BIT_RIGHT
433
434
// TODO: не ясна семантика Opt_Bit_Expr в грамматики для конструкции
435
 mem, в примерах использование именно такой формы тоже не было встречено.
436
Примеры:
437
	mem A[6, int(32)]
438
	mem M[3, card(32)] alias = A[3] 
439
Проблемы:
440
Ограничения:
441
Трансляция:
442
Анализ спецификаций на языке Sim-nML позволил выявить, что конструкция mem может быть использована для двух различных целей. Во-первых, она может использоваться для описания памяти моделируемого микропроцессора. В этом случае число ячеек памяти в описании довольно большое (N >> 1). Необходимо найти описание с максимальным числом ячеек, именно оно будет транслироваться в класс, моделирующий память. При трансляции данного описания создается класс ProcessorNameMemory, который является наследником абстрактного класса Memory из библиотеки поддержки трансляции. Класс ProcessorNameMemory имеет следующий вид:
443
class ProcessorNameMemory {
444
	public static final SIZE = <N>;
445
	protected HashMap(Long, <type>) memoryHashMap = new HashMap(Long, <type>)();
446
}
447
Для всех других описаний памяти, которые являются синонимами основной памяти (используют alias <имя основной памяти>), в атрибутах action для операций необходимо изменять обращения по этим именам на обращения по имени основной памяти.
448
Второй класс описаний памяти составляют описания, которые имеют небольшое число ячеек (обычно 1 или 2). Такие описания используются в качестве локальных переменных при описании атрибутов action для инструкций. Все такие описания при трансляции запоминаются. Затем при трансляции атрибутов action в методы инструкций, для каждой запомненной памяти, по которой присутствует обращение в данном атрибуте, вводится локальная переменная соответствующего типа. Все обращения по данным элементам памяти заменяются при трансляции на обращения к данной переменной. Например,
449
	mem tmp_signed_byte [ 1 , int (32) ]
450
451
	action = {
452
		 tmp_signed_byte = 31
453
454
	}
455
При трансляции атрибута action получаем получим:
456
	public void execute(...) {
457
		int tmp_signed_byte
458
459
	}
460
461
// TODO: определить абстрактный класс Memory
462
463
Ошибочные ситуации:
464
465
h3. Конструкция reg
466
467
Конструкция reg используется для описания регистров микропроцессора. Общая форма описания регистров представлена ниже:
468
reg R [N, type] [optional-properties]
469
В представленном определении R – имя регистрового файла, N – опциональный параметр, показывающий количество регистров в регистровом файле и type – тип каждого регистра. Если параметр N не указан, то по умолчанию он полагается равным 1.Доступ к регистрам данного регистрового файла осуществляется посредством оператора индексирования — R[0], R[1], …, R[N-1]. Определение регистров может иметь следующие опциональные атрибуты:
470
Ports: позволяет указать число портов чтения и записи для данного регистрового файла. Например:
471
reg R[16, int(8)] port = 3, 2
472
В представленном примере регистровый файл R имеет 3 порта для записи и 2 порта для чтения. Кроме того, каждый регистр в данном регистровом файле имеет 2 порта для чтения, так же как и весь регистровый файл, и один порт для записи. Порты чтения и записи для регистров рассматриваются в качестве ресурсов и используются для определения зависимостей между инструкциями.
473
Initial: позволяет указать начальное значение для описанных регистров. Например:
474
reg R[1, card(32)] initial = 100
475
Правила грамматики для конструкции reg:
476
RegisterSpec
477
:
478
REG ID ''['' SizeType '']'' OptionalRegAttr
479
OptionalRegAttr
480
:
481
482
483
|
484
PortsDef
485
486
|
487
InitialDef
488
489
|
490
PortsDef InitialDef
491
492
|
493
InitialDef PortsDef
494
PortsDef
495
:
496
PORTS ''='' CARD_CONST '','' CARD_CONST
497
InitialDef
498
:
499
INITIALA ''='' ConstNumExpr
500
501
Примеры:
502
	reg GPR [2 ** REGS, signed_long]
503
	reg LO [1, signed_long]
504
	reg NIA [1, long]
505
Проблемы:
506
Ограничения:
507
Трансляция:
508
Для каждого описанного регистрового файла создается класс RegisterFileName, который является наследником абстрактного класса библиотеки поддержки трансляции Register. Класс Register содержит следующие поля и методы:
509
class Register {
510
	public static final int WRITE_PORTS = 1;
511
	public static final int READ_PORTS = 1;
512
	...
513
}
514
Класс RegisterFileName содержит следующие поля и методы:
515
class RegisterFileName {
516
	public static final int READ_PORTS = <read_ports>;
517
	protected <type> value = <init_value>;
518
	...
519
}
520
Так же в класс ProcessorName добавляются следующие поля и методы:
521
	public static final int RegisterFileName_WRITE_PORTS = <write_ports>;
522
	protected RegisterFileName <some_uniq_name> [] = {
523
		new RegisterFileName(),
524
		...
525
	}
526
Причем количество элементов в массиве RegisterFileName равно N.
527
Ошибочные ситуации:
528
529
h3. Конструкция var
530
531
Конструкция var используется для определения временных переменных. Типичная конструкция определения временной переменной выглядит следующим образом:
532
var TEMP[N, type]
533
В приведенном выше определении TEMP – имя массива временных переменных, N – количество переменных в определенном массиве и type – тип каждой переменной в массиве. Если параметр N не определен, то по умолчанию он полагается равным 1. Доступ к переменным осуществляется посредством оператора индексирования — TEMP[0], TEMP[1], …, TEMP[N-1]. Важно отметить, что значения временных переменных не сохраняются при переходе от одной инструкции к другой.
534
// COMMENT: по всей видимости переменные были введены в язык для прекращения нецелевого использования конструкций определения памяти для введения временных данных. Смотри второй класс конструкций определения памяти в разделе «трансляция» описания конструкции mem.
535
Правила грамматики для конструкции var:
536
// TODO: противоречие между текстовым описанием и грамматикой.
537
VarSpec
538
:
539
VAR ID ''['' SizeType '']'' OptionalMemVarAttr
540
541
Примеры:
542
	var amod[1, card(8)]
543
	var carry[1, card(1)]
544
	var op1[1, int(32)]
545
Проблемы:
546
Ограничения:
547
Трансляция:
548
Трансляция выполняется аналогично второму классу конструкций определения памяти. Описание приводится в разделе «трансляция» описания конструкции mem.
549
Ошибочные ситуации:
550
Конструкция mode
551
Конструкция mode используется для спецификации механизмов адресации. Основу данного описания этих механизмов составляют два вида конструкций: «И»-правила и «ИЛИ»-правила.
552
«ИЛИ»-правила используются для описания логически связанной группы механизмов адресации. С помощью «ИЛИ»-правила можно задать группе таких механизмов общие атрибуты. Общий вид «ИЛИ»-правила следующий:
553
554
555
«И»-правила используются для описания листовых элементов в дереве механизмов адресации. Общий вид «И»-правила следующий:
556
557
558
Правила грамматики для конструкции mode:
559
ModeRuleSpec
560
:
561
MODE ID ModeSpecPart
562
ModeSpecPart
563
:
564
AndRule OptionalModeExpr AttrDefList
565
566
|
567
OrRule
568
OptionalModeExpr
569
:
570
571
572
|
573
''='' Expr
574
Примеры:
575
Проблемы:
576
Ограничения:
577
Трансляция:
578
Трансляция дерева «И»-«ИЛИ» правил проводится идентично как для инструкций, так и для режимов адресации. Подробные описания общих концепций трансляции приведены в разделе «Трансляция» описания конструкции op. Эти положения верны и при описании режимов адресации. Специфические моменты при трансляции этих описаний отражены ниже.
579
У и правил конструкции mode может присутствовать дополнительный опциональный элемент, который вычисляет значение параметра, передающегося данным способом адресации. Для каждого правила, обладающего таким элементом, в соответствующем классе создается тело метода getValue() на основе описания данного элемента. Метод возвращает оттранслированное выражение записанное в правиле после знака равенства.
580
Ошибочные ситуации:
581
582
h3. Конструкция op
583
584
Конструкция op используется для описания системы команд моделируемого процессора.
585
Правила грамматики для конструкции op:
586
OpRuleSpec
587
:
588
OP ID OpRulePart
589
OpRulePart
590
:
591
AndRule AttrDefList
592
593
|
594
OrRule
595
596
Примеры:
597
Проблемы:
598
Ограничения:
599
Трансляция:
600
Общие положения при трансляции древовидной структуры «И»-«ИЛИ» правил заключаются в следующем. Для каждого правила создается класс. Классы, соответствующие элементам из правых частей «ИЛИ» правил связываются с классом, соответствующим элементу в левой части, отношением наследования. Каждый класс, соответствующий элементу из списка параметров в «И»-правиле, связывается с классом, соответствующим элементу из левой части правила, отношением агрегации. На примере ниже продемонстрированы данные принципы с использованием нотации UML для отображения зависимостей между классами.
601
op instruction(inst alu_op)
602
op alu_instruction = add | sub
603
В каждом из этих классов создаются методы, соответствующие атрибутам. Механизм трансляции атрибутов подробно описан в разделе «Атрибуты». Имена создаваемых классов должны содержать некоторый служебный суффикс, что будет говорить о служебном внутреннем использовании данных классов. 
604
Для каждого элемента из списка параметров «И» правила в соответствующем классе создаются поле. Для класса также создается конструктор с сигнатурой, соответствующей данному правилу, который инициализирует эти поля.
605
// TODO: посмотреть информацию про модификаторы доступа классов, пакетов для защиты служебных классов от некорректного использования.
606
Далее, для каждого листового элемента в дереве инструкций создается еще один класс, который наследуется от класса Instruction (соответствует корню дерева). Эти классы распределяются по пакетам в соответствии со структурой дерева. Для каждого не листового узла дерева создается отдельный пакет, куда вложены все пакеты и классы, соответствующие потомкам данного узла.
607
Ошибочные ситуации: