Professional Documents
Culture Documents
Tema1 Hash
Tema1 Hash
Мовні процесори
Компілятори Транслятори Інтерпретатори
Крос-компілятори
Препроцесори
PHP
Perl
Python
Ruby
2. Основні фази мовного процесора,
спрощена модель компілятора.
препроцесор;
лексичний аналіз;
організація таблиць;
синтаксичний аналіз;
семантичний аналіз;
генерація проміжного коду;
оптимізація;
генерація машинного коду.
2.1. Лексичний аналіз програм для мови
високого рівня
Лексичний аналіз - це розбиття вхідної послідовності
символів на найпростіші змістовні одиниці (лексеми).
Послідовність символів:
cost := (price + tax) * 0.98
Послідовність лексем:
<iden,р1> <assign> <left> <iden,р2> <plus> <iden,р3>
<right> <mult> <number,q1>
Виконання індивідуальної роботи №1
(фаза лексичного аналізу)
Приклад лексичного аналізу
подібний до лабораторних робіт 1, 2
Вхідний файл: asdsf aaaf asssas j 123as
a12222fkl nmnmn faaa
Маска: a*s*
Файл з лексемами: <match, asdsf> <notMatch,
aaaf> <match, asssas> <notMatch, j> < notMatch,
123as> <notMatch, a12222fkl> <notMatch,
nmnmn> <notMatch, faaa>
Схема пам’яті
h(α): h0(α), h1(α), . . , h m (α)
Приклад одновимірного
хешування
cost, tax і price
h0(α)=СОDЕ(α) mod 6
hi(α)=(СОDЕ(α)+i+2) mod 6), i=1,…,5
CODE (cost)=3+15+19+20=57
h0(cost)= CODE(cost) mod 6= 57 mod 6 =3
CODE(a)=1 CODE(p)=16
CODE (tax)= 20+1+24=45
CODE(c)=3 CODE(r)=18
h0(tax)= CODE(tax) mod 6 = 45 mod 6 = 3
CODE(e)=5 CODE(s)=19 h1(tax)= 48 mod 6 = 0
CODE(i)=9 CODE(t)=20 CODE (price)=16+18+9+3+5=51
h0(price)= CODE (price) mod 6 = 51 mod 6 = 3
CODE(o)=15 CODE(x)=24 h1(price)= 54 mod 6 =0
h2(price)= 55 mod 6 =1
Виконання індивідуальної роботи №1
(робота з таблицями)
Оператор: cost:=(tax+price)*0.98
Розмір таблиці: n=6
Первинна хеш-функція:
h0(α)=Code(α) % n
Вторинні хеш-функції:
hi(α)=(Code(α)+i+2) % n,
i=1,...,n-1
Адреса у локальній мережі:
Програмна група Apm \Math_02 \Zavd_Lab \SystProg \Проекти \Хеш таблиці
Функції розміщення
// Адитивний метод
// Ділення typedef
typedef int HashIndexType; unsigned char
const int HashTableSize=7; HashIndexType; //8 bit
const int HashTableSize=256;
HashIndexType Hash(int Key) HashIndexType Hash(char *str)
{ {
return Key % HashTableSize; HashIndexType h = 0;
} while (*str) h+= *str++;
return h;
}
Методи вирішення
конфліктів
Побудова вторинних функцій
h1,...,hm
hj(α) hi(α) для всіх i j, m = n-1.
hi(α) = (h0(α) + i) mod n, (1)
hi(α) = (h0(α) + ri) mod n, (2)
h (α) = (i(h0(α) +1)) mod n, (3)
i
h (α) = (h (α) + ai2+bi) mod n, (4)
i 0
i=1,2,…,n-1
2.3. Синтаксичний аналіз програми
Послідовність символів: Послідовність кроків:
cost := (price + tax)*0.98 1) <ід, р2> <+> <ід, р3>
2) крок1 <*> <дч, q1>
3) <ід, р1> <пр> крок2
Послідовність лексем:
<ід, р1> <пр> <(> <ід, р2> <+> <ід, р3> <)> <*> <дч, q1>
< >
< >
Пріоритети операцій
0 – “:=”
1 – “+”
2 – “*”
“(” – збільшує пріоритет операції на 3
“)” – зменшує пріоритет операції на 3
cost:=(price+tax*5)*0.98+k*7.2
cost:=(price+tax)*0.98 0 4 5 2 1 2
0 4 2 Послідовність операцій:
*
Послідовність операцій: +
+ *
* *
:= +
:=
Рівні вершин
cost := (price + tax) * 0.98
0, якщо n немає нащадків
l n
max l ni 1, ni нащадки вершини n
1i k
Виконання індивідуальної роботи №1
(синтаксичний аналіз)
2.4. Генерація проміжного коду
Дерево у компактному вигляді для
числового виразу:
((3-(5+9))/(2*3))
Команда Значення
Load m R(m)суматор
Add m суматор + R(m)суматор
Mpy m суматор * R(m)суматор
Store m суматор R(m)
Load =m m суматор
Add =m суматор + m суматор
Mpy =m суматор * m суматор
2.4. Генерація проміжного коду
а) б) в)
Введемо позначення:
C n – частина проміжного коду, що відповідає вершині .
l n – рівень вершини .
0, якщо n не немає
має нащадків
l n
max l ni 1, ni нащадки вершини n
1i k
Визначимо код , для кожного типу вершини:
C n Load C m3
Store C m1
3) Якщо n – вершина типу б), m1, m2, m3 –
нащадки, то вершині відповідає такий
код:
C n C m3
Store $l n
Load C m1
Add $l n
C n C m3
Store $l n
Load C m1
Add $l n
C n C m3
Store $l n
* Load C m1
Mpy $l n
cost := (price + tax)*0.98
???
(зайві пробіли, не той рівень вершин,
не той порядок завантаження)
Load a Load b
2) Mpy b
операція «*» є комутативною .
Mpy a
Store a
3) Load a можна вилучити при умові, що
надалі комірка a не буде використовуватись або буде
заповнена безпосередньо перед використанням.
Load a
4) Store b можна вилучити при умові, що за нею
слідує інший оператор Load і немає переходу до Store b.
Наступні входження b замінюються на a до того
моменту, поки знову не з’явиться оператор Store b.
2.5. Оптимізація проміжного коду