Семантичний контроль. Приклад.

Інформація про навчальний заклад

ВУЗ:
Національний університет Львівська політехніка
Інститут:
Не вказано
Факультет:
Не вказано
Кафедра:
Не вказано

Інформація про роботу

Рік:
2024
Тип роботи:
Лекція
Предмет:
Інші

Частина тексту файла (без зображень, графіків і формул):

Приклад перевірки контексних умов Розглянемо приклад перевірки контекстних умов при обробці оператора опису у мові типу С. Розглянемо граматику з такими правилами: <оператор_опису>::=<тип><список>; <список>::=<ідентифікатор>{ , <ідентифікатор>} Нагадаємо, що у прикладі програмування лексичного аналізатора, розглянутого раніше, формувався потік лексем-дескрипторів, які описувалась парою syn, lex[lexsize], де символьна змінна syn призначалась для позначення синтаксичної категорії лексеми, у символьний масив-рядок lex[lexsize] записувалась конкретна лексема (ідентифікатор, число, службове слово, розділювач). Так, для ідентифікаторів було вибрано syn=’i’, а для односимвольних розділювачів , ; syn=’,’ і syn=’;’ відповідно. Припустимо, що для службових слів int і float було вибрано syn=’1’ і syn=’2’ відповідно. Тоді наведені правила граматики можна переписати у вигляді O → ( 1 | 2 ) i { , i } Для проведення синтаксичного контролю ланцюжків, що виводяться з нетермінального символа О, можна запропонувати таку процедуру: void Op_opysy ( ) { switch (syn) { case ‘1’: case ‘2’: scan ( ) ; if (syn != ‘i’) { f=0; puts(“Nema identyfikatora u spysku”); } else { scan( ); while (syn==’,’) { scan( ); if (syn != ‘i’) { f=0; puts(“Nema identyfikatora pislja comu”); } else scan( ) ; } if (syn == ‘;’) scan( ); else { f=0; puts(“Nema ; pislja spysku”); } break; default: f=0; puts(“Nema typu”); } } Для проведення семантичного контролю потрібно викликати певні семантичні підпрограми. Семантична підпрограма для обробки оператора опису повинна забезпечити виконання семантичної угоди про єдиність опису ідентифікаторів. Для цього використовується таблиця ідентифікаторів, у якій кожному ідентифікатору повинен відповідати лише один запис. Такий запис додається у таблицю, коли даний ідентифікатор виявлено вперше. Це повинна зробити семантична підпрограма, що викликається під час обробки оператора опису. Вона повинна спочатку здійснити пошук кожного розпізнаного ідентифікатора у таблиці символів (ідентифікаторів). Якщо такий ідентифікатор відсутній, потрібно внести новий запис у таблицю. Якщо такий ідентифікатор знайдено, це свідчить про те, що він був описаний раніше, і робиться спроба повторного опису ідентифікатора. У цьому випадку потрібно сформувати повідомлення про семантичну помилку. Крім того, при обробці оператора опису фіксується інформація про тип змінної; дана інформація заноситься у полі значення для відповідного ідентифікатора. Таблицю символів будемо розглядати як масив структур. У кожному записі таблиці передбачимо поле для самого ідентифікатора (ключ запису), а також інформацію про його тип. Нехай структура одного запису описується у такий спосіб: typedef struct { char name[lexsize]; char type; /* 1 – int, 2 – float, 0 – unknown */ int ozn ; /* 1 – було присвоєно значення, 0 – не було*/ } el_tabl; Тоді таблицю ідентифікаторів можна описати так: el_tabl tabl_ident[tablsize]; Розмістимо ці описи серед описів глобальних змінних, щоб до таблиці символів легко було звертатись з різних підпрограм. Також серед глобальних змінних передбачимо змінну цілого типу k_el − для обліку кількості занесених у таблицю записів (спочатку k_el=0) і змінну символьного type_ident − для запам'ятовування типу, що вказаний на початку оператора опису. # include <stdio.h> # include <string.h> # define lexsize 30 # define tablsize 100 … char lit, syn, lex[lexsize] type_ident; int cl, i , f , k_el=0; typedef struct { char name[lexsize]; char type; /* 1 – int, 2 – float, 0 – unknown */ int ozn ; /* 1 – було присвоєно значення, 0 – не було*/ } el_tabl; el_tabl tabl_ident[tablsize]; … int poshuk(void); void zapys(void); void scan(void); … void Op_opysy ( ) { switch (syn) { case ‘1’: case ‘2’: type_ident=syn; scan ( ) ; if (syn != ‘i’) { f=0; puts(“Nema identyfikatora u spysku”); } else { if (poshuk()=-1) zapys( ); else ( printf (“Povtornyy opys %s \n”,lex); scan( ); while (syn==’,’) { scan( ); if (syn != ‘i’) { f=0; puts(“Nema identyfikatora pislja comu”); } else {if (poshuk()=-1) zapys( ); else ( printf (“Povtornyy opys %s \n”,lex); scan( ) ; } } if (syn == ‘;’) scan( ); else { f=0; puts(“Nema ; pislja spysku”); } break; default: f=0; puts(“Nema typu”); } } У мові типу Паскаль тип змінної у операторі опису вказано після списку змінних, тому семантична програма для обробки оператора опису дещо складніша. Можна, наприклад, під час формування нового запису у таблиці ідентифікаторів вказати : type_ident=0 (тип невідомий), а наприкінці обробки чергового оператора опису у всіх елементах таблиці відповідне поле з таким типом замінити. Для послідовних невпорядковиших таблиць можна вести облік кількості ідентифікаторів, описаних у одному операторі опису, і наприкінці його обробки змінити відповідне поле у певній кількості останніх записів. Можна також створити список всіх ідентифікаторів, які описані у даному операторі. У всіх випадках потрібно ретельно продумати спосіб організації таблиці символів і зміст полів у її записах.
Антиботан аватар за замовчуванням

01.01.1970 03:01-

Коментарі

Ви не можете залишити коментар. Для цього, будь ласка, увійдіть або зареєструйтесь.

Ділись своїми роботами та отримуй миттєві бонуси!

Маєш корисні навчальні матеріали, які припадають пилом на твоєму комп'ютері? Розрахункові, лабораторні, практичні чи контрольні роботи — завантажуй їх прямо зараз і одразу отримуй бали на свій рахунок! Заархівуй всі файли в один .zip (до 100 МБ) або завантажуй кожен файл окремо. Внесок у спільноту – це легкий спосіб допомогти іншим та отримати додаткові можливості на сайті. Твої старі роботи можуть приносити тобі нові нагороди!
Нічого не вибрано
0%

Оголошення від адміністратора

Антиботан аватар за замовчуванням

Подякувати Студентському архіву довільною сумою

Admin

26.02.2023 12:38

Дякуємо, що користуєтесь нашим архівом!