|
|||||||
АвтоАвтоматизацияАрхитектураАстрономияАудитБиологияБухгалтерияВоенное делоГенетикаГеографияГеологияГосударствоДомДругоеЖурналистика и СМИИзобретательствоИностранные языкиИнформатикаИскусствоИсторияКомпьютерыКулинарияКультураЛексикологияЛитератураЛогикаМаркетингМатематикаМашиностроениеМедицинаМенеджментМеталлы и СваркаМеханикаМузыкаНаселениеОбразованиеОхрана безопасности жизниОхрана ТрудаПедагогикаПолитикаПравоПриборостроениеПрограммированиеПроизводствоПромышленностьПсихологияРадиоРегилияСвязьСоциологияСпортСтандартизацияСтроительствоТехнологииТорговляТуризмФизикаФизиологияФилософияФинансыХимияХозяйствоЦеннообразованиеЧерчениеЭкологияЭконометрикаЭкономикаЭлектроникаЮриспунденкция |
LL(1)-синтаксичний аналізатор для мови PascalНаведемо текст LL(1)-синтаксичного аналізатора для мови програмування Pascal, зробивши деякі пояснення: - Синтаксичний аналізатор мови програмування Pascal використовує для виділення лексем з текстового файла функцію pascal_scaner(), яка при кожному звернені до неї виділяє з файла програми нову лексему. Коли сканер досягне кінця файла, то в подальшому EOF передається як нова лексема. Текст виділеної лексеми знаходиться в змінній lexema[], яка є зовнішньою змінною. - Допоміжна функція index_elem () знаходить індекс (порядковий номер починаючи з нуля) у відповідному масиві терміналів або нетерміналів. #include <stdio.h> #include "mystand.h" /* визначення структури стека синтаксичого аналiзатора */ #define MAX_STACK 200 int STACK[MAX_STACK], POS_STACK=0; #define NULL_STACK() (POS_STACK? 0: 1) #define COPY_STACK() (STACK[POS_STACK]) #define PUSH_STACK() (POS_STACK? --POS_STACK:0) #define DOWN_STACK(c) (POS_STACK < MAX_STACK? STACK[++POS_STACK]=c,1: 0) extern int pascal_scaner(void); // функція виділення нової лексеми extern void scaner_close(void); // функція, що закриває вхідний файл extern char lexema[]; // поточна вхідна лексема extern int lexema_code; // код виділеної лексеми extern int lexema_line; // рядок, з якого прочитана лексема extern int lexema_pos; // позиція лексеми у рядку extern int index_elem(int *, int, int); // Зовнішні змінні для синтаксичного аналізатора: // - таблиця управління LL(1) - синтаксичним аналізатором - TABL_LL1_UPR. // Кількість рядків таблиці numnet - кількість нетерміналів граматики, // кількість стовпчиків - (numtrm+1) - кількість терміналів в граматиці // Допоміжна функція, яка визначає індекс термінала або нетермінала у // відповідному масиві. int index_elem(int *net_term, int num, int elem) { int i; for (i=0; i < num; i++) if (*(net_term+i) = = elem) return i; } // Лексичний аналiзатор: // - видiляє лексему в поле lexema, // - в поле lexema_code заносить код лексеми. // - аналізатор повертає E-епсилон слово(lexema_code==0), коли досягли ЕOF, // iнакше код лексеми в полi lexema_code // В lexema_line знаходиться номер рядка, з якого прочитана лексема. // В lexema_pos знаходиться позиція в рядку, з якого прочитана лексема.
int ll1_parser_pascal(q,r) struct node *q; struct dnode *r; { struct node *qw; int i, line0, colomn, ind; int upr; /* початковi установки для синтаксичного аналiзатора */ STACK[0]=0; STACK[1]=*(q->pd); POS_STACK=1; ind=0; lexema_code=0; /* головний цикл работи синтаксичного аналiзатора */ while (! NULL_STACK()) // поки стек не пустий { if (!ind) ind=1, pascal_scaner(); // A. Обробка при умовi, що на вершинi стека термiнал if (COPY_STACK() >= 0) { if (COPY_STACK() == lexema_code) { ind=0; PUSH_STACK(); continue; } // можливо короткий if if (strcmp(NAME_ELEM(COPY_STACK()),"else") == 0) { PUSH_STACK(); PUSH_STACK(); continue; } // короткий if // Синтаксична помилка printf("Синтаксична помилка: рядок - %5.5i, позицiя - %3.3i\n",lexema_line,lexema_pos); printf("Пропущена лексема %s\n",NAME_ELEM(COPY_STACK())); printf("Вершина стека - %s, вхiдна лексема - %s - %s\n",NAME_ELEM(COPY_STACK()),lexema,NAME_ELEM(lexema_code)); scaner_close(); return(0); } // B. Обробка при умовi, що на вершинi нетермiнал line0=index_elem(netname,numnet,COPY_STACK()); if (lexema_code) colomn=index_elem(terminal,numtrm,lexema_code); else colomn=numtrm; if (upr= *(TABL_LL1_UPR+line0*(numtrm+1)+colomn)) { PUSH_STACK(); // пошук продукції в списку продукцій for(qw=q,i=1; i < upr; i++,qw=qw->next); // запис правої частини продукції в стек for (i=qw->len-1; i > 0; i--) DOWN_STACK(*(qw->pd+i)); continue; } // Синтаксична помилка в програмi printf("Синтаксична помилка: рядок - %5.5i, позицiя - %3.3i\n",lexema_line,lexema_pos); printf("Вершина стека - %s, вхiдна лексема - %s - %s\n",NAME_ELEM(COPY_STACK()),lexema,NAME_ELEM(lexema_code)); scaner_close(); return(0); } // кiнець цикла обробки стека // Стек порожній: перевiримо стан справ на входi if (! ind) pascal_scaner(); scaner_close(); if (lexema_code == 0) { printf("\nВ програмi синтаксичних помилок немає\n");return(1); } else { printf("\nЛогiчний кiнець програми знайдено до кiнця вхiдного файла\n"); return(0); } } // кiнець програми
Поиск по сайту: |
Все материалы представленные на сайте исключительно с целью ознакомления читателями и не преследуют коммерческих целей или нарушение авторских прав. Студалл.Орг (0.006 сек.) |