Лекции.Орг


Поиск:




Категории:

Астрономия
Биология
География
Другие языки
Интернет
Информатика
История
Культура
Литература
Логика
Математика
Медицина
Механика
Охрана труда
Педагогика
Политика
Право
Психология
Религия
Риторика
Социология
Спорт
Строительство
Технология
Транспорт
Физика
Философия
Финансы
Химия
Экология
Экономика
Электроника

 

 

 

 


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нець програми

 





Поделиться с друзьями:


Дата добавления: 2015-11-05; Мы поможем в написании ваших работ!; просмотров: 561 | Нарушение авторских прав


Поиск на сайте:

Лучшие изречения:

Своим успехом я обязана тому, что никогда не оправдывалась и не принимала оправданий от других. © Флоренс Найтингейл
==> читать все изречения...

2378 - | 2186 -


© 2015-2024 lektsii.org - Контакты - Последнее добавление

Ген: 0.007 с.