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

Материал из Викиучебника — открытых книг для открытого мира
Содержимое удалено Содержимое добавлено
м <source> -> <syntaxhighlight> (phab:T237267)
Нет описания правки
Метки: через визуальный редактор с мобильного устройства из мобильной версии
 
Строка 6: Строка 6:
=== Файл с правилами <tt>bison</tt> ===
=== Файл с правилами <tt>bison</tt> ===
<code>
<code>

<!-- <syntaxhighlight lang="bison"> -->
/*
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; }
;
%%
<!-- </syntaxhighlight> -->
</code>
</code>


Строка 50: Строка 14:


1. В данный файл описания грамматики(сразу после "#include <stdio.h>" и до "%}") пришлось добавить прототипы ф-ий "yylex", "yyerror" (определенных в «main»):
1. В данный файл описания грамматики(сразу после "#include <stdio.h>" и до "%}") пришлось добавить прототипы ф-ий "yylex", "yyerror" (определенных в «main»):
int yylex (void);
int yyerror (const char *s);

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



Текущая версия от 19:59, 27 июля 2022

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


  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++».

Файл на языке Си с функциями 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>
$