While E do R
Пример
While x<y do begin x:=x+1; … end
X y < m1 if x x 1 +:= … m0 j
Дополним грамматику:
A→ if E then *1 RL| while*4 E do*1 R*5
E→S<S|… E→(S)F’T’<S<|aDF’T’<S<
L→λ*2| else *3 R*2
R→A| begin P end |aD:=S| if …| while …
Семантические программы: (для их реализации нужен независимый стек, т.е. у нас уже 3 стека, count - номер очередного символа обратной польской строки, который должен выводиться )
*1
count→в 3й стек,
пусто→ОПС,
jf →ОПС
*2
count→ ОПС[3й стек]
*3
(Count+2)→ОПС[3й стек]
count→ ОПС[3й стек]
пусто→ ОПС,
j → ОПС
пример:
if a<b then x:=a else x:=b
ab< m1 jf xa:= m2 j xb:=
| |
M1 M2
*4
В дополнительный 3ий стек записать номер счетчика count
*5
(count+2)→по ссылке из 3-го стека в ОПС
(По ссылке 3-го стека) →ОПС
j →ОПС
пример
while a<b do a:=a+1
ab < m1 jf aa1 +:= m0 j
| |
M0 m1
Цикла while вполне достаточно, поэтому не будем рассматривать реализацию (генерацию) цикла for и других…
Дополним грамматику операторами read и write.
A→ read H* read | write S *write
Где H→aD (скалярная переменная, индекс или пусто)
Разберемся теперь с описаниями переменных.
|
|
B→ program V; R _|_
B – вся программа
Описание может быть не одно, а несколько. V – возможная группа описания, U – одиночное описание (описывает либо вещественные либо целые переменные)
V→V;U
U→ int**1 a**2W| real aW
W→λ**5|[a**3]**4
Замена (исправленная грамматика, для анализатора LL(1)):
V→ int aW U’| real aW U’
U’→;U U’|λ
Описания могут быть и пустыми (например, если программа состоит только из оператора вывода). Тогда получаем
V→ int aW U’| real aW U’| λ
U’→;U U’|λ
**1
Тип – целый
**2
Имя a→в таблицу целых переменных (эта таблица – массив целых, где будут храниться значения этой переменной. Там же можно хранить, например, и само имя)
Для простых переменных этих двух программ достаточно, но для массивов – мало.
**3
Константа а →размер массива
**4
Размер → в таблицу
**5
0-размер →в таблицу
Мы рассмотрели действия для целых. Для вещественных те же действия, только отличается 1ый шаг. Ну и в таблице соответственные изменения.
имя | значение | количество | Ссылки для массивов | |
>0 |
Для работы с массивами – Ссылки для массивов, плюс в 4ую семантическую программу пишем:
Выделение памяти, в таблицу (номер переменной, размер в байтах)
Т.е. на выходе не только ОПС, но и сформированные таблицы переменных (т.е. таблицы, содержащие формат данных)
На выходе из синтаксического анализатора получим:
1. Длина констант типа int
2. Таблица констант типа int
3. Длина констант типа real
4. Таблица констант типа real
5. Длина переменных типа int
6. Таблица переменных типа int
|
|
7. Длина переменных типа real
8. Таблица переменных типа real
9. Длина ОПС
10. ОПС
При реализации процедур и функций у нас в языке появляются Описания и Вызовы.
Вызовы функций – операнды в формулах.
Вызов процедур как и во всех языках.
В момент вызова процедуры или функции должна работать автономная программа со своим локальным блоком памяти. Все фактические параметры и внутренние переменные локальны для конкретного вызова. Т.е. нужно предусмотреть выделение блока памяти по типу стека (для локальных переменных) при каждом вызове. И этот стек можно совместить с основным стеком вычислений, которые использует интерпретатор.
Тогда ОПС может иметь такой вид:
Pr(a,b,c,d);
Если считать что в момент вызова порядок операндов не меняется, то:
Pr – имя процедуры, операнд
Нужно предусмотреть счетчик количества параметров в вызове процедуры (4).
Pr abcd 4 сall точка возврата
Сall – универсальная процедура вызова
«Возврат из процедуры» – операция, должна стоять в конце процедуры, должна привести стек в такой вид, который был до вызова.