- •Министерство образования
- •Исходная постановка задачи
- •1. Описание входного языка
- •2. Этап лексического анализа Определение типов лексем
- •Соотношения токенов и лексем.
- •Функции лексического анализатора
- •3. Описание синтаксического анализа
- •1) Главная подграмматика
- •2) Подграмматика if/for
- •3) Подграмматика объявлений
- •5. Тестирование дмп-процессора
3. Описание синтаксического анализа
3.1 Исходная порождающая КС-грамматика
S–начальный нетерминальный символ.
S->VOID MAIN ( )Instruction
S->VOID MAIN ( )
Instruction->InstExp
Instruction -> Comp_Instr }
Instruction -> If_Instr
Instruction -> For_Instr
Instruction -> Def_Instr
Instruction -> CIN >> _ID
Instruction -> COUT << InstExp
InstExp -> Expression ;
Comp_Instr -> { Foll_Ins
Comp_Instr -> {
Foll_Ins -> Foll_Ins Instruction
Foll_Ins -> Instruction
Expression -> Log_OR = Expression
Expression -> Log_OR x= Expression
Expression -> If_Exp
If_Exp -> Log_OR ? Expression : Expression
If_Exp -> Log_OR
Log_OR -> Log_OR || Log_AND
Log_OR -> Log_AND
Log_AND -> Log_AND && Equivalence
Log_AND -> Equivalence
Equivalence -> Equivalence _EOP N_Equivalence
Equivalence -> N_Equivalence
N_Equivalence -> N_Equivalence _COP Additional
N_Equivalence -> Additional
Additional -> Additional _AOP Multip
Additional -> Multip
Multip -> Multip _MOP Unar
Multip -> Unar
Unar -> # Unar
Unar -> _INC Unar
Unar -> Postfix
Unar -> New
Unar -> Delete
Postfix -> Postfix _INC
Postfix -> First_Exp
First_Exp -> (Expression)
First_Exp -> _ID
First_Exp -> Massive [Log_OR]
Massive -> _ID
Massive -> Massive [Log_OR]
First_Exp -> _ZCONST
First_Exp -> _RCONST
Type -> INT
Type -> FLOAT
New -> NEW Type ( First_Exp )
Delete -> DELETE _ID
New -> NEW [] Type ( First_Exp )
Delete -> DELETE []_ID
If_Instr -> IF ( Expression) Instruction
If_Instr -> IF ( Expression) Instruction ELSE Instruction
For_Instr -> FOR ( Def_Instr Expression ; Expression) Instruction
Def_Instr -> SeqSpecif_Types List_InitDef ;
SeqSpecif_Types -> Specif_Types
SeqSpecif_Types -> SeqSpecif_Types Specif_Types
Specif_Types -> Type
Specif_Types -> Specif_Enum
Specif_Types -> CONST
Specif_Enum -> ENUM { }
Specif_Enum -> ENUM _ID { }
Specif_Enum -> ENUM { Specif_Enum_List }
Specif_Enum -> ENUM _ID { Specif_Enum_List }
Specif_Enum_List -> ElemEnum_List
Specif_Enum_List -> Specif_Enum_List, ElemEnum_List
ElemEnum_List -> _ID = Expression
List_InitDef -> InitDef
List_InitDef -> List_InitDef InitDef
InitDef -> Defenitor
InitDef -> Defenitor Initor
Defenitor -> Directly_Initor
Defenitor -> PTR_struct Defenitor
Initor -> = Expression
Directly_Initor -> _ID
Directly_Initor -> Directly_Initor [ ]
Directly_Initor -> Directly_Initor [ Expression ]
PTR_struct->*
PTR_struct->*CONST
3.2) Разбиение на подграмматики
Главная подграмматика:
Имя терминала/нетерминала |
Описание |
Токен |
PRG |
Программа |
|
INS |
Инструкция |
|
EXP |
Инструкция-выражение |
|
SOE |
Составная инструкция |
|
PIN |
Последовательность инструкций |
|
P1 |
Вспомогательная последовательность инструкций |
|
i_f |
Переход в подграмматику if/for |
|
ino |
Переход в подграмматику объявлений |
|
exp |
Переход в подграмматику выражений |
|
voi |
Ключевое слово |
VOID |
mai |
Ключевое слово |
MAIN |
cin |
Ключевое слово |
CIN |
cou |
Ключевое слово |
COUT |
id |
Идентификатор |
_ID |
>> |
Знак ввода |
>> |
<< |
Знак вывода |
<< |
( |
Символ «(» |
( |
) |
Символ «)» |
) |
{ |
Символ «{» |
{ |
} |
Символ «}» |
} |
; |
Символ «;» |
; |
Грамматика простого предшествования.
Правила :
1) PRG->voimai( )INS
2) PRG->voimai( )
3) INS->EXP
4) INS->SOE}
5) INS->i_f
6) INS->ino
7) INS->cin>>id
8) INS -> cou << EXP
9) EXP -> exp ;
10) SOE -> { P1
11) SOE -> {
12) P1 -> PIN
13) PIN -> PIN INS
14) PIN -> INS
Подграмматика выражения:
Имя терминала/нетерминала |
Описание |
Токен |
EXP |
Выражение |
|
IFE |
Условное выражение |
|
ORE |
Выражение логического ИЛИ |
|
ANE |
Выражение логического И |
|
EQL |
Выражение равенства |
|
NEQ |
Выражение отношения |
|
ADD |
Аддитивное выражение |
|
MUL |
Мультипликативное выражение |
|
UNE |
Унарное выражение |
|
POS |
Постфиксное выражение |
|
FIR |
Первичное выражение |
|
MAS |
Выражение массива |
|
NEW |
New-выражение |
|
DEL |
Delete-выражение |
|
TYP |
Спецификатор простого типа |
|
id |
Идентификатор |
_ID |
zco |
Целочисленная константа |
_ZCONST |
rco |
Вещественная константа |
_RCONST |
new |
new |
NEW |
del |
delete |
DELETE |
int |
Тип int |
INT |
flt |
Тип float |
FLOAT |
inc |
Автоинкремент и автодекремент |
_INC |
# |
Унарный знак |
# |
eop |
Операция проверки на равенство |
_EOP |
cop |
Операция сравнения |
_COP |
aop |
Аддитивная операция |
_AOP |
mop |
Мультипликативная операция |
_MOP |
= |
Присваивание |
= |
x= |
Сокращённое присваивание |
x= |
? |
Символ «?» |
? |
: |
Символ «:» |
: |
|| |
Логическое ИЛИ |
_OR |
&& |
Логическое И |
_AND |
( |
Символ «(» |
) |
) |
Символ «)» |
( |
[ |
Символ «[» |
[ |
] |
Символ «]» |
] |
Грамматика SLR(1).
Правила :
1) EXP -> ORE = EXP
2) EXP -> ORE x= EXP
3) EXP -> IFE
4) IFE -> ORE ? EXP : EXP
5) IFE -> ORE
6) ORE -> ORE || ANE
7) ORE -> ANE
8) ANE -> ANE && EQL
9) ANE -> EQL
10) EQL -> EQL eop NEQ
11) EQL -> NEQ
12) NEQ -> NEQ cop ADD
13) NEQ -> ADD
14) ADD -> ADD aop MUL
15) ADD -> MUL
16) MUL -> MUL mop UNE
17) MUL -> UNE
18) UNE -> # UNE
19) UNE -> inc UNE
20) UNE -> POS
21) UNE -> NEW
22) UNE -> DEL
23) POS -> POS inc
24) POS -> FIR
25) FIR -> ( EXP )
26) FIR -> id
27) FIR -> MAS [ ORE ]
28) MAS -> id
29) MAS -> MAS [ ORE ]
30) FIR -> rco
31) FIR -> zco
32) TYP -> int
33) TYP -> flt
34) NEW -> new TYP ( FIR )
35) NEW -> new [ ] TYP ( FIR )
36) DEL -> del id
37) DEL -> del [ ] id
Подграмматика if/for:
Имя терминала/нетерминала |
Описание |
Токен |
I_F |
Начальный символ |
|
INI |
Инструкция выбора |
|
INF |
Инструкция итерации |
|
if |
Ключевое слово |
IF |
els |
Ключевое слово |
ELSE |
for |
Ключевое слово |
FOR |
( |
Символ «(» |
( |
) |
Символ «)» |
) |
; |
Символ «;» |
; |
exp |
Переход в подграмматику выражений |
|
ins |
Переход в главную подграмматику |
|
ino |
Переход в подграмматику объявлений |
|
Грамматика SLR(1).
Правила :
1) I_F -> INI
2) I_F -> INF
3) INI -> if ( exp ) ins
4) INI -> if ( exp ) ins els ins
5) INF -> for ( ino exp ; exp ) ins
Подграмматика объявлений:
Имя терминала/нетерминала |
Описание |
Токен |
INO |
Инструкция объявления |
|
PST |
Последовательность спецификаторов типов |
|
STY |
Спецификатор типа |
|
SST |
Спецификатор простого типа |
|
SEN |
Спецификатор перечисления |
|
SEE |
Список элементов перечисления |
|
DEP |
Определение элемента перечисления |
|
SIO |
Список инициализирующих объявителей |
|
IDE |
Инициализирующий объявитель |
|
DEF |
Объявитель |
|
INR |
Инициализатор |
|
NDE |
Непосредственно объявитель |
|
PTR |
Ptr-оператор |
|
EXP |
Константное выражение |
|
id |
Идентификатор |
_ID |
con |
Спецификатор const |
CONST |
int |
Тип int |
INT |
flt |
Тип float |
FLOAT |
enu |
Тип enum |
ENUM |
, |
Символ «,» |
, |
= |
Символ «=» |
= |
[ |
Символ «[» |
[ |
] |
Символ «]» |
] |
{ |
Символ «{» |
{ |
} |
Символ «}» |
} |
* |
Символ «*» |
* |
exp |
Переход в подграмматику выражений |
|
Грамматика SLR(1).
Правила :
1) INO -> PST SIO ;
2) PST -> STY
3) PST -> PST STY
4) STY -> SST
5) STY -> SEN
6) STY -> con
7) SST -> int
8) SST -> flt
9) SEN -> enu { }
10) SEN -> enu id { }
11) SEN -> enu { SEE }
12) SEN -> enu id { SEE }
13) SEE -> DEP
14) SEE -> SEE , DEP
15) DEP -> id = EXP
16) SIO -> IDE
17) SIO -> SIO IDE
18) IDE -> DEF
19) IDE -> DEF INR
20) DEF -> NDE
21) DEF -> PTR DEF
22) INR -> = EXP
23) NDE -> id
24) NDE -> NDE [ ]
25) NDE -> NDE [ EXP ]
26) PTR -> *
27) PTR -> * con
28) EXP -> exp
Описание ПОЛИЗ | ||
Синтаксис |
Семантика | |
Операнды |
Оператор | |
m |
DEFL |
Определение метки m |
m |
BRL |
Безусловный переход на метку m |
a, m |
BF |
Переход на метку m, если a = “Ложь” |
m |
RET |
Возврат к метке m |
a |
COUT |
Вывод значения “a” на экран |
a |
CIN |
Запрос на ввод с клавиатуры значения переменнойa |
a, i1…in, k |
SUBS |
Вычисление адреса элемента массива a; ik - индексы; k = n+1 - число операндов |
a, b |
:= |
Оператор присваивания a:=b |
a, b |
+ |
Аддитивная операция a+b |
a, b |
- |
Аддитивная операция a-b |
a, b |
* |
Мультипликативная операция a*b |
a, b |
/ |
Мультипликативная операция a/b |
a, b |
AND |
Операция логического И: a&&b |
a, b |
OR |
Операция логического ИЛИ: a||b |
a |
NOT |
Операция логического отрицания: !a |
a |
RNAME |
Операция разыменования (обращения к объекту): *a |
a |
-u |
Операция унарный минус. |
a |
INC |
Инкремент a+1 |
a |
DEC |
Декремент a-1 |
a, b |
< |
a<bдля целых и вещественных значений |
a, b |
> |
a> bдля целых и вещественных значений |
a, b |
<= |
a<=bдля целых и вещественных значений |
a, b |
>= |
a>=bдля целых и вещественных значений |
a, b |
== |
a==bдля целых, вещественных значений и указателей |
a, b |
!= |
a!=bдля целых, вещественных значений и указателей |
a, b |
SET |
Назначает тип a для переменной b |
a, b |
CHTP |
Преобразует тип выражения a к типу b |
a |
NEW |
Создает новый объект уже известного типа и отводит для имени «а» место в соответствующей таблице |
a |
DEL |
Удаляет объект из соответствующей таблицы. |
3.3) Описание промежуточного языка
3.4) Неформальное описание перевода
1. Перевод условного оператора IF (Полная форма)
Входная конструкция:
IF(<Выражение>) THEN<Инструкция1>ELSE<Инструкция2>
ПОЛИЗ:
<Выражение>
m1 BF <Инструкция1>
m2 BRL m1 DEFL <Инструкция2>
m2 DEFL
2. Перевод условного оператора IF (Сокращённая форма)
Входная конструкция:
IF(<Выражение>)THEN<Инструкция>
ПОЛИЗ:
<Выражение> m1 BF <Инструкция>
m1 DEFL
3. Перевод оператора цикла FOR
Входная конструкция:
FOR ( <Инструкция объявления>; <Выражение1>;<Выражение2>)<Инструкция>
ПОЛИЗ:
<Инструкция объявления>
m1 DEFL<Выражение1>m4 BF
m3 BRLm2 DEFL <Выражение2>m1 RET
m3 DEFL<Инструкция>m2 RET
m4 DEFL
4. Перевод оператора вывода COUT
Входная конструкция:
COUT <<<Выражение> ;
ПОЛИЗ:
<Выражение> COUT
5. Перевод оператора ввода CIN
Входная конструкция:
CIN >>_ID ;
ПОЛИЗ:
_ID CIN
3.5) Построение атрибутных транслирующих грамматик
Так как в данной работе грамматики принадлежат классам грамматик SLR(1) и простого предшествования, то будет использоваться восходящий метод синтаксического анализа, поэтому на атрибутную транслирующую грамматику накладывается ограничение – она должна быть постфиксной. Построим S-атрибутную транслирующую грамматику:
Аргументами правила вычисления значения унаследованного атрибута символа из правой части правила вывода могут быть только унаследованные атрибуты символа из левой части и произвольные атрибуты символов из правой части, расположенные левее рассматриваемого символа.
Аргументами правила вычисления значения синтезированного атрибута символа из левой части правила вывода являются унаследованные атрибуты этого символа или произвольные атрибуты символов из правой части.
Аргументами правила вычисления значения синтезированного атрибута операционного символа могут быть только унаследованные атрибуты этого символа.
Все атрибуты нетерминалов синтезированные.
При достижении операционного символа вызывается соответствующая функция, которая участвует в формировании выходной цепочки, записанной польской инверсной записью в соответствии с описанием выходного языка, приведенным выше, а также, если это необходимо, вызывает функции для вычисления атрибутов и проверки (возможно преобразования типов).
Атрибуты лишь указывают на реальные значения переменных, типов и адресов, хранимые в таблицах. Значения атрибутов - номера соответствующих строк в таблице. Функции, работающие с атрибутами организованы так, что при необходимости происходит выборка реального значения, а не его адреса в таблице.
Главная подграмматика (простого предшествования):
Операционный символ |
Атрибуты |
Комментарий |
{CIN}p |
p - введенное пользователем значение |
Вывод: a CIN a - идентификатор |
{COUT}p |
p - выводимое на экран значение |
Вывод на экран зависит от типа, так, например, вывод массива отличается от вывода целого числа, а вывод указателя приводит к ошибке. Вывод: a COUT a - выводимое выражение |
1) PRG -> void main ( ) INS
2) PRG -> void main ( )
3) INS -> EXP
4) INS -> SOE }
5) INS -> i_f
6) INS -> ino
7) INSk,_t -> cin >> idq,t {CIN}p,t1
k<-p
q<-k
_t<-t1
t<_t
8) INS -> cou << EXPq,t {COUT}p,_t
p<-q
_t<-t
9) EXP -> exp ;
10) SOE -> { P1
11) SOE -> {
12) P1 -> PIN
13) PIN -> PIN INS
14) PIN->INS
Подграмматика выражения(SLR(1)):
Здесь и далее:
Все функции, имеющие возможность преобразовывать тип своих атрибутов могут выводить также и цепочки вида: a,typeCHTP. Эта запись выводится строго до выполнения основной операции.
Пример:
Пусть a=6 - тип int
10,7 a a float_T CHTP +
Таким образом, сначала а будет приведена к типу float, а затем произойдет сложение.
float_T - указывает на типfloatв таблице.
Операционный символ |
Атрибуты |
Комментарий |
{:=}a, b, x, y, vres, tres |
a - значение первого операнда b - значение второго операнда x - тип первого операнда y - тип второго операнда vres - результирующее значение tres - тип результирующего значения |
Для вычисления vres и tres вызывается функция COUNT. Входные параметры: a,b,x,y. Выходные параметры: vres, tres. На основе входных данных функция проверяет совместимость типов, при необходимости преобразует типы(если возможно), и формирует результат присваивания. Вывод: := Здесь и далее: В случае несовместимости типов выдается ошибка и трансляция останавливается. |
{x=COUNT}t1, a’, b’, x’, y’, vres’, tres’ |
t1 - № типа операции в соответствующей таблице a’ - значение первого операнда b’ - значение второго операнда x’ - тип первого операнда y’ - тип второго операнда vres’ - результирующее значение tres’ - тип результирующего значения |
Для вычисления vres и tres вызывается функция COUNTx. Входные параметры: t1,a’,b’,x’,y’. Выходные параметры: vres, tres. На основе входных данных функция проверяет совместимость типов, при необходимости преобразует типы (если возможно), и формирует результат операции. Вывод: одно из - +,-,*,/
|
{BRL}m |
m - метка, на которую будет произведен безусловный переход. |
Если данная метка отсутствует в таблице меток, то вызывается функция NewLabel,которая создает метку и заносит ее в таблицу, возвращая адрес новой записи, который впоследствии получит атрибут. Вывод: m BRL |
{BF}m,val |
m - метка, на которую будет произведен переход, в случае, если val = 0. |
Если данная метка отсутствует в таблице меток, то вызывается функция NewLabel,которая создает метку и заносит ее в таблицу, возвращая адрес новой записи, который впоследствии получит атрибутm. Вывод: m BF Выражение, значение которого будет использовано для BF к этому моменту уже записано. |
{DEFL}m |
m - метка, которая объявляется. |
Если данная метка отсутствует в таблице меток, то вызывается функция NewLabel,которая создает метку и заносит ее в таблицу, возвращая адрес новой записи, который впоследствии получит атрибутm. Функция IF_V вычисляет значение условного оператора присваивания. Входные параметры: val,v1,v2. v1 - значение первого выражения (ветка true) - если val!=0 v2 - значение второго выражения (ветка false) - если val=0 Выходные параметры:значение. Функция IF_T вычисляет тип значения условного оператора присваивания. Входные параметры: val,t1,t2. Выходные параметры: тип. Вывод: m DEFL |
{OR}a, b, x, y, val, type |
a - значение первого операнда b - значение второго операнда x - тип первого операнда y - тип второго операнда val - результирующее значение type - тип результирующего значения |
На основе входных данных функция проверяет совместимость типов, при необходимости преобразует типы (если возможно), и формирует результат операции логического ИЛИ. Для вычисления val вызывается функция OR_V. Входные параметры: a,b. Выходные параметры: val. Для вычисления type вызывается функция OR_T. Входные параметры: x,y. Выходные параметры: type. Вывод: OR |
{AND} a, b, x, y, val, type |
a - значение первого операнда b - значение второго операнда x - тип первого операнда y - тип второго операнда val - результирующее значение type - тип результирующего значения |
На основе входных данных функция проверяет совместимость типов, при необходимости преобразует типы (если возможно), и формирует результат операции логического И. Для вычисления val вызывается функция AND_V. Входные параметры: a,b. Выходные параметры: val. Для вычисления type вызывается функция AND_T. Входные параметры: x,y. Выходные параметры: type. Вывод: AND |
{EOP} a, b, _t1, x, y, val, type |
a- значение первого операнда b- значение второго операнда _t1 - № типа операции в соответствующей таблице x - тип первого операнда y- тип второго операнда vat- результирующее значение type- тип результирующего значения |
На основе входных данных функция проверяет совместимость типов, при необходимости преобразует типы (если возможно), и формирует результат операции равенства. Для вычисления val вызывается функция EOP_V. Входные параметры: a,b,_t1. Выходные параметры: val. Для вычисления type вызывается функция EOP_T. Входные параметры: x,y,_t1. Выходные параметры: type. Вывод: одно из ==, != |
{COP} a, b, _t1, x, y, val, type |
a- значение первого операнда b- значение второго операнда _t1 - № типа операции в соответствующей таблице x - тип первого операнда y- тип второго операнда vat- результирующее значение type- тип результирующего значения |
На основе входных данных функция проверяет совместимость типов, при необходимости преобразует типы (если возможно), и формирует результат операции сравнения. Для вычисления val вызывается функция COP _V. Входные параметры: a,b,_t1. Выходные параметры: val. Для вычисления type вызывается функция COP _T. Входные параметры: x,y,_t1. Выходные параметры: type. Вывод: одно из <, >, <=, >= |
{AOP} a, b, _t1, x, y, val, type |
a- значение первого операнда b- значение второго операнда _t1 - № типа операции в соответствующей таблице x - тип первого операнда y- тип второго операнда vat- результирующее значение type- тип результирующего значения |
На основе входных данных функция проверяет совместимость типов, при необходимости преобразует типы (если возможно), и формирует результат аддитивной операции. Для вычисления val вызывается функция AOP _V. Входные параметры: a,b,_t1. Выходные параметры: val. Для вычисления type вызывается функция AOP _T. Входные параметры: x,y,_t1. Выходные параметры: type. Вывод: одно из +,- |
{MOP} a, b, _t1, x, y, val, type |
a- значение первого операнда b- значение второго операнда _t1 - № типа операции в соответствующей таблице x - тип первого операнда y- тип второго операнда vat- результирующее значение type- тип результирующего значения |
На основе входных данных функция проверяет совместимость типов, при необходимости преобразует типы (если возможно), и формирует результат мультипликативной операции. Для вычисления val вызывается функция MOP _V. Входные параметры: a,b,_t1. Выходные параметры: val. Для вычисления type вызывается функция MOP _T. Входные параметры: x,y,_t1. Выходные параметры: type. Вывод: одно из *,/ |
{#} a, _t1, x, val, type |
а - операнд _t1 - № типа операции в соответствующей таблице x - тип операда val- результирующее значение type- тип результирующего значения |
На основе входных данных функция проверяет совместимость типов, при необходимости преобразует типы (если возможно), и формирует результат унарной префиксной операции. Для вычисления val вызывается функция UNE _V. Входные параметры: a,_t1. Выходные параметры: val. Для вычисления type вызывается функция UNE _T. Входные параметры: x,_t1. Выходные параметры: type. Вывод: одно из -u,+, NOT, RNAME |
{INC} a, _t1, x, val, type |
а - операнд _t1 - № типа операции в соответствующей таблице x - тип операда val- результирующее значение type- тип результирующего значения |
На основе входных данных функция проверяет совместимость типов, при необходимости преобразует типы (если возможно), и формирует результат унарной операции инкремента/декремента. Вызываются те же функции UNE _V и UNE _T, что и для {#}, меняются только значения _t1. Для префиксной и постфиксной ++ и -- они различны, а отсюда различны и val. Вывод: одно из INC, DEC |
{ID} v1, t1, vres, tres |
v1 - значени t1 - тип vres - выходное знычение tres - выходной тип |
Вызывается функция IDENT,чтобы найти идентификатор в таблице. Вывод: a - переменная |
{MAS}_v1,_t1,_x,_y, vres, tres |
_v1 - накопленный список индексов _t1 - тип подмассива _x- значение текущего индекса _y- тип текущего индекса vres- выходное знычение (список индексов для выборки значения) tres- выходной тип |
На основе входных данных функция проверяет совместимость типов, при необходимости преобразует типы (если возможно), и формирует список индексов для выборки значения. Функция MAS добавляет индекс в список, если его тип структурно совпадает с типомint. Вывод: a, i1…in, k SUBS массива a; ik - индексы;k = n+1 - число операндов. |
{RCO} vres, tres |
v1 - значени t1 - тип vres - выходное знычение tres - выходной тип |
Вызывается функция RCONST,чтобы найти вещественную константу в таблице и передать ее значение. Вывод: a - вещественная константа |
{ZCO} vres, tres |
v1 - значени t1 - тип vres - выходное знычение tres - выходной тип |
Вызывается функция ZCONST,чтобы найти целочисленную константу в таблице и передать ее значение. Вывод: a - целочисленная константа |
{NEW} x, y, z,_z, vres, tres |
x - значение выражения инициализации y - тип выражения инициализации z - тип новой переменной _z - создание массива vres - выходное знычение tres - выходной тип |
Функция NEW создает новый идентификатор, закрепляя за ним адрес в таблице, и производит неявное преобразование типов при инициализации, если необходимо и возможно. Вывод: tres a SET a NEW |
{DELETE}a, _z |
а - имя удаляемого из таблицы идентификатора _z - удаление массива |
Проверка типа удаляемого объекта. Уничтожение соответствующей записи в таблице. Вывод: a DEL |
Правила :
1) EXPv’,t’ -> ORE_v,_t = EXPv,t {:=}a, b, x, y, vres, tres
a<-_v
b<-v
x<-_t
y<-t
vres<- COUNT(a,b,c,d)
tres<- COUNT(a,b,c,d)
v’<- vres
t’<- tres
2) EXPv’,t’ -> ORE_v,_t x=t EXPv,t {x=COUNT}t1, a’, b’, x’, y’, vres’, tres’ {:=} a, b, x, y, vres, tres
a, a’<-_v
b’<-v
x, x’<-_t
y’<-t
vres’<- COUNTx(t1, a’,b’,c’,d’)
tres’<- COUNTx(t1, a’,b’,c’,d’)
b<-vres’
y<-tres’
vres<- COUNT(a,b,c,d)
tres<- COUNT(a,b,c,d)
v’<- vres
t’<- tres
3) EXP_v,_t -> IFEv,t
_v<-v
_t<-t
4) IFEv,t -> IFE_2q,val, v1,t1 EXPv2,t2 {DEFL}m2
m2<-q
v<- IF_V(val,v1,v2)
t<- IF_T(val,t1,t2)
4’) IFE_1m,__val -> ORE_val ? {BF}m1,val
m1<- NewLabel
m<-m1
__val, val<-_val
4’’) IFE_2m, val, _v1,_t1 -> IFE_1p,q EXPv1,t1 : {BRL}m2 {DEFL}m1
m2<- NewLabel
m<-m2
m1<-p
val<-q
_v1<-v1
_t1<-t1
5) IFE_v,_t -> OREv,t
_v<-v
_t<-t
6) ORE_v,_t -> OREv1,t1 || ANEv2,t2 {OR}a, b, x, y, val, type
a<-v1
b<-v2
x<-t1
y<-t2
val<- OR_V(a,b)
type<- OR_T(x,y)
_v<-val
_t<-type
7) ORE_v,_t -> ANEv,t
_v<-v
_t<-t
8) ANE_v,_t -> ANE v1,t1 && EQL v2,t2 {AND} a, b, x, y, val, type
a<-v1
b<-v2
x<-t1
y<-t2
val<- AND_V(a,b)
type<- AND_T(x,y)
_v<-val
_t<-type
9) ANE_v,_t -> EQLv,t
_v<-v
_t<-t
10) EQL_v,_t -> EQL v1,t1 eopt NEQ v2,t2 {EOP} a, b, _t1, x, y, val, type
a<-v1
b<-v2
_t1<-t
x<-t1
y<-t2
val<- EOP_V(a,b,_t1)
type <- EOP_T(x,y,_t1)
_v<-val
_t<-type
11) EQL_v,_t -> NEQv,t
_v<-v
_t<-t
12) NEQ_v,_t -> NEQ v1,t1 copt ADD v2,t2 {COP} a, b, _t1, x, y, val, type
a<-v1
b<-v2
_t1<-t
x<-t1
y<-t2
val<- COP_V(a,b,_t1)
type <- COP_T(x,y,_t1)
_v<-val
_t<-type
13) NEQ_v,_t -> ADDv,t
_v<-v
_t<-t
14) ADD_v,_t -> ADD v1,t1 aopt MUL v2,t2 {AOP} a, b, _t1, x, y, val, type
a<-v1
b<-v2
_t1<-t
x<-t1
y<-t2
val<- AOP_V(a,b,_t1)
type <- AOP_T(x,y,_t1)
_v<-val
_t<-type
15) ADD_v,_t -> MULv,t
_v<-v
_t<-t
16) MUL_v,_t -> MUL v1,t1 mopt UNE v2,t2 {MOP} a, b, _t1, x, y, val, type
a<-v1
b<-v2
_t1<-t
x<-t1
y<-t2
val<- MOP_V(a,b,_t1)
type <- MOP_T(x,y,_t1)
_v<-val
_t<-type
17) MUL_v,_t -> UNEv,t
_v<-v
_t<-t
18) UNE_v,_t -> #t UNEv,t {#} a, _t1, x, val, type
a<-v
_t1<-t
x<-t1
val<- UNE_V(a,_t1)
type <- UNE_T(x,_t1)
_v<-val
_t<-type
19) UNE_v,_t -> inct UNEv,t {INC} a, _t1, x, val, type
a<-v
_t1<-t
x<-t1
val<- UNE_V(a,_t1)
type <- UNE_T(x,_t1)
_v<-val
_t<-type
20) UNE_v,_t -> POS v,t
_v<-v
_t<-t
21) UNE_v,_t -> NEW v,t
_v<-v
_t<-t
22) UNE_v,_t -> DEL v,t
_v<-v
_t<-t
23) POS_v,_t -> POS v,t inct {INC} a, _t1, x, val, type
a<-v
_t1<-t
x<-t1
val<- UNE_V(a,_t1)
type <- UNE_T(x,_t1)
_v<-val
_t<-type
24) POS_v,_t -> FIR v,t
_v<-v
_t<-t
25) FIR_v,_t -> ( EXP v,t )
_v<-v
_t<-t
26) FIR_v,_t -> id v,t {ID} v1, t1, vres, tres
v1<-v
t1<-t
vres<- IDENT(v1,t1)
tres<- IDENT(v1,t1)
_v<-vres
_t<-tres
27) FIR_v,_t -> MAS v1,t1 [ ORE v,t ] {MAS}_v1,_t1,_x,_y, vres, tres
_v1<-v1
_t1<t1
_x<-v
_y<-t
vres<- MAS(_v1,_t1,_x,_y)
tres<- MAS(_v1,_t1,_x,_y)
_v<-vres
_t<-tres
28) MAS_v,_t -> id v,t
_v<-v
_t<-t
29) MAS_v,_t -> MASv1,t1 [ ORE v,t ] {MAS}_v1,_t1,_x,_y, vres, tres
_v1<-v1
_t1<t1
_x<-v
_y<-t
vres<- MAS(_v1,_t1,_x,_y)
tres<- MAS(_v1,_t1,_x,_y)
_v<-vres
_t<-tres
30) FIR_v,_t -> rco {RCO} vres, tres
vres<- RCONST
tres<- RCONST
_v<-vres
_t<-tres
31) FIR_v,_t -> zco {ZCO} vres, tres
vres<- ZCONST
tres<- ZCONST
_v<-vres
_t<-tres
32) TYPt -> intt1
t<-t1
33) TYPt -> floatt1
t<-t1
34) NEW_v,_t -> new TYPt1 ( FIRv,t ) {NEW} x, y, z, _z, vres, tres
x<-v
y<-t
z<-t1
_z<-NIL
vres<- NEW (x,y,z, _z)
tres<- NEW (x,y,z, _z)
_v<-vres
_t<-tres
35) NEW_v,_t -> new [ ] t2 TYP t1 ( FIRv,t ) {NEW} x, y, z, _z, vres, tres
x<-v
y<-t
z<-t1
_z<t2
vres<- NEW (x,y,z, _z)
tres<- NEW (x,y,z, _z)
_v<-vres
_t<-tres
36) DEL_v,_t -> delete id v,t {DELETE}a, _z
_v<-1
_t<-int
a<-v
_z<-NIL
37) DEL_v,_t -> delete [ ] t2 id v,t {DELETE}a, _z
_v<-1
_t<-int
a<-v
_z<-t2
Подграмматика if/for (SLR(1)):
Операционный символ |
Атрибуты |
Комментарий |
{BRL}m |
m - метка, на которую будет произведен безусловный переход. |
Здесь и далее: Если данная метка отсутствует в таблице меток, то вызывается функция NewLabel,которая создает метку и заносит ее в таблицу. Вывод: m BRL |
{BF}m,val |
m - метка, на которую будет произведен переход, в случае, если val = 0. |
Вывод: m BF |
{DEFL}m |
m - метка, которая объявляется. |
Вывод: m DEFL |
(RET}m |
Возврат к метке m |
Вывод: m RET |
{DEL}a |
а - имя удаляемого из таблицы идентификатора
|
Уничтожение соответствующей записи в таблице. Вывод: a DEL |
1) I_F -> INI
2) I_F -> INF
3) INI -> INI_1p ins {DEFL}m
mp
3’) INI_1p-> if ( expval ) {BF}m, v
m NewLabel
p m
vval
4) INI -> INI_2 q2 ins {DEFL}m2
m2<-q2
4’) INI_2q2 -> INI_1p ins else {BRL}m2 {DEFL}m1
m2 NewLabel
q2 m2
m1p
INF -> INF_1_m2, _m4, n ins {RET}m2 {DEFL}m4 {DEL} _n
m2<-_m2
m4<-_m4
n<-_n
5’) INF_1__m2, __m4, n -> INF_2_m1, _m2, _m3, _m4, _n; exp ) {RET}m1 {DEFL}m3
m1<-_m1
m3<-_m3
n<-_n
5’’)INF_2_m1, _m2, _m3, _m4, n -> INF_3p, _n expval {BF}m4, v {BRL}m3 {DEFL}m2
_m1<-p
v<-val
m4<- NewLabel
m3<- NewLabel
m2<- NewLabel
_m2<-m2
_m3<-m3
_m4<-m4
n<-_n
5’’’)INF_3p, n -> for ( inoname {DEFL}m1
m1<- NewLabel
p<-m1
n<-name
Подграмматика объявлений (SLR(1)):
Операционный символ |
Атрибуты |
Комментарий |
{ADDVAR}_t, _enum, _list, vres, tres |
_t - список спецификаторов типа _enum - индикатор наличия описания enum в _t _list - список пар (значение, тип) vres - результат - список значений tres - результирующий тип |
Функция ADDVAR в случае правильного синтаксиса создает новые записи (запись) в таблице идентификаторов и, если это возможно, инициализирует их (ее). Функции, описанные ниже необходимы для формирования и передачи необходимых значений атрибутов. Они ничего не выводят на выходную ленту, поскольку данные, которыми они оперируют недостаточны для однозначного определения синтаксиса и семантики конструкции. Вывод: tres a SET a NEW Здесь и далее: В случае несовместимости типов или некорректного синтаксиса выдается ошибка и трансляция останавливается. |
{PSTEND} list_in, list_res |
list_in - новый полный список спецификаторов типа tres - результирующий тип |
Функция PSTEND вычисляет тип объявляемого значения по мере поступления спецификаторов типа. |
{ADDENUM}_list, _name, tres |
_list - список инициализаторов enum _name - имя перечисления tres - тип элементов перечисления |
Функция ADDENUM вычисляет тип элементов перечисления в зависимости от вида его объявления и инициализирует их. |
{ADDDEF}v, _t |
v - значение инициализатора _t - тип инициализатора |
Функция ADDDEF проверяет корректность инициализации элемента перечисления. |
{IDE}t1,t2, tres |
t1 - тип объявителя t2 - тип инициализирующего значения tres - результирующий тип |
Функция IDE производит преобразование типов, если появляется такая необходимость. |
{DEF}_t1, _t2, tres |
_t1 - наличие указателя _t2 - объекта tres- результирующий тип |
Функция DEF производит преобразование типов для случаев с объявлением указателя, если появляется такая необходимость. |
{NDE}_val, _type, _t, tres
|
_val - значение индекса _type - тип индекса _t - тип подмассива tres- результирующий тип |
Функция NDE производит преобразование типов для случаев с объявлением массива, если появляется такая необходимость. Проверяет корректность семантики объявления массива или простой переменной. |
{PTR}_t, _c, type |
_t - степень указателя _c - наличие спецификатора const type - результирующий тип |
Функция PTR производит объявление спецификатора указателя, определяя его вид. |
1) INOval_list, type -> PST t, enum SIOlist ; {ADDVAR}_t, _enum, _list, vres, tres
_t<-t
_enum<-enum
_list<-list
vres<- ADDVAR(_t, _enum, _list)
tres<- ADDVAR(_t, _enum, _list)
val_list<-vres
type<-tres
2) PSTt, enum -> STY_t {PSTEND} list_in, tres
list_in<-_t
tres<- PSTEND(list_in)
enum<- PSTEND(list_in)
t<-tres
3) PSTt, enum -> PST_list STYt {PSTEND} list_in, tres
list_in <-CONC(_list,t)
tres<- PSTEND(list_in)
t<-tres
enum<-NIL
4) STYt -> SST_t
t<-_t
5) STYt -> SEN_t
t<-_t
6) STYt -> constc
t<-c
7) SST_t -> intt
_t<-t
8) SST_t -> floatt
_t<-t
9) SENt -> enum { } {ADDENUM}_list, _name, tres
_list<-NIL
_name<- int
tres<- ADDENUM(_name)
t<-tres
10) SENt -> enum idname { } {ADDENUM}_list, _name, tres
_list<-NIL
_name<-name
tres<- ADDENUM(_name)
t<-tres
11) SENt -> enum { SEElist } {ADDENUM}_list, _name, tres
_list<-list
_name<-int
tres<- ADDENUM(_name)
t<-tres
12) SENt -> enum idname { SEElist } {ADDENUM}_list, _name, tres
_list<-list
_name<-name
tres<- ADDENUM(_name)
t<-tres
13) SEE list -> DEPp
list<-p
14) SEE list -> SEE_list , DEPp
list<-CONC(_list,p)
15) DEPp -> id = EXPval, t {ADDDEF}v, _t
v, p<-val
_t<-t
16) SIOlist -> IDEt,p
list<- PAIR(t,p)
17) SIOlist -> SIO_list IDEt,p
list<-CONC(_list,PAIR(t,p))
18) IDEt,p -> DEF_t {IDE} t1,t2, tres
t1<-_t
t2<-NIL
tres<-IDE(t1,t2)
t<-tres
p<-NIL
19) IDE t,p -> DEF_t INRv,t {IDE}t1,t2, tres
t1<-_t
t2<-t
tres<-IDE(t1,t2)
t<-tres
p<-v
20) DEFt -> NDE t1{DEF}_t1, _t2, tres
_t1<-NIL
_t2<-t1
tres<-DEF(_t1, _t2)
t<-tres
21) DEFt -> PTR type DEFt1 {DEF}_t1, _t2, tres
_t1<-type
_t2<-t1
tres<-DEF(_t1, _t2)
t<-tres
22) INRv,t -> = EXP val,type
v<-val
t<-type
23) NDEt1 -> id {NDE}_val, _type, _v, _t, tres
_val<-NIL
_type<-NIL
_v<-NIL
_t<-NIL
tres<- NDE(_val, _type, _v, _t)
t1<-tres
24) NDEt1 -> NDEt [ ] {NDE}_val, _type, _t, tres
_val<-NIL
_type<-NIL
_t<-t
tres<- NDE(_val, _type, _v, _t)
t1<-tres
25) NDEt1 -> NDEt [ EXP val,type ] {NDE}_val, _type, _t, tres
_val<-val
_type<-type
_t<-t
tres<- NDE(_val, _type, _v, _t)
t1<-tres
26) PTR_ type -> * t {PTR}_t, _c, type
_t<-t
_c<-NIL
type<-PTRTYPE(_t,_c)
_ type<- type
27) PTR _type -> *t constc {PTR}_t, _c, type
_t<-t
_c<-c
type<-PTRTYPE(_t,_c)
_ type<- type
28) EXPval,type -> expv,t
val<-v
type<-t
4. ДМП-преобразователь
Наша грамматика состоит из 4 подграмматик, а значит, и ДМП-преобразователь будет состоять из 4 взаимодействующих ДМП-преобразователей, для каждого из которых были построены таблицы функций действий и переходов, представленные ниже.
Сначала рассмотрим алгоритм работы одного преобразователя, а затем принципы их взаимодействия.
ДМП-процессор состоит из магазина, входной ленты, выходной ленты и управляющего устройства М.
Магазинный алфавит Vp представляет собой множество символов , соответствующих грамматическим вхождениям. Перед началом работы алгоритма магазин пуст : содержит маркер дна ( ┴ ).
Восходящий анализатор можно расширить действиями по выполнению перевода, если перевод определяется постфиксной транслирующей грамматикой, как в нашем случае. Модификация анализатора заключается в том, что операция свертки расширяется действиями, описываемыми операционными символами соответствующего правила грамматики. Это можно сделать потому, что при обработке входной цепочки момент времени выполнения свертки для каждого правила совпадает с моментом выполнения действий по переводу для этого правила.
В S-атрибутном ДМП-процессоре каждый магазинный символ имеет конечное множество полей для представления атрибутов. Примем, что магазинный символ с n атрибутами представляется в магазине n + 1 полями, верхнее из которых содержит имя символа, а остальные – значения атрибутов.
В ходе разбиения исходной грамматики на подграмматики нами использовались подграмматики двух классов: простого предшествования и SLR(1).
Рассмотрим устройство ДМП-преобразователя для SLR(1) грамматик:
Управляющее устройство анализатора представляет собой таблицу, строки которой отмечены символами магазинного алфавита. Каждая строка таблицы задает две функции: функцию действия (F) и функцию переходов (G). Функция действия F, аргументом которой служит некоторый символ входной цепочки, принимает значения из множества {"ДОПУСК", "ПЕРЕНОС", "(СВЕРТКА,i)", "ОШИБКА" }. Аргументом функции переходов G является символ из полного словаря грамматики, а значениями - символ "ОШИБКА" или символ магазинного алфавита.
Тогда алгоритм работы ДМП-преобразователя имеет вид:
Вход алгоритма :
1) Анализируемая входная цепочка Z = t1 t2 ... tj ... tn , где j - номер текущего символа входной цепочки, находящегося под читающей головкой;
2) Управляющая таблица для SLR(1)-грамматики.
Выход алгоритма :
Выходная цепочка, представленная на промежуточном языке
Описание алгоритма :
1. j:=0.
2. j:=j+1. Если j > n , то выдать сообщение об ошибке и перейти к
п.5.
3. Определить очередной символ входной цепочки :
u = tj , тогда u = tj+1 ... tn - остаток входной цепочки.
4. Применить функцию действия F из строки управляющей таблицы, отмеченной верхним символом магазина T, к символу u.
а) F(u) = ПЕРЕНОС. Определить функцию переходов G(tj) из строки управляющей таблицы, отмеченной символом T из верхушки магазина. Если G(tj) = T1 и T1 принадлежит множеству { Vp U {┴} }, то записать T1 в магазин и перейти к п.2. Если G(tj) = ОШИБКА, то выдать сигнал об ошибке и перейти к п.5.
Атрибуты переносимого входного символа помещаются в соответствующие поля вталкиваемого при переносы магазинного символа. При вталкивании символа в магазин атрибуты заполняются и не изменяются до выталкивания этого символа из магазина.
б) F(u) = (СВЕРТКА,i) и A -> a - правило вывода с номером i грамматики. Удалить из верхней части магазина столько символов, сколько содержится в правой части i-го правила, в результате чего в верхушке магазина окажется символ T1, принадлежащий множеству { Vp U {┴} }. Определить символ T2 = G(A) , записать его в магазин и перейти к п.3.
При выполнении свертки поля магазинных символов, представляющих собой правую часть некоторого правила, содержат значения атрибутов соответствующих символов грамматика. Эти значения используются для вычисления значений атрибутов всех операционных символов, связанных с правилом вывода транслирующей грамматики, и значений всех атрибутов нетерминала из левой части правила. Значения атрибутов операционных символов используются для выдачи результатов в выходную ленту или выполнения других действий, определяемых этими символами. Атрибуты нетерминала из левой части правила вывода записываются в соответствующие поля магазинного символа, который соответствует этому нетерминалу и вталкивается в магазин во время свертки.
в) F(u) = ОШИБКА. Выдать сообщение об ошибке и перейти к п.5.
г) F(u) = ДОПУСК. .Успешное завершение работы процессора, получена цепочка на промежуточном языке
5. Завершение работы.
Рассмотрим устройство ДМП-преобразователя для грамматик простого предшествования:
Пусть G = < T, N, S, R > – КС-грамматика, правила которой занумерованы натуральными числами 1, 2, ... , р. Алгоритмом разбора типа “перенос- свертка” для грамматики G называется пара функций A = (f, g), где f - функция переноса, a g - функция свертки.
Функции f и g зависят от цепочки, находящейся в верхушке магазина, и необработанной части входной цепочки. Эти функции определяются следующим образом:
f отображает множество V*( T {})* в множество {ПЕРЕНОС, СВЕРТКА, ДОПУСК, ОШИБКА} ;
g отображает множество V*( T {})* в множество{1, 2, ... , р, ОШИБКА} при условии, что если и g(, w)=i, то правая часть i-го правила А является суффиксом цепочки .
Для КС-грамматики G = < T, N, S, R > отношения простого предшествования <• и определяются на (V { }) (V { }), где – маркер дна магазина, следующим образом:
X Y, если в R есть правило A XY.
б) X <• Y, если в R есть правило A XB и B + Y;
в) <• Y для всех Y, для которых S + Y;
Отношение • определяется на (V { }) (T { }), так как непосредственно справа от правовыводимой цепочки может стоять только терминал.
a) X • a, если в R есть правило A BY и B + X и Y a;
б) X • для всех, для которых S + X.
В правовыводимой цепочке w, где = X1X2 … Xn, = Y1Y2 …Ym , w=ax и – основа, между символами цепочки выполняются следующие отношения (фигурные скобки { } означают, что выполняется одно из отношений, записанных в них):
X1 { <• } X2 { <• } … { <• } Xn <• Y1 Y2 …Ym • ax
Тогда алгоритм работы ДМП-преобразователя имеет вид:
Вход:
Грамматика простого предшествования G = < T, N, S, R >, в которой правила вывода занумерованы натуральными числами 1, 2, ... , р.
Выход:
Алгоритм A = (f, g) типа “перенос – свертка” для грамматики G.
Функция переноса f зависит только от верхнего символа магазина и самого левого необработанного символа входной цепочки. Поэтому f определяется на множестве (V { }) (T { }) ( за исключением правила с), которое имеет приоритет над правилами а) и b), когда Х = S и a = ):
f(X, а) = ПЕРЕНОС, если Х <• а или Х а ;
f(X, а) = СВЕРТКА, если Х •> а ;
f(S, ) = ДОПУСК;
f(X, а) = ОШИБКА в остальных случаях.
2) Функция свертки g зависит от верхней части магазинной цепочки, включающей основу и еще один символ ниже нее. Необработанная часть входной цепочки на g не влияет, поэтому g задается только на (V { })*:
g(Xk+1XkXk-1 … X1, ) = i, если Xk+1 <• Xk, Xj+1 Xj для k>j1 и
A ХkХk-1 ... Х1 – правило вывода с номером i. Заметим, что функция g определяется только тогда, когда Х1 •> a – текущий входной символ;
b) g(, ) = ОШИБКА в остальных случаях.
Организация взаимодействия n ДМП-процессоров:
Вызывающий ДМП-процессор.
В основе этого процессора лежит грамматика, которая среди своих терминальных символов содержит специальный терминальный символ (в тексте выделен жирным шрифтом), по которому происходит вызов другого ДМП-процессора. Когда этот символ находится наверху магазина, данный процессор должен выполнить переход к вызываемому процессору.
Вызываемый ДМП-процессор.
Каждый процессор должен работать со своим магазином. В программной реализации ДПМ-процессора это может быть новый объект соответствующего класса или, если используется один физический магазин, то в него вталкивается символ «дно магазина» и анализ начинается так, как если бы магазин был пуст. После завершения анализа верх магазина должен быть приведен к виду, пригодному для продолжения работы вызывающего процессора.
Для подграмматики определен некоторый набор символов, по которым возможен «ДОПУСК», то есть корректное завершение работы процессора. Этими символами являются те символы, которые отмечают столбцы, на пересечении которых со строками стоит ДОПУСК в таблицах функций действий.