Инфраструктура для тестирования лексического и синтаксического анализатора
Были реализованы генераторы тестовых файлов для лексических и синтаксических анализаторов:
Генератор для лексических анализаторов. Результатом его работы являются файлы с заданным количеством лексем. Лексемы выбираются случайным образом из множества, которое поддерживает язык.
Генератор для синтаксических анализаторов. Результатом его работы являются файлы с заданным количеством функций. Функции имеют:
сигнатуру с случайными именами, именами переменных и типами;
тела функций, которые представляют собой объединение нескольких тел функции, заранее заданных (список возможных тел расширяем).
В данной работе рассматриваются лексический и синтаксический генераторы – flex и bison, соответственно.
Flex – это инструмент для лексического анализа, который может использоваться для выделения из исходного текста определенных строк заранее заданным способом.
Bison – это инструмент для синтаксического разбора; он читает текст и может использоваться для конвертирования последовательности слов в структурированный формат для дальнейшей обработки.
На вход генераторы принимают правила выделения лексем, а на выходе даёт код анализатора, в виде функции на языке Си. Общая структура для описания генераторов:
блок определений – содержит стартовые значения и определения;
блок правил – выражения и соответствующие им действия;
блок кода на С – пользовательский код.
Определения и правила описываются при помощи одного из вариантов расширенной формы Бекуса-Наура.
Пример описания лексического генератора (flex) для целых чисел и чисел с плавающей точкой:
| Блок определений | ||
|---|---|---|
| Нетерминальные символы(идентификаторы) | Выражение | |
DIGIT IntegerLiteral FloatLiteral |
[0-9] {DIGIT}+ {DIGIT}+"."{DIGIT}* |
|
| Блок правил | ||
| Правило | Обработчик | |
{IntegerLiteral} {FloatLiteral} |
int int_literal = atoi(yytext); printf("%d\n“, int_literal); float fl_literal = atof(yytext); printf("%f\n“, fl_literal); |
|
| Блок пользовательского кода | ||
void main(int argc, char **argv) { ++argv, --argc; if ( argc > 0 ) yyin = fopen( argv[0], "r" ); else yyin = stdin; yylex(); } |
||
Пример описания синтаксического генератора (bison) для целых чисел и чисел с плавающей точкой:
| Блок определений | |
|---|---|
| Лексемы | |
%token INTEGER_LITERAL FLOAT_LITERAL // ожидаемые токены %start input // Входное правило для анализатора |
|
| Блок правил | |
| Правило | Обработчик |
%% input: /* empty */ | integer_literal input | float_literal input; integer_literal: INTEGER_LITERAL float_literal: FLOAT_LITERAL |
// Входное правило для анализатора {printf("Current int: %d\n", $1);} {printf("Current float: %f\n", fsum);} |
Для связи двух генераторов между собой необходимо подключить сгенерированный с помощью bison файл в описание для flex и в обработчиках вернуть соответствующие токены.