home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / bc-1.03-src.tgz / tar.out / fsf / bc / bc.y < prev    next >
Text File  |  1996-09-28  |  15KB  |  616 lines

  1. %{
  2. /* bc.y: The grammar for a POSIX compatable bc processor with some
  3.          extensions to the language. */
  4.  
  5. /*  This file is part of bc written for MINIX.
  6.     Copyright (C) 1991, 1992, 1993, 1994 Free Software Foundation, Inc.
  7.  
  8.     This program is free software; you can redistribute it and/or modify
  9.     it under the terms of the GNU General Public License as published by
  10.     the Free Software Foundation; either version 2 of the License , or
  11.     (at your option) any later version.
  12.  
  13.     This program is distributed in the hope that it will be useful,
  14.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16.     GNU General Public License for more details.
  17.  
  18.     You should have received a copy of the GNU General Public License
  19.     along with this program; see the file COPYING.  If not, write to
  20.     the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  
  22.     You may contact the author by:
  23.        e-mail:  phil@cs.wwu.edu
  24.       us-mail:  Philip A. Nelson
  25.                 Computer Science Department, 9062
  26.                 Western Washington University
  27.                 Bellingham, WA 98226-9062
  28.        
  29. *************************************************************************/
  30.  
  31. #include "bcdefs.h"
  32. #include "global.h"
  33. #include "proto.h"
  34. %}
  35.  
  36. %start program
  37.  
  38. %union {
  39.     char     *s_value;
  40.     char      c_value;
  41.     int      i_value;
  42.     arg_list *a_value;
  43.        }
  44.  
  45. /* Extensions over POSIX bc.
  46.    a) NAME was LETTER.  This grammer allows longer names.
  47.       Single letter names will still work.
  48.    b) Relational_expression allowed only one comparison.
  49.       This grammar has added boolean expressions with
  50.       && (and) || (or) and ! (not) and allowed all of them in
  51.       full expressions.
  52.    c) Added an else to the if.
  53.    d) Call by variable array parameters
  54.    e) read() procedure that reads a number under program control from stdin.
  55.    f) halt statement that halts the the program under program control.  It
  56.       is an executed statement.
  57.    g) continue statement for for loops.
  58.    h) optional expressions in the for loop.
  59.    i) print statement to print multiple numbers per line.
  60.    j) warranty statement to print an extended warranty notice.
  61.    j) limits statement to print the processor's limits.
  62. */
  63.  
  64. %token <i_value> NEWLINE AND OR NOT
  65. %token <s_value> STRING NAME NUMBER
  66. /*     '-', '+' are tokens themselves        */
  67. %token <c_value> MUL_OP
  68. /*     '*', '/', '%'                 */
  69. %token <c_value> ASSIGN_OP
  70. /*     '=', '+=',  '-=', '*=', '/=', '%=', '^=' */
  71. %token <s_value> REL_OP
  72. /*     '==', '<=', '>=', '!=', '<', '>'     */
  73. %token <c_value> INCR_DECR
  74. /*     '++', '--'                 */
  75. %token <i_value> Define    Break    Quit    Length
  76. /*     'define', 'break', 'quit', 'length'     */
  77. %token <i_value> Return    For    If    While    Sqrt   Else
  78. /*     'return', 'for', 'if', 'while', 'sqrt', 'else'     */
  79. %token <i_value> Scale    Ibase    Obase    Auto  Read
  80. /*     'scale', 'ibase', 'obase', 'auto', 'read'     */
  81. %token <i_value> Warranty, Halt, Last, Continue, Print, Limits
  82. /*     'warranty', 'halt', 'last', 'continue', 'print', 'limits'   */
  83.  
  84. /* Types of all other things. */
  85. %type <i_value> expression return_expression named_expression opt_expression
  86. %type <c_value> '+' '-' 
  87. %type <a_value> opt_parameter_list opt_auto_define_list define_list
  88. %type <a_value> opt_argument_list argument_list
  89. %type <i_value> program input_item semicolon_list statement_list
  90. %type <i_value> statement function   statement_or_error
  91.  
  92. /* precedence */
  93. %left OR
  94. %left AND
  95. %nonassoc NOT
  96. %left REL_OP
  97. %right ASSIGN_OP
  98. %left '+' '-'
  99. %left MUL_OP
  100. %right '^'
  101. %nonassoc UNARY_MINUS
  102. %nonassoc INCR_DECR
  103.  
  104. %%
  105. program            : /* empty */
  106.                 {
  107.                   $$ = 0;
  108.                   if (interactive)
  109.                 {
  110.                   printf ("%s\n", BC_VERSION);
  111.                   welcome ();
  112.                 }
  113.                 }
  114.             | program input_item
  115.             ;
  116. input_item        : semicolon_list NEWLINE
  117.                 { run_code (); }
  118.             | function
  119.                 { run_code (); }
  120.             | error NEWLINE
  121.                 {
  122.                   yyerrok;
  123.                   init_gen ();
  124.                 }
  125.             ;
  126. semicolon_list        : /* empty */
  127.                 { $$ = 0; }
  128.             | statement_or_error
  129.             | semicolon_list ';' statement_or_error
  130.             | semicolon_list ';'
  131.             ;
  132. statement_list        : /* empty */
  133.                 { $$ = 0; }
  134.             | statement_or_error
  135.             | statement_list NEWLINE
  136.             | statement_list NEWLINE statement_or_error
  137.             | statement_list ';'
  138.             | statement_list ';' statement
  139.             ;
  140. statement_or_error    : statement
  141.               | error statement
  142.                 { $$ = $2; }
  143.             ;
  144. statement         : Warranty
  145.                 { warranty (""); }
  146.             | Limits
  147.                 { limits (); }
  148.             | expression
  149.                 {
  150.                   if ($1 & 2)
  151.                 warn ("comparison in expression");
  152.                   if ($1 & 1)
  153.                 generate ("W");
  154.                   else 
  155.                 generate ("p");
  156.                 }
  157.             | STRING
  158.                 {
  159.                   $$ = 0;
  160.                   generate ("w");
  161.                   generate ($1);
  162.                   free ($1);
  163.                 }
  164.             | Break
  165.                 {
  166.                   if (break_label == 0)
  167.                 yyerror ("Break outside a for/while");
  168.                   else
  169.                 {
  170.                   sprintf (genstr, "J%1d:", break_label);
  171.                   generate (genstr);
  172.                 }
  173.                 }
  174.             | Continue
  175.                 {
  176.                   warn ("Continue statement");
  177.                   if (continue_label == 0)
  178.                 yyerror ("Continue outside a for");
  179.                   else
  180.                 {
  181.                   sprintf (genstr, "J%1d:", continue_label);
  182.                   generate (genstr);
  183.                 }
  184.                 }
  185.             | Quit
  186.                 { exit (0); }
  187.             | Halt
  188.                 { generate ("h"); }
  189.             | Return
  190.                 { generate ("0R"); }
  191.             | Return '(' return_expression ')'
  192.                 { generate ("R"); }
  193.             | For 
  194.                 {
  195.                   $1 = break_label; 
  196.                   break_label = next_label++;
  197.                 }
  198.               '(' opt_expression ';'
  199.                 {
  200.                   if ($4 > 1)
  201.                 warn ("Comparison in first for expression");
  202.                   $4 = next_label++;
  203.                   if ($4 < 0)
  204.                 sprintf (genstr, "N%1d:", $4);
  205.                   else
  206.                 sprintf (genstr, "pN%1d:", $4);
  207.                   generate (genstr);
  208.                 }
  209.               opt_expression ';'
  210.                 {
  211.                   if ($7 < 0) generate ("1");
  212.                   $7 = next_label++;
  213.                   sprintf (genstr, "B%1d:J%1d:", $7, break_label);
  214.                   generate (genstr);
  215.                   $<i_value>$ = continue_label;
  216.                   continue_label = next_label++;
  217.                   sprintf (genstr, "N%1d:", continue_label);
  218.                   generate (genstr);
  219.                 }
  220.               opt_expression ')'
  221.                 {
  222.                   if ($10 > 1)
  223.                 warn ("Comparison in third for expression");
  224.                   if ($10 < 0)
  225.                 sprintf (genstr, "J%1d:N%1d:", $4, $7);
  226.                   else
  227.                 sprintf (genstr, "pJ%1d:N%1d:", $4, $7);
  228.                   generate (genstr);
  229.                 }
  230.               statement
  231.                 {
  232.                   sprintf (genstr, "J%1d:N%1d:",
  233.                        continue_label, break_label);
  234.                   generate (genstr);
  235.                   break_label = $1;
  236.                   continue_label = $<i_value>9;
  237.                 }
  238.             | If '(' expression ')' 
  239.                 {
  240.                   $3 = if_label;
  241.                   if_label = next_label++;
  242.                   sprintf (genstr, "Z%1d:", if_label);
  243.                   generate (genstr);
  244.                 }
  245.               statement  opt_else
  246.                 {
  247.                   sprintf (genstr, "N%1d:", if_label); 
  248.                   generate (genstr);
  249.                   if_label = $3;
  250.                 }
  251.             | While 
  252.                 {
  253.                   $1 = next_label++;
  254.                   sprintf (genstr, "N%1d:", $1);
  255.                   generate (genstr);
  256.                 }
  257.             '(' expression 
  258.                 {
  259.                   $4 = break_label; 
  260.                   break_label = next_label++;
  261.                   sprintf (genstr, "Z%1d:", break_label);
  262.                   generate (genstr);
  263.                 }
  264.             ')' statement
  265.                 {
  266.                   sprintf (genstr, "J%1d:N%1d:", $1, break_label);
  267.                   generate (genstr);
  268.                   break_label = $4;
  269.                 }
  270.             | '{' statement_list '}'
  271.                 { $$ = 0; }
  272.             | Print
  273.                 {  warn ("print statement"); }
  274.               print_list
  275.             ;
  276. print_list        : print_element
  277.              | print_element ',' print_list
  278.             ;
  279. print_element        : STRING
  280.                 {
  281.                   generate ("O");
  282.                   generate ($1);
  283.                   free ($1);
  284.                 }
  285.             | expression
  286.                 { generate ("P"); }
  287.              ;
  288. opt_else        : /* nothing */
  289.             | Else 
  290.                 {
  291.                   warn ("else clause in if statement");
  292.                   $1 = next_label++;
  293.                   sprintf (genstr, "J%d:N%1d:", $1, if_label); 
  294.                   generate (genstr);
  295.                   if_label = $1;
  296.                 }
  297.               statement
  298. function         : Define NAME '(' opt_parameter_list ')' '{'
  299.               NEWLINE opt_auto_define_list 
  300.                 {
  301.                   /* Check auto list against parameter list? */
  302.                   check_params ($4,$8);
  303.                   sprintf (genstr, "F%d,%s.%s[",
  304.                        lookup($2,FUNCTDEF), 
  305.                        arg_str ($4), arg_str ($8));
  306.                   generate (genstr);
  307.                   free_args ($4);
  308.                   free_args ($8);
  309.                   $1 = next_label;
  310.                   next_label = 1;
  311.                 }
  312.               statement_list /* NEWLINE */ '}'
  313.                 {
  314.                   generate ("0R]");
  315.                   next_label = $1;
  316.                 }
  317.             ;
  318. opt_parameter_list    : /* empty */ 
  319.                 { $$ = NULL; }
  320.             | define_list
  321.             ;
  322. opt_auto_define_list     : /* empty */ 
  323.                 { $$ = NULL; }
  324.             | Auto define_list NEWLINE
  325.                 { $$ = $2; } 
  326.             | Auto define_list ';'
  327.                 { $$ = $2; } 
  328.             ;
  329. define_list         : NAME
  330.                 { $$ = nextarg (NULL, lookup ($1,SIMPLE)); }
  331.             | NAME '[' ']'
  332.                 { $$ = nextarg (NULL, lookup ($1,ARRAY)); }
  333.             | define_list ',' NAME
  334.                 { $$ = nextarg ($1, lookup ($3,SIMPLE)); }
  335.             | define_list ',' NAME '[' ']'
  336.                 { $$ = nextarg ($1, lookup ($3,ARRAY)); }
  337.             ;
  338. opt_argument_list    : /* empty */
  339.                 { $$ = NULL; }
  340.             | argument_list
  341.             ;
  342. argument_list         : expression
  343.                 {
  344.                   if ($1 > 1) warn ("comparison in argument");
  345.                   $$ = nextarg (NULL,0);
  346.                 }
  347.             | NAME '[' ']'
  348.                 {
  349.                   sprintf (genstr, "K%d:", -lookup ($1,ARRAY));
  350.                   generate (genstr);
  351.                   $$ = nextarg (NULL,1);
  352.                 }
  353.             | argument_list ',' expression
  354.                 {
  355.                   if ($3 > 1) warn ("comparison in argument");
  356.                   $$ = nextarg ($1,0);
  357.                 }
  358.             | argument_list ',' NAME '[' ']'
  359.                 {
  360.                   sprintf (genstr, "K%d:", -lookup ($3,ARRAY));
  361.                   generate (genstr);
  362.                   $$ = nextarg ($1,1);
  363.                 }
  364.             ;
  365. opt_expression         : /* empty */
  366.                 {
  367.                   $$ = -1;
  368.                   warn ("Missing expression in for statement");
  369.                 }
  370.             | expression
  371.             ;
  372. return_expression    : /* empty */
  373.                 {
  374.                   $$ = 0;
  375.                   generate ("0");
  376.                 }
  377.             | expression
  378.                 {
  379.                   if ($1 > 1)
  380.                 warn ("comparison in return expresion");
  381.                 }
  382.             ;
  383. expression        :  named_expression ASSIGN_OP 
  384.                 {
  385.                   if ($2 != '=')
  386.                 {
  387.                   if ($1 < 0)
  388.                     sprintf (genstr, "DL%d:", -$1);
  389.                   else
  390.                     sprintf (genstr, "l%d:", $1);
  391.                   generate (genstr);
  392.                 }
  393.                 }
  394.               expression
  395.                 {
  396.                   if ($4 > 1) warn("comparison in assignment");
  397.                   if ($2 != '=')
  398.                 {
  399.                   sprintf (genstr, "%c", $2);
  400.                   generate (genstr);
  401.                 }
  402.                   if ($1 < 0)
  403.                 sprintf (genstr, "S%d:", -$1);
  404.                   else
  405.                 sprintf (genstr, "s%d:", $1);
  406.                   generate (genstr);
  407.                   $$ = 0;
  408.                 }
  409.             ;
  410.             | expression AND 
  411.                 {
  412.                   warn("&& operator");
  413.                   $2 = next_label++;
  414.                   sprintf (genstr, "DZ%d:p", $2);
  415.                   generate (genstr);
  416.                 }
  417.               expression
  418.                 {
  419.                   sprintf (genstr, "DZ%d:p1N%d:", $2, $2);
  420.                   generate (genstr);
  421.                   $$ = $1 | $4;
  422.                 }
  423.             | expression OR
  424.                 {
  425.                   warn("|| operator");
  426.                   $2 = next_label++;
  427.                   sprintf (genstr, "B%d:", $2);
  428.                   generate (genstr);
  429.                 }
  430.               expression
  431.                  {
  432.                   int tmplab;
  433.                   tmplab = next_label++;
  434.                   sprintf (genstr, "B%d:0J%d:N%d:1N%d:",
  435.                        $2, tmplab, $2, tmplab);
  436.                   generate (genstr);
  437.                   $$ = $1 | $4;
  438.                 }
  439.             | NOT expression
  440.                 {
  441.                   $$ = $2;
  442.                   warn("! operator");
  443.                   generate ("!");
  444.                 }
  445.             | expression REL_OP expression
  446.                 {
  447.                   $$ = 3;
  448.                   switch (*($2))
  449.                 {
  450.                 case '=':
  451.                   generate ("=");
  452.                   break;
  453.  
  454.                 case '!':
  455.                   generate ("#");
  456.                   break;
  457.  
  458.                 case '<':
  459.                   if ($2[1] == '=')
  460.                     generate ("{");
  461.                   else
  462.                     generate ("<");
  463.                   break;
  464.  
  465.                 case '>':
  466.                   if ($2[1] == '=')
  467.                     generate ("}");
  468.                   else
  469.                     generate (">");
  470.                   break;
  471.                 }
  472.                 }
  473.             | expression '+' expression
  474.                 {
  475.                   generate ("+");
  476.                   $$ = $1 | $3;
  477.                 }
  478.             | expression '-' expression
  479.                 {
  480.                   generate ("-");
  481.                   $$ = $1 | $3;
  482.                 }
  483.             | expression MUL_OP expression
  484.                 {
  485.                   genstr[0] = $2;
  486.                   genstr[1] = 0;
  487.                   generate (genstr);
  488.                   $$ = $1 | $3;
  489.                 }
  490.             | expression '^' expression
  491.                 {
  492.                   generate ("^");
  493.                   $$ = $1 | $3;
  494.                 }
  495.             | '-' expression  %prec UNARY_MINUS
  496.                 {
  497.                   generate ("n");
  498.                   $$ = $2;
  499.                 }
  500.             | named_expression
  501.                 {
  502.                   $$ = 1;
  503.                   if ($1 < 0)
  504.                 sprintf (genstr, "L%d:", -$1);
  505.                   else
  506.                 sprintf (genstr, "l%d:", $1);
  507.                   generate (genstr);
  508.                 }
  509.             | NUMBER
  510.                 {
  511.                   int len = strlen($1);
  512.                   $$ = 1;
  513.                   if (len == 1 && *$1 == '0')
  514.                 generate ("0");
  515.                   else if (len == 1 && *$1 == '1')
  516.                 generate ("1");
  517.                   else
  518.                 {
  519.                   generate ("K");
  520.                   generate ($1);
  521.                   generate (":");
  522.                 }
  523.                   free ($1);
  524.                 }
  525.             | '(' expression ')'
  526.                 { $$ = $2 | 1; }
  527.             | NAME '(' opt_argument_list ')'
  528.                 {
  529.                   $$ = 1;
  530.                   if ($3 != NULL)
  531.                 { 
  532.                   sprintf (genstr, "C%d,%s:",
  533.                        lookup ($1,FUNCT),
  534.                        call_str ($3));
  535.                   free_args ($3);
  536.                 }
  537.                   else
  538.                 {
  539.                   sprintf (genstr, "C%d:", lookup ($1,FUNCT));
  540.                 }
  541.                   generate (genstr);
  542.                 }
  543.             | INCR_DECR named_expression
  544.                 {
  545.                   $$ = 1;
  546.                   if ($2 < 0)
  547.                 {
  548.                   if ($1 == '+')
  549.                     sprintf (genstr, "DA%d:L%d:", -$2, -$2);
  550.                   else
  551.                     sprintf (genstr, "DM%d:L%d:", -$2, -$2);
  552.                 }
  553.                   else
  554.                 {
  555.                   if ($1 == '+')
  556.                     sprintf (genstr, "i%d:l%d:", $2, $2);
  557.                   else
  558.                     sprintf (genstr, "d%d:l%d:", $2, $2);
  559.                 }
  560.                   generate (genstr);
  561.                 }
  562.             | named_expression INCR_DECR
  563.                 {
  564.                   $$ = 1;
  565.                   if ($1 < 0)
  566.                 {
  567.                   sprintf (genstr, "DL%d:x", -$1);
  568.                   generate (genstr); 
  569.                   if ($2 == '+')
  570.                     sprintf (genstr, "A%d:", -$1);
  571.                   else
  572.                       sprintf (genstr, "M%d:", -$1);
  573.                 }
  574.                   else
  575.                 {
  576.                   sprintf (genstr, "l%d:", $1);
  577.                   generate (genstr);
  578.                   if ($2 == '+')
  579.                     sprintf (genstr, "i%d:", $1);
  580.                   else
  581.                     sprintf (genstr, "d%d:", $1);
  582.                 }
  583.                   generate (genstr);
  584.                 }
  585.             | Length '(' expression ')'
  586.                 { generate ("cL"); $$ = 1;}
  587.             | Sqrt '(' expression ')'
  588.                 { generate ("cR"); $$ = 1;}
  589.             | Scale '(' expression ')'
  590.                 { generate ("cS"); $$ = 1;}
  591.             | Read '(' ')'
  592.                 {
  593.                   warn ("read function");
  594.                   generate ("cI"); $$ = 1;
  595.                 }
  596.             ;
  597. named_expression    : NAME
  598.                 { $$ = lookup($1,SIMPLE); }
  599.             | NAME '[' expression ']'
  600.                 {
  601.                   if ($3 > 1) warn("comparison in subscript");
  602.                   $$ = lookup($1,ARRAY);
  603.                 }
  604.             | Ibase
  605.                 { $$ = 0; }
  606.             | Obase
  607.                 { $$ = 1; }
  608.             | Scale
  609.                 { $$ = 2; }
  610.             | Last
  611.                 { $$ = 3;
  612.                   warn ("Last variable");
  613.                 }
  614.             ;
  615. %%
  616.