Project

General

Profile

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

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