- •Транслирующая грамматика
- •C) Функии переходов преобразователя и пример его работы
- •Пример работы преобразователя
- •Лексический анализатор
- •A) Грамматика лексических единиц и структура лексем
- •B) Матрица переходов лексического анализатора
- •D) Структура программы лексического анализатора и пример его работы
- •C) Описание символов действия
- •D) Атрибутная грамматика в окончательном виде
- •E) Вывод в атрибутной грамматике
- •B) Построение инструкций а-преобразвателя
- •C) Фрагмент работы а-преобразователя
- •Заключение
Лексический анализатор
A) Грамматика лексических единиц и структура лексем
Множественные терминальные символы:
_CHAR_::={A..Z,a..z}
_DIGIT_::={0..9}
_RAZD_::= ‘{‘ , ‘}’ ,’ ‘, ‘(‘ , ‘ )’, ‘;’ , ‘ , ‘ , ‘ . ‘
_OP_::= ‘ * ‘ , ‘ + ‘ , ‘ < ’ , ‘ > ‘ , ‘ = ‘
Правила, описывающие лексические единицы идентификаторов ,служебных слов:
<IDENTIFICATOR>::=_CHAR_<CONT >
<CONT >::=_DIGIT_<CONT>
<CONT >::=_CHAR_<CONT>
<CONT >::=’(‘ <KEY>
<CONT >::=$
<KEY>::=’)’ | $
Правила, описывающие лексические единицы чисел:
<NUMBER>::=_DIGIT_<CONT_NUMBER>
<CONT_NUMBER>::=$ | <NUMBER>
< CONT_NUMBER>::=.< CONT_NUMBER _F>
< CONT_NUMBER _F>::=_DIGIT_< CONT_NUMBER _F>
< CONT_NUMBER _F>::=$
Правила, описывающие лексические единицы разделителя:
<R>::= _RAZD_<CONT_R>
<CONT_R>::= $
Правила, описывающие лексические единицы ‘операций’:
<OP>::=_OP_<CONT_OP>
<CONT_OP>::= <OP> | $
B) Матрица переходов лексического анализатора
/*_I_*/ /*_NbrI_*/ /*_NbrF_*/ /*_Id_*/ /*_Key_*/ /*_Op_*/
/*Digt*/ {BeginNbr,ProcessNbr ,ProcessNbr ,ProcessId ,EndKey ,EndOp },
/*Char*/ {BeginId ,Error ,Error ,ProcessId ,EndKey ,EndOp },
/*Op*/ {BeginOp ,EndNbr ,EndNbrF ,EndId ,Error ,ProcessOp },
/*{*/ {EndRazd ,Error ,Error ,Error ,Error ,Error },
/*}*/ {EndRazd ,Error ,Error ,Error ,Error ,Error },
/*(*/ {EndRazd ,Error ,Error ,ProcessKey,EndKey ,EndOp },
/*)*/ {EndRazd ,EndNbr ,EndNbrF ,EndId ,EndKey ,Error },
/*;*/ {EndRazd ,EndNbr ,EndNbrF ,EndId ,Error ,Error },
/* */ {EndRazd ,EndNbr ,EndNbrF ,EndId ,EndKey ,EndOp },
/*.*/ {Error ,ProcessNbrF,Error ,Error ,Error ,Error },
/*,*/ {EndRazd ,Error ,Error ,EndId ,Error ,Error }
Диаграмма состояний:
c) Структуры данных и символы действия лексического анализатора
Семантика лексического анализатора: заключается в том, что на вход лексического анализатора подается текст программы(цепочка символов) и на выходе мы получаем лексемы. Лексема должна быть представлена в следующей форме: класс, указатель на символьное представление. Класс-группа, к которой относится данная лексема -идентификатор, служебное слово, разделитель, операция, число (целочисленная константа , дробная константа). Указатель на символьное представление, например, может хранить номер в таблице символов. Лексический анализатор должен строить таблицу символьных представлений, таблицу идентификаторов.Для контроля за правильностью служебных слов можно создать таблицу допустимых служебных слов. И при обнаружении какого-то служебного слова в исходном тексте программы нужно проверить, а допустим ли такое слово.
class Lex: public Sortable
{
public:
Lex() {type=0;ptr.idx=0L;};
Lex(int t,int idx){type=t;ptr.idx=idx;};
Lex(int t,void *p ){type=t;ptr.ptr=p;};
Lex(Object &s)
{Lex::Lex((Lex&)s);}
Lex(const Lex& l)
{ if(this!=&l)
{
type=l.type;
ptr.idx=l.ptr.idx;
}
}
virtual classType isA() const { return 0xFF; }
virtual char *nameOf() const { return "Lexem"; }
virtual int isEqual( const Object& O) const
{return (type==((Lex&)O).type)&&(ptr.ptr==((Lex&)O).ptr.ptr);}
virtual int isLessThan( const Object& ) const {return 1;};
virtual hashValueType hashValue() const { return 0; }
virtual void printOn( ostream& out) const{output(out);}
int operator==(Lex &l)
{
return (type==l.type)&&(ptr.idx==l.ptr.idx);
}
void output(ostream &) const;
static void (*Table[11][6])();
static char* Errors[11][6];
static int classify(char);
private:
int type;
union
{ int idx;
void *ptr;
}ptr;
// Символы действия:
static void BeginNbr(); // начать обработку числовой константы
static void BeginId(); // начать обработку идентификатора
static void BeginOp(); // начать обработку операции
static void BeginRazd(); // начать обработку разделителя
static void ProcessNbr(); // обрабатывать целую константу
static void ProcessNbrF();// обрабатывать дробную константу
static void ProcessKey(); // обрабатывать служебное слово
static void ProcessId(); // обрабатывать идентификатор
static void ProcessOp(); // обрабатывать операцию
static void EndNbr(); // создать лексему - целую константу
static void EndNbrF(); // создать лексему - дробную константу
static void EndId(); // создать лексему - идентификатор
static void EndOp(); // создать лексему - операцию
static void EndKey(); // создать лексему - служебное слово
static void EndRazd(); // создать лексему - разделитель
static void Error();
static char* LexName[];
static char* RazdName[];
static char* KeyWord[];
static char* Op[];
static int nKeyWord;
static int nOp;
};