[ Страница назад | Страница вперед | Содержание | Индекс | Библиотека | Юридическая информация | Поиск ]

Программирование: Разработка и отладка программ


Примеры программ с использованием lex и yacc

Этот раздел описывает примеры программ для команд lex и yacc. Эти программы описывают простой калькулятор, поддерживающий операции сложения, вычитания, умножения и деления. Калькулятор также позволяет присваивать значения переменным (обозначаемым одной строчной буквой) и затем использовать их в вычислениях. Примеры программ lex и yacc находятся в следующих файлах:

Файл Содержание
calc.lex (Исходный текст лексического анализатора) Файл спецификаций lex, в котором определяются правила лексического анализа.
calc.yacc (Исходный текст синтаксического анализатора) Файл грамматики yacc, который содержит правила грамматического разбора. Для ввода информации применяется функция yylex, созданная командой lex.

Далее везде предполагается, что программы calc.lex и calc.yacc находятся в текущем каталоге.

Компиляция примеров

Для создания программы калькулятора выполните следующие действия в указанном порядке:

  1. Обработайте файл грамматики yacc, указав флаг -d (в результате yacc создаст не только исходную программу на C, но и файл определений лексем):

    yacc -d calc.yacc
    
  2. С помощью команды ls убедитесь, что были созданы следующие файлы:
    y.tab.c Исходный файл на языке C, созданный командой yacc для синтаксического анализатора.
    y.tab.h Файл заголовка, содержащий определения лексем, используемых анализатором.
  3. Обработайте файл спецификаций lex:

    lex calc.lex
    
  4. С помощью команды ls убедитесь, что был создан следующий файл:
    lex.yy.c Исходный файл на языке C, созданный командой lex для лексического анализатора.
  5. Скомпилируйте и скомпонуйте два исходных файла на языке C:

    cc y.tab.c lex.yy.c
    
  6. С помощью команды ls убедитесь, что были созданы следующие файлы:
    y.tab.o Объектный файл для исходного файла y.tab.c
    lex.yy.o Объектный файл для исходного файла lex.yy.c
    a.out Исполняемая программа
    После этого запустите программу a.out, введя команду:

    $ a.out
    

    Или переименуйте файл и запустите программу:

    $ mv a.out calculate
    $ calculate
    

    В любом случае, после запуска программы курсор будет помещен на строку, расположенную ниже приглашения командной строки ($). После этого вы можете работать с калькулятором, вводя числа и операторы. После нажатия клавиши Enter программа выведет результаты операции. Присвойте значение переменной:

    m=4 <enter>
    _
    

    Курсор переместится на следующую строку. После этого вы сможете использовать переменную в дальнейших вычислениях:

    m+5 <enter>
    9
    _
    

Исходный текст синтаксического анализатора

Ниже приведен текст файла calc.yacc. В это файле находится код из всех трех разделов файла грамматики yacc: объявления, правила и программы.

%{
#include <stdio.h>

int regs[26];
int base;

%}

%start list

%token DIGIT LETTER

%left '|'
%left '&'
%left '+' '-'
%left '*' '/' '%'
%left UMINUS  /* определение приоритета унарного минуса */

%%                   /* начало раздела правил */

list:                       /*empty */
         |
        list stat '\n'
         |
        list error '\n'
         {
           yyerrok;
         }
         ;

stat:    expr
         {
           printf("%d\n",$1);
         }
         |
         LETTER '=' expr
         {
           regs[$1] = $3;
         }

         ;

expr:    '(' expr ')'
         {
           $$ = $2;
         }
         |
         expr '*' expr
         {
           $$ = $1 * $3;
         }
         |
         expr '/' expr
         {
           $$ = $1 / $3;
         }
         |
         expr '%' expr
         {
           $$ = $1 % $3;
         }
         |
         expr '+' expr
         {
           $$ = $1 + $3;
         }
          |

         expr '-' expr
         {
           $$ = $1 - $3;
         }
         |
         expr '&' expr
         {
           $$ = $1 & $3;
         }
         |
         expr '|' expr
         {
           $$ = $1 | $3;
         }
         |

        '-' expr %prec UMINUS
         {
           $$ = -$2;
         }
         |
         LETTER
         {
           $$ = regs[$1];
         }

         |
         number
         ;

number:  DIGIT
         {
           $$ = $1;
           base = ($1==0) ? 8 : 10;
         }       |
         number DIGIT
         {
           $$ = base * $1 + $2;
         }
         ;

%%
main()
{
 return(yyparse());
}

yyerror(s)
char *s;
{
  fprintf(stderr, "%s\n",s);
}

yywrap()
{
  return(1);
}

Раздел объявлений

Записи этого раздела выполняют следующие функции:

Раздел правил

Раздел правил содержит правила грамматического разбора входного потока.

Раздел программ

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

main Функция, с которой начинается выполнение программы. Она вызывает функцию yyparse для запуска анализатора.
yyerror(s) Эта функция обработки ошибок выводит сообщения об ошибках.
yywrap Функция, которая возвращает 1 при обнаружении конца ввода.

Исходный текст лексического анализатора

Ниже приведен текст файла calc.lex. В этом файле подключается библиотека стандартного ввода-вывода и файл y.tab.h. Программа yacc создает этот файл заголовка на основе файла грамматики yacc, если в вызове команды yacc указан флаг -d. Файл y.tab.h содержит определения лексем, используемых синтаксическим анализатором. Файл calc.lex содержит правила формирования этих лексем из входного текста.

%{
 
#include <stdio.h>
#include "y.tab.h"
int c;
extern int yylval;
%}
%%
" "       ;
[a-z]     {
            c = yytext[0];
            yylval = c - 'a';
            return(LETTER);
          }
[0-9]     {
            c = yytext[0];
            yylval = c - '0';
            return(DIGIT);
          }
[^a-z0-9\b]    {
                 c = yytext[0];
                 return(c);
               }

Связанная информация

Глава 1, Инструменты и утилиты.

Создание языка ввода с помощью команд lex и yacc.

Работа с программами lex и yacc.

Команды ed, lex, sed, yacc.

Функция printf


[ Страница назад | Страница вперед | Содержание | Индекс | Библиотека | Юридическая информация | Поиск ]