Язык Си в примерах/Калькулятор выражений в обратной польской нотации на Bison: различия между версиями

Материал из Викиучебника — открытых книг для открытого мира
Содержимое удалено Содержимое добавлено
м Категоризация по запросу на w:ВП:РДБ
Строка 5: Строка 5:


=== Файл с правилами <tt>bison</tt> ===
=== Файл с правилами <tt>bison</tt> ===
Примечание:
Пример реально удалось запустить...
НО... при выполнении этого примера в VM-Linux под SuSe-11.1 относительно оригинала статьи пришлось сделать следующие изменения:
1. В данный файл описания грамматики(после "#include <stdio.h>")
пришлось добавить прототипы ф-ий «yylex», «yyerror»(определенных в «main»).
2. Вместо команды «cpp» - трансляцию-сборку надо было выполнять при помощи «c++».


<code>
<code>

Версия от 07:57, 11 июня 2010

Язык Си в примерах


  1. Компиляция программ
  2. Простейшая программа «Hello World»
  3. Учимся складывать
  4. Максимум
  5. Таблица умножения
  6. ASCII-коды символов
  7. Верхний регистр
  8. Скобочки
  9. Факториал
  10. Степень числа
  11. Треугольник Паскаля
  12. Корень уравнения
  13. Система счисления
  14. Сортировка
  15. Библиотека complex
  16. Сортировка на основе qsort
  17. RPN-калькулятор
  18. RPN-калькулятор на Bison
  19. Простая грамматика
  20. Задача «Расчёт сопротивления схемы»
  21. Простая реализация конечного автомата
  22. Использование аргументов командной строки
  23. Чтение и печать без использования stdio
  24. Декодирование звукозаписи в формате ADX
  25. Другие примеры

Калькулятор на Bison

GNU Bison

Файл с правилами bison

Примечание: Пример реально удалось запустить... НО... при выполнении этого примера в VM-Linux под SuSe-11.1 относительно оригинала статьи пришлось сделать следующие изменения: 1. В данный файл описания грамматики(после "#include <stdio.h>")

       пришлось добавить прототипы ф-ий «yylex», «yyerror»(определенных в «main»).

2. Вместо команды «cpp» - трансляцию-сборку надо было выполнять при помощи «c++».

/*  
  file:  rpn.yy
  title: Reverse polish notation calculator rules. 
*/

%{
     #define YYSTYPE double
     #include <math.h>
     #include <stdio.h>
%}

%token NUM 

%% /* Grammar rules and actions follow */


     input:    /* empty */
             | input line
     ; 

     line:     '\n'
             | exp '\n'  { printf ("\t%.10g\n", $1); }
     ;

     exp:      NUM             { $$ = $1;         }
             | exp exp '+'     { $$ = $1 + $2;    }
             | exp exp '-'     { $$ = $1 - $2;    }
             | exp exp '*'     { $$ = $1 * $2;    }
             | exp exp '/'     { $$ = $1 / $2;    }
           /* Exponentiation */
             | exp exp '^'     { $$ = pow ($1, $2); }
           /* Unary minus    */
             | exp 'n'         { $$ = -$1;        }
     ;
%%

Файл на языке Си с функциями main и yylex

 /*  
   file:  rpn.cc
   title: Tokenizer functions 
           yylex   -- функция разбиения входного потока на токены. 
           yyerror -- функция обработки ошибок
           main    -- главная функция
 */
 #include <stdio.h>
 #include <ctype.h>
 #include "rpn.tab.hh"
 int yyparse(void); 
 
 int yyerror (const char *s)  /* Called by yyparse on error */
 {
     printf ("%s\n", s);
 }
 
 /* Lexical analyzer returns a double floating point
     number on the stack and the token NUM, or the ASCII
     character read if not a number.  Skips all blanks
     and tabs, returns 0 for EOF. */
 int yylex (void)
 {
     int c;
 
     /* skip white space  */
     while ((c = getchar ()) == ' ' || c == '\t')
       ;
     /* process numbers   */
     if (c == '.' || isdigit (c))
     {
         ungetc (c, stdin);
         scanf ("%lf", &yylval);
         return NUM;
      }
      /* return end-of-file  */
      if (c == EOF)
         return 0;
      /* return single chars */
      return c;
 }
 
 int main (void)
 {
     return yyparse ();
 }

Команды компиляции

$ bison -d rpn.yy      # -> produce files rpn.tab.cc  and rpn.tab.hh
$ gcc rpn.tab.cc rpn.cc -lm -o rpn #  produce executable file rpn


Пример использования калькулятора:

$
./rpn
1 2 +
        3
1 2 3 * + 100 +
        107
<Ctrl+D>
$