GPLex + GPPG

Материал из Вики проекта PascalABC.NET
(разн.) ← Предыдущая версия | Текущая версия (разн.) | Следующая версия → (разн.)
Перейти к навигацииПерейти к поиску

Практическое занятие 1

  • GPLex - генератор сканеров (лексических анализаторов)
  • GPPG - генератор парсеров (синтаксических анализаторов)

Комплект для практического занятия скачиваем отсюда. Состав:

  • LexProjects.sln - файл решения, содержащее проект Lex1.csproj
  • Lex1.csproj - файл демонстрационного проекта для GPLex
  • gplex.exe - исполняемый файл генератора сканеров
  • gppg.exe - исполняемый файл генератора парсеров (он нам понадобится на следующем занятии)
  • ShiftReduceParser.dll - внешняя сборка, необходимая для работы сгенерированного компилятора
  • gplexx.frame - файл, включаемый в генерируемый файл лексического анализатора
  • mymain.cs - основная программа, содержащая создание сканера и сканирование всех лексем в файле
  • my.lex - файл, содержащий правила для генерации лексического анализатора
  • a.txt - файл программы, подаваемой на вход сгенерированному лексеру

Компиляция проекта

  • Выполняем команду gplex.exe /noparser my.lex
При этом генерируется файл my.cs, содержащий код лексера. Ключ /noparser означает, что генерируется лексер без парсера.
  • Открываем и компилируем .sln

Формат .lex-файла

Определения
%%
Правила
%%
Пользовательский код

Пользовательский код содержит описания полей и методов, включаемых в генерируемый класс Scanner.

Класс Scanner

  • Основной метод - int yylex() - возвращает номер следующей лексемы (токена)
  • Свойства
string yytext - текст лексемы
int yyline - номер строки лексемы
int yycol - номер столбца лексемы
int yyleng - длина лексемы

Задание

  1. Откомпилировать лексический анализатор и запустить его для файла a.txt
  2. Сделать имя файла, обрабатываемого лексическим анализатором, параметром командной строки
  3. Подсчитать количество, среднюю, минимальную и максимальную длину всех идентификаторов
  4. Найти сумму всех целых и сумму всех вещественных в файле
  5. Дана программа, в которой встречаются ключевые слова begin end. Определить, правильно ли они расставлены
  6. По данному тексту слов составить таблицу
слово   список его вхождений в текст в формате (строка,столбец), (строка,столбец)

Практическое занятие 2

Задание

Создадим программу для HTML-форматирования кода на языке программирования. Необходимо выделять ключевые слова жирным, строковые литералы - синим, комментарии - серым, цифры - зеленым. Комментарии в {} писать вразрядку (после каждого символа - пробел)

Комментарии к заданию

Правила в .lex-файле:

.|\n {
  Console.Write(yytext);
}

- означает, что если встречен любой символ (.) или конец строки (\n), то просто вывести его. Это правило стоит последним, поэтому оно выполняется только если не выполняются другие правила.

Однострочный комментарий можно создать так:

DotChr [^\r\n]
OneLineCmnt  \/\/{DotChr}*

\/ означает символ /, он так пишется, поскольку значок /, написанный без \, имеет другой смысл

^" "+

означает "строка, начинающаяся с пробелов" Это нужно, чтобы задать отступы в начале строки, заменив их на  

\'[^']*\'

означает "строка, заключенная в одинарные апострофы"

[^']

означает "последовательность символов, не включающая '"

Инициализацию полей провести в статическом методе

public static void Init(){

Состояния лексического анализатора

При работе лексер может переходить из состояния в состояние командой BEGIN(ИмяСостояния);

Для возврата в первоначальное состояние следует вызвать BEGIN(INITIAL);

В другом состоянии могут распознаваться другие лексемы.

Например, вот как делаются многострочные комментарии {...}

В первой секции (до первого %%) следует задать новое состояние:

%x COMMENT

Вход, выход и действия в состоянии COMMENT обрабатываются следующим образом:

"{" { 
  // переход в состояние COMMENT
  BEGIN(COMMENT);
}

<COMMENT> "}" { 
  // переход в состояние INITIAL
  BEGIN(INITIAL);
}

<COMMENT>{ID} {
  // обрабатывается ID внутри комментария
}

Практическое занятие 3

Комплект для практического занятия скачиваем отсюда.

Он содержит .y и .lex файлы, создающие компилятор перевода выражения со скобками в обратную польскую бесскобочную запись.

Для уяснения содержимого .y и .lex файлов необходимо иметь в виду следующее: эти файлы неразрывно связаны друг с другом, и информация, определенная в одном файле, используется в другом.

Разберемся в содержимом этих файлов и в том, как их компилировать.

  • Поскольку gplex и gppg теперь работают вместе, gplex следует запускать без ключа /noparser, а gppg - с ключом /gplex
  • my.lex
{INTNUM} {return (int)Tokens.INTNUM;}

Для каждой лексемы обязательно следует возвращать целое значение, характеризующее тип лексемы.

  • Tokens - перечислимый тип с полями, задаваемыми в myyacc.y. Он формируется автоматически по записи
%token INTNUM,REALNUM,ID
  • Приведем для примера одно из правил в myyacc.y:
expr : expr PLUS T { Console.WriteLine("+"); }
     | T {}
     ;

Здесь лексема PLUS определена в файле my.lex Обратим также внимание на то, что правила во второй секции myyacc.y разделяются пустой строкой и если правило состоит более чем из одного подправила, то оно обязательно должно завершаться символом ;

  • Определим лексему PLUS в файле my.lex:
PLUS \+
%%
{PLUS} {return (int)Tokens.PLUS;}

В файле myyacc.y:

%token INTNUM,REALNUM,ID
  • В файле myyacc.y:
F : INTNUM {Console.WriteLine($1);}
  • В файле myyacc.y:
%union {
  public int iVal;
  public double dVal;
  public string sVal;
}
%token <iVal> INTNUM

В файле my.lex:

{INTNUM} {
           yylval.iVal = int.Parse(yytext); 
           return (int)Tokens.INTNUM;
         }

Задания

  • Разобраться в содержимом lex-файла
  • Разобраться в содержимом и формате yacc-файла
  • Добавить операции - /
  • Добавить операцию % (остаток от целочисленного деления)
  • Рассмотреть грамматику if then else и посмотреть на выдаваемую ошибку
  • Рассмотреть модифицированную грамматику if then else и убедиться, что ошибки нет
  • Добавить в грамматику выражений в начале программы присваивания вида a=3;b=4; После всех присваиваний должно идти выражение. Выражение также может содержать указанные переменные.

Практическое занятие 4

Задания

  • Реализовать вычисление двоичного рационального числа, используя грамматику 1
  • Реализовать вычисление двоичного рационального числа, используя грамматику 2
  • Реализовать численное дифференцирование, дополнив его функциями exp, ln, x^n, a^x

Практическое занятие 5

  • Реализовать перевод грамматики выражений в дерево разбора, после чего написать интерпретатор, вызывающий метод eval() для корневого узла дерева разбора, вычисляющий выражение.

Итоговые задания на зачет

1. Подсчитать количество идентификаторов в файле, а также сумму всех целых чисел в файле.

2. По данному тексту слов составить таблицу.

слово   список его вхождений в текст в формате (строка,столбец), (строка,столбец).

3. Программа для HTML-форматирования кода на языке программирования.

4. Реализовать вычисление двоичного рационального числа, используя грамматику 1

5. Реализовать численное дифференцирование

6. Реализовать перевод грамматики выражений в дерево разбора, и интерпретатор, вычисляющий выражение.