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

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

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

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

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

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

Приклад перевірки контексних умов Розглянемо приклад перевірки контекстних умов при обробці оператора опису у мові типу С. Розглянемо граматику з такими правилами: <оператор_опису>::=<тип><список>; <список>::=<ідентифікатор>{ , <ідентифікатор>} Нагадаємо, що у прикладі програмування лексичного аналізатора, розглянутого раніше, формувався потік лексем-дескрипторів, які описувалась парою 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 (тип невідомий), а наприкінці обробки чергового оператора опису у всіх елементах таблиці відповідне поле з таким типом замінити. Для послідовних невпорядковиших таблиць можна вести облік кількості ідентифікаторів, описаних у одному операторі опису, і наприкінці його обробки змінити відповідне поле у певній кількості останніх записів. Можна також створити список всіх ідентифікаторів, які описані у даному операторі. У всіх випадках потрібно ретельно продумати спосіб організації таблиці символів і зміст полів у її записах.
Антиботан аватар за замовчуванням

2015

Коментарі

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

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

Нічого не вибрано
0%

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

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

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

Admin

26.02.2023 12:38

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