"Fossies" - the Fresh Open Source Software Archive

Member "wcalc-2.5/src/common/parser.y" (29 Dec 2014, 17391 Bytes) of package /linux/privat/wcalc-2.5.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Bison source code syntax highlighting (style: standard) with prefixed line numbers. Alternatively you can here view or download the uninterpreted source code file. See also the latest Fossies "Diffs" side-by-side code changes report for "parser.y": 2.4.1_vs_2.5.

    1 /*%pure-parser */
    2 /* this may be a bison-only thing... */
    3 /*%error-verbose*/
    4 %{
    5 /*#define REENTRANT_PARSER */
    6 #ifdef HAVE_CONFIG_H
    7 #include "config.h"
    8 #endif
    9 #if ! defined(HAVE_CONFIG_H) || HAVE_STRING_H
   10 # include <string.h>
   11 #else
   12 # if !HAVE_STRCHR
   13 #  define strchr index
   14 #  define strrchr rindex
   15 # endif
   16 char *strchr (), *strrchr ();
   17 #endif
   18 
   19 #include <stdio.h>
   20 #include <stdlib.h>
   21 
   22 #include "number.h"
   23 
   24 #include <stdarg.h>
   25 #include <math.h>
   26 #include <float.h>
   27 #include <unistd.h> /* for isatty() */
   28 #include "calculator.h"
   29 #include "variables.h"
   30 #include "files.h"
   31 #include "conversion.h"
   32 #include "number_formatting.h"
   33 #include "output.h"
   34 
   35 /* Based on the headstart code by Shawn Ostermann
   36 * modified by Kyle Wheeler
   37 */
   38 
   39 /* include debugging code, in case we want it */
   40 #define YYDEBUG 1
   41 
   42 /* to make it stop complaining about undeclared functions */
   43 int yylex(void);
   44 int yyerror(char *error_string, ...);
   45 
   46 int lines = 1;
   47 int synerrors = 0;
   48 short scanerror = 0;
   49 char * errstring = NULL;
   50 int errloc = -1;
   51 int show_line_numbers = 0;
   52 
   53 %}
   54 
   55 
   56 %union  { /* the types that we use in the tokens */
   57 enum functions function;
   58 enum operations operation;
   59 Number number;
   60 long integer;
   61 enum commands cmd;
   62 char * variable;
   63 char character;
   64 struct conv_req conver;
   65 }
   66 
   67 %token DEC_CMD OCT_CMD HEX_CMD BIN_CMD DISPLAY_PREFS_CMD
   68 %token RADIAN_CMD REMEMBER_CMD LISTVAR_CMD STORE_CMD CMOD_CMD
   69 %token PRINT_HELP_CMD PREFIX_CMD INT_CMD VERBOSE_CMD DELIM_CMD
   70 %token <variable> ASSERT_CMD
   71 %token <integer> ENG_CMD HLIMIT_CMD ROUNDING_INDICATION_CMD
   72 %token <integer> PRECISION_CMD BITS_CMD BASE_CMD GUARD_CMD
   73 %token <conver> CONVERT_CMD
   74 
   75 %token EOLN OPEN_PARENTHESES CLOSE_PARENTHESES OPEN_BRACE
   76 %token CLOSE_BRACE OPEN_BRACKET CLOSE_BRACKET
   77 %token WPLUS WMINUS WMULT WDIV WMOD EQUALS_SIGN WPOW WEXP WSQR
   78 %token WOR WAND WEQUAL WNEQUAL WGT WLT WGEQ WLEQ
   79 %token WLSHFT WRSHFT WBOR WBAND WBXOR
   80 
   81 %token WBNOT WNOT WLOG WLN WROUND WABS WSQRT WCEIL WFLOOR WCBRT WLOGTWO WBANG
   82 %token WSIN WCOS WTAN WASIN WACOS WATAN WSINH WCOSH WTANH WASINH WACOSH WATANH
   83 %token WCOT WACOT WCOTH WACOTH WRAND WIRAND WFACT WCOMP WSEC WCSC WASEC WACSC
   84 %token WSECH WCSCH WASECH WACSCH WEINT WGAMMA WLNGAMMA WZETA WSINC
   85 
   86 %token <number> NUMBER
   87 %token <variable> VARIABLE STRING OPEN_CMD SAVE_CMD ASSIGNMENT
   88 %token <character> IDSEP_CMD DSEP_CMD ITSEP_CMD TSEP_CMD
   89 
   90 %type <number> exp exp_l2 exp_l3
   91 %type <number> oval capsule parenthated
   92 %type <integer> sign
   93 %type <cmd> command
   94 %type <function> func
   95 %type <variable> optionalstring
   96 
   97 %left WAND WOR WBAND WBOR
   98 %left WEQUAL WNEQUAL WGT WLT WGEQ WLEQ
   99 %left WMINUS WPLUS
  100 %left WMULT WDIV WMOD WLSHFT WRSHFT
  101 %right WBANG WSQR
  102 %left WNOT WBNOT WNEG
  103 %right WPOW
  104 
  105 %expect 1560
  106 
  107 %%  /* beginning of the parsing rules   */
  108 
  109 input : lines
  110 |
  111 ;
  112 
  113 lines : oneline
  114 | oneline lines
  115 ;
  116 
  117 oneline : exp eoln
  118 {
  119     extern int line_is_a_command;
  120 
  121     if (scanerror) {
  122         scanerror = synerrors = 0;
  123     } else {
  124         if (! synerrors && ! yynerrs) {
  125             set_prettyanswer($1);
  126             num_set(last_answer,$1);
  127         } else {
  128             synerrors = 0;
  129             report_error("Too many errors.");
  130         }
  131     }
  132     num_free($1);
  133     compute = 1;
  134     line_is_a_command = 0;
  135 }
  136 | assignment eoln {
  137     extern int line_is_a_command;
  138 
  139     compute = 1;
  140     line_is_a_command = 0;
  141 }
  142 | command eoln {
  143     extern int line_is_a_command;
  144 
  145     switch ($1) {
  146         case redisplay:
  147             if (! synerrors) {
  148                 set_prettyanswer(last_answer);
  149             } else {
  150                 synerrors = 0;
  151                 report_error("Too many errors.");
  152             }
  153                 break;
  154         case nothing: break;
  155     }
  156     compute = 1;
  157     line_is_a_command = 0;
  158 }
  159 | eoln  /* blank line */
  160 {
  161     extern int line_is_a_command;
  162 
  163     if (scanerror) {
  164         scanerror = synerrors = 0;
  165     }
  166     compute = 1;
  167     line_is_a_command = 0;
  168 }
  169 | error eoln {
  170     extern int line_is_a_command;
  171 
  172     /* there is the possibility of lost memory here,
  173      * because "error" has no data type
  174      * (and because I'm passing around *actual* Number's
  175      * rather than pointers to them) */
  176     /* report_error("3 Error in scanner halts parser."); */
  177     compute = 1;
  178     line_is_a_command = 0;
  179 }
  180 /* if we got an error on the line */
  181 ;
  182 
  183 eoln : EOLN { ++lines; }
  184 ;
  185 
  186 command : HEX_CMD {
  187     $$ = isatty(0)?redisplay:nothing;
  188     conf.output_format = HEXADECIMAL_FORMAT;
  189         display_output_format(HEXADECIMAL_FORMAT); }
  190 | OCT_CMD {
  191     $$ = isatty(0)?redisplay:nothing;
  192     conf.output_format = OCTAL_FORMAT;
  193         display_output_format(OCTAL_FORMAT); }
  194 | BIN_CMD {
  195     $$ = isatty(0)?redisplay:nothing;
  196     conf.output_format = BINARY_FORMAT;
  197         display_output_format(BINARY_FORMAT); }
  198 | DEC_CMD {
  199     $$ = isatty(0)?redisplay:nothing;
  200     conf.output_format = DECIMAL_FORMAT;
  201         display_output_format(DECIMAL_FORMAT); }
  202 | ASSERT_CMD {
  203     if (strcmp($1, pretty_answer)) {
  204                 fprintf(stderr, "Assertion on line %u:\n", lines);
  205         fprintf(stderr, "   Pretty Answer is: '%s'\n", pretty_answer);
  206         fprintf(stderr, "...should have been: '%s'\n", $1);
  207         exit(EXIT_FAILURE);
  208     }
  209     free($1);
  210 }
  211 | DSEP_CMD {
  212     $$ = nothing;
  213     if (conf.thou_delimiter != $1) {
  214             conf.dec_delimiter = $1;
  215         display_status("%c is now the decimal separator.", $1);
  216     } else {
  217             extern int column;
  218             column --;
  219         report_error("%c cannot be the decimal separator. It is the thousands separator.", $1);
  220     }}
  221 | IDSEP_CMD {
  222     $$ = nothing;
  223     if (conf.in_thou_delimiter != $1 && (conf.in_thou_delimiter != 0 || conf.thou_delimiter != $1)) {
  224         conf.in_dec_delimiter = $1;
  225         display_status("%c is now the decimal separator for input.\n", $1);
  226     } else {
  227             extern int column;
  228             column --;
  229         report_error("%c cannot be the decimal separator. It is the thousands separator.\n", $1);
  230     }}
  231 | TSEP_CMD {
  232     $$ = nothing;
  233     if (conf.dec_delimiter != $1) {
  234         conf.thou_delimiter = $1;
  235         display_status("%c is now the thousands separator.\n", $1);
  236     } else if (standard_output) {
  237             extern int column;
  238             column --;
  239         report_error("%c cannot be the thousands separator. It is the decimal separator.\n", $1);
  240     }}
  241 | ITSEP_CMD {
  242     $$ = nothing;
  243     if (conf.in_dec_delimiter != $1 && (conf.in_dec_delimiter != 0 || conf.dec_delimiter != $1)) {
  244         conf.in_thou_delimiter = $1;
  245         display_status("%c is now the thousands separator for input.\n", $1);
  246     } else  {
  247             extern int column;
  248             column --;
  249         report_error("%c cannot be the thousands separator. It is the decimal separator.\n", $1);
  250     }
  251 }
  252 | DELIM_CMD {
  253     $$ = nothing;
  254     conf.print_commas = ! conf.print_commas;
  255     display_status("Will %sshow separators when printing large numbers.\n",conf.print_commas?"":"not ");
  256 }
  257 | INT_CMD {
  258     $$ = nothing;
  259     conf.print_ints = ! conf.print_ints;
  260     display_status("Will %suse abbreviations for large integers.\n",conf.print_ints?"not ":"");
  261 }
  262 | VERBOSE_CMD
  263 {
  264     $$ = nothing;
  265     conf.verbose = ! conf.verbose;
  266     display_status("Will %secho the lines to be evaluated.\n",conf.verbose?"":"not ");
  267 }
  268 | DISPLAY_PREFS_CMD {
  269         display_prefs();
  270     $$ = nothing;
  271 }
  272 | RADIAN_CMD {
  273     $$ = nothing;
  274     conf.use_radians = ! conf.use_radians;
  275     display_status("Now Using %s\n", conf.use_radians?"Radians":"Degrees");}
  276 | GUARD_CMD {
  277     $$ = nothing;
  278         switch ($1) {
  279             case 0: conf.precision_guard = 0; break;
  280             case 1: conf.precision_guard = 1; break;
  281             case -1: conf.precision_guard = ! conf.precision_guard; break;
  282         }
  283     display_status("Now %sUsing Conservative Precision\n", conf.precision_guard?"":"Not ");}
  284 | PRECISION_CMD {
  285     $$ = isatty(0)?redisplay:nothing;
  286     conf.precision = $1;
  287         if (conf.precision == -1) {
  288             display_status("Precision = auto");
  289         } else {
  290             display_status("Precision = %i", conf.precision);
  291         } }
  292 | HLIMIT_CMD {
  293     $$ = nothing;
  294     if ($1) {
  295         conf.history_limit = 1;
  296         conf.history_limit_len = $1;
  297     } else {
  298         conf.history_limit = 0;
  299         conf.history_limit_len = 0;
  300     }
  301 }
  302 | LISTVAR_CMD {
  303     printvariables();
  304     $$ = nothing;
  305 }
  306 | ENG_CMD {
  307     if ($1 < 0) {
  308         switch (conf.engineering) {
  309             case always: conf.engineering = never; break;
  310             case never: conf.engineering = automatic; break;
  311             case automatic: conf.engineering = always; break;
  312         }
  313     } else {
  314         switch($1) {
  315             case 1: conf.engineering = automatic; break;
  316             case 2: conf.engineering = always; break;
  317             case 3: conf.engineering = never; break;
  318         }
  319     }
  320     display_status("Engineering notation is %s\n",(conf.engineering==always)?"always used":(conf.engineering==never)?"never used":"used if convenient");
  321     $$ = isatty(0)?redisplay:nothing;
  322 }
  323 | ROUNDING_INDICATION_CMD {
  324     $$ = nothing;
  325     if ($1 != -1)
  326         conf.rounding_indication = $1;
  327     else {
  328         conf.rounding_indication += 1;
  329         conf.rounding_indication %= 3;
  330     }
  331     display_status("Will display %s rounding indication",
  332         (conf.rounding_indication==NO_ROUNDING_INDICATION)?"no":
  333                 ((conf.rounding_indication==SIMPLE_ROUNDING_INDICATION)?"simple":"significant figure"));
  334 }
  335 | PREFIX_CMD {
  336     $$ = nothing;
  337     conf.print_prefixes = ! conf.print_prefixes;
  338     display_status("Will %sprint number prefixes\n",conf.print_prefixes?"":"not ");
  339 }
  340 | REMEMBER_CMD {
  341     $$ = nothing;
  342     conf.remember_errors = ! conf.remember_errors;
  343     display_status("Statements that produce errors are %s.\n",conf.remember_errors?"recorded":"forgotten");
  344 }
  345 | PRINT_HELP_CMD {
  346     $$ = nothing;
  347     display_interactive_help();
  348 }
  349 | OPEN_CMD {
  350     extern char* open_file;
  351     int i;
  352     unsigned int len = strlen($1)+1;
  353     open_file = malloc(len);
  354         strncpy(open_file, $1, len);
  355     /* strip trailing spaces */
  356     for (i=strlen(open_file)-1;i>=0;i--) {
  357         if (open_file[i] != ' ') break;
  358         open_file[i] = 0;
  359     }
  360     if (strlen(open_file) == 0) {
  361         free(open_file);
  362         open_file = NULL;
  363         report_error("Please specify a file name to open.");
  364     }
  365     $$ = nothing;
  366 }
  367 | SAVE_CMD {
  368     int retval;
  369     retval = saveState($1);
  370     if (retval) {
  371         report_error("Could not save file. (%s)", (char*)strerror(retval));
  372     }
  373     $$ = nothing;
  374 }
  375 | BITS_CMD {
  376     if ($1 < NUM_PREC_MIN) {
  377         report_error("Minimum precision is %lu (you asked for %lu).\n", (unsigned long)NUM_PREC_MIN, $1);
  378     } else if ($1 > NUM_PREC_MAX) {
  379         report_error("Maximum precision is %lu (you asked for %lu).\n", (unsigned long)NUM_PREC_MAX, $1);
  380     } else {
  381         num_set_default_prec($1);
  382     }
  383     $$ = nothing;
  384 }
  385 | CONVERT_CMD
  386 {
  387     int category = identify_units($1.u1,$1.u2);
  388     switch (category) {
  389         case -1:
  390             report_error("Units must be in the same category.");
  391             break;
  392         case -2:
  393             report_error("Units provided are not recognized.");
  394             break;
  395         case -3:
  396             report_error("First unit provided was not recognized (%s).", $1.u1);
  397             break;
  398         case -4:
  399             report_error("Second unit provided was not recognized (%s).", $1.u2);
  400             break;
  401         default:
  402             uber_conversion(last_answer,category,unit_id(category,$1.u1),unit_id(category,$1.u2),last_answer);
  403     }
  404     free($1.u1);
  405     free($1.u2);
  406     $$ = redisplay;
  407 }
  408 | BASE_CMD
  409 {
  410     if ($1 >= 2 && $1 <= 36) {
  411         char * str, junk;
  412         str = num_to_str_complex(last_answer, $1, conf.engineering, -1, conf.print_prefixes, &junk);
  413         display_status("base %i: %s\n",$1,str);
  414     } else {
  415         report_error("Base must be greater than one and less than 37.");
  416     }
  417     $$ = nothing;
  418 }
  419 | STORE_CMD VARIABLE
  420 {
  421     int retval = storeVar($2);
  422     if (retval == 0) {
  423         display_status("successfully stored %s\n",$2);
  424     } else {
  425         report_error("Failure to store variable!");
  426     }
  427     free($2);
  428 }
  429 | CMOD_CMD
  430 {
  431     $$ = nothing;
  432     conf.c_style_mod = ! conf.c_style_mod;
  433     display_status("The mod (%%) operation will %sbehave like it does in the C programming language.\n",conf.c_style_mod?"":"not ");
  434 }
  435 ;
  436 
  437 optionalstring : STRING {
  438                $$ = $1;
  439                }
  440                | {
  441                $$ = NULL;
  442                }
  443                ;
  444 
  445 assignment : ASSIGNMENT exp optionalstring
  446 {
  447     if (compute && ! scanerror) {
  448         /* if standard_error, q is reserved */
  449         if (standard_output && !strcmp($1,"q")) {
  450             report_error("q cannot be assigned a value. q is used to exit.");
  451         } else {
  452             if (putval($1,$2,$3) == 0) {
  453                                 display_val($1);
  454             } else {
  455                 report_error("There was a problem assigning the value.");
  456             }
  457         }
  458         num_free($2);
  459     } else {
  460         scanerror = 0;
  461         report_error("Scanner error halts parser.");
  462     }
  463     free($1);
  464     if ($3 != NULL) {
  465         free($3);
  466     }
  467 }
  468 | ASSIGNMENT STRING optionalstring
  469 {
  470     if (compute && ! scanerror) {
  471         if (standard_output && !strcmp($1,"q")) {
  472             report_error("q cannot be assigned an expression. q is used to exit.");
  473         } else {
  474             if (putexp($1,$2,$3) == 0) {
  475                                 display_val($1);
  476             } else {
  477                 report_error("There was a problem assigning the expression.");
  478             }
  479         }
  480     } else {
  481         scanerror = 0;
  482         report_error("Scanner error halts parser.");
  483     }
  484     free($1);
  485     free($2);
  486     if ($3 != NULL) {
  487         free($3);
  488     }
  489 }
  490 | NUMBER EQUALS_SIGN exp optionalstring
  491 {
  492     report_error("Constants cannot be assigned to other values.");
  493     num_free($3);
  494     if ($4 != NULL) {
  495         free($4);
  496     }
  497 }
  498 | NUMBER EQUALS_SIGN STRING optionalstring
  499 {
  500     report_error("Constants cannot be assigned to other values.");
  501     free($3);
  502     if ($4 != NULL) {
  503         free($4);
  504     }
  505 }
  506 ;
  507 
  508 exp : exp WMINUS exp { num_init($$); simple_exp($$, $1, wminus, $3); num_free($1); num_free($3); }
  509 | exp WPLUS exp { num_init($$); simple_exp($$, $1, wplus, $3); num_free($1); num_free($3); }
  510 | exp WAND exp { num_init($$); simple_exp($$, $1, wand, $3); num_free($1); num_free($3); }
  511 | exp WOR exp { num_init($$); simple_exp($$, $1, wor, $3); num_free($1); num_free($3); }
  512 | exp WBOR exp { num_init($$); simple_exp($$, $1, wbor, $3); num_free($1); num_free($3); }
  513 | exp WBXOR exp { num_init($$); simple_exp($$, $1, wbxor, $3); num_free($1); num_free($3); }
  514 | exp WBAND exp { num_init($$); simple_exp($$, $1, wband, $3); num_free($1); num_free($3); }
  515 | exp WEQUAL exp { num_init($$); simple_exp($$, $1, wequal, $3); num_free($1); num_free($3); }
  516 | exp WNEQUAL exp { num_init($$); simple_exp($$, $1, wnequal, $3); num_free($1); num_free($3); }
  517 | exp WGT exp { num_init($$); simple_exp($$, $1, wgt, $3); num_free($1); num_free($3); }
  518 | exp WLT exp { num_init($$); simple_exp($$, $1, wlt, $3); num_free($1); num_free($3); }
  519 | exp WGEQ exp { num_init($$); simple_exp($$, $1, wgeq, $3); num_free($1); num_free($3); }
  520 | exp WLEQ exp { num_init($$); simple_exp($$, $1, wleq, $3); num_free($1); num_free($3); }
  521 | exp WLSHFT exp { num_init($$); simple_exp($$, $1, wlshft, $3); num_free($1); num_free($3); }
  522 | exp WRSHFT exp { num_init($$); simple_exp($$, $1, wrshft, $3); num_free($1); num_free($3); }
  523 | exp WMULT exp { num_init($$); simple_exp($$, $1, wmult, $3); num_free($1); num_free($3); }
  524 | exp WDIV exp { num_init($$); simple_exp($$, $1, wdiv, $3); num_free($1); num_free($3); }
  525 | exp WMOD exp { num_init($$); simple_exp($$, $1, wmod, $3); num_free($1); num_free($3); }
  526 | exp_l2
  527 ;
  528 
  529 func : WSIN { $$ = wsin; }
  530 | WCOS { $$ = wcos; }
  531 | WTAN { $$ = wtan; }
  532 | WCOT { $$ = wcot; }
  533 | WSEC { $$ = wsec; }
  534 | WCSC { $$ = wcsc; }
  535 | WASIN { $$ = wasin; }
  536 | WACOS { $$ = wacos; }
  537 | WATAN { $$ = watan; }
  538 | WACOT { $$ = wacot; }
  539 | WASEC { $$ = wasec; }
  540 | WACSC { $$ = wacsc; }
  541 | WSINH { $$ = wsinh; }
  542 | WCOSH { $$ = wcosh; }
  543 | WTANH { $$ = wtanh; }
  544 | WCOTH { $$ = wcoth; }
  545 | WSECH { $$ = wsech; }
  546 | WCSCH { $$ = wcsch; }
  547 | WASINH { $$ = wasinh; }
  548 | WACOSH { $$ = wacosh; }
  549 | WATANH { $$ = watanh; }
  550 | WACOTH { $$ = wacoth; }
  551 | WASECH { $$ = wasech; }
  552 | WACSCH { $$ = wacsch; }
  553 | WLOG { $$ = wlog; }
  554 | WLOGTWO { $$ = wlogtwo; }
  555 | WLN { $$ = wln; }
  556 | WROUND { $$ = wround; }
  557 | WABS { $$ = wabs; }
  558 | WSQRT { $$ = wsqrt; }
  559 | WEXP { $$ = wexp; }
  560 | WFLOOR { $$ = wfloor; }
  561 | WCEIL { $$ = wceil; }
  562 | WCBRT { $$ = wcbrt; }
  563 | WRAND { $$ = wrand; }
  564 | WIRAND { $$ = wirand; }
  565 | WBNOT { $$ = wbnot; }
  566 | WNOT { $$ = wnot; }
  567 | WFACT { $$ = wfact; }
  568 | WCOMP { $$ = wcomp; }
  569 | WEINT { $$ = weint; }
  570 | WGAMMA { $$ = wgamma; }
  571 | WLNGAMMA { $$ = wlngamma; }
  572 | WZETA { $$ = wzeta; }
  573 | WSINC { $$ = wsinc; }
  574 ;
  575 
  576 nullexp : OPEN_PARENTHESES CLOSE_PARENTHESES
  577 | OPEN_BRACE CLOSE_BRACE
  578 | OPEN_BRACKET CLOSE_BRACKET
  579 ;
  580 
  581 sign : WMINUS { $$ = -1; }
  582 | WPLUS { $$ = 1; }
  583 | { $$ = 1; }
  584 ;
  585 
  586 exp_l2 : exp_l3
  587 | sign exp_l2 oval { num_init($$);
  588              num_mul($2,$2,$3);
  589              num_mul_si($$,$2,$1);
  590              num_free($2);
  591              num_free($3); }
  592 ;
  593 
  594 oval : exp_l3 oval {
  595      num_init_set($$,$1);
  596      num_free($1);
  597      num_free($2);
  598 }
  599 | { num_init_set_ui($$,1); }
  600 ;
  601 
  602 exp_l3 : capsule oval { num_init($$);
  603                         simple_exp($$,$1,wmult,$2);
  604             num_free($1);
  605             num_free($2);}
  606 | capsule WPOW sign exp_l3 oval { num_init($$);
  607                   num_mul_si($4,$4,$3);
  608                   num_pow($1,$1,$4);
  609                   num_mul($$,$1,$5);
  610                   num_free($1);
  611                   num_free($4);
  612                   num_free($5);}
  613 ;
  614 
  615 parenthated: OPEN_PARENTHESES exp CLOSE_PARENTHESES
  616            { num_init($$); num_set($$,$2); num_free($2); }
  617            | OPEN_BRACE exp CLOSE_BRACE
  618            { num_init($$); num_set($$,$2); num_free($2); }
  619            | OPEN_BRACKET exp CLOSE_BRACKET
  620            { num_init($$); num_set($$,$2); num_free($2); }
  621            | nullexp { num_init_set_ui($$,0); }
  622            ;
  623 
  624 capsule: parenthated
  625        { num_init($$); num_set($$,$1); num_free($1); }
  626        | NUMBER
  627        | capsule WBANG
  628        {
  629        num_init($$);
  630        num_factorial($$,num_get_ui($1));
  631        num_free($1);
  632        }
  633        | capsule WSQR { num_init($$); num_sqr($$,$1); num_free($1); }
  634        | func parenthated %prec WMULT
  635        {
  636        num_init($$);
  637        uber_function($$,$1,$2);
  638        num_free($2);
  639        }
  640        | func sign capsule %prec WEQUAL
  641        {
  642        num_init($$);
  643        num_mul_si($3,$3,$2);
  644        uber_function($$,$1,$3);
  645        num_free($3);
  646        }
  647 ;
  648 
  649 %%
  650 
  651 int
  652 yyerror(char *error_string, ...) {
  653     va_list ap;
  654     char error[1000];
  655 
  656     ++synerrors;
  657 
  658     va_start(ap,error_string);
  659     vsnprintf(error,1000,error_string,ap);
  660     va_end(ap);
  661 
  662     report_error(error);
  663     return 0;
  664 }