/* $Id: gram.y,v 1.28 1998/10/20 13:20:47 cthulhu Exp $
*/
%{ 

     /* yacc grammar for spreadsheet expressions */

     /* Arlindo Oliveira */

#include "calc.hh"
extern Parser *act_parser;

/*
#include <stdio.h>
extern "C" {
#include "yydefines.h"
}
#include "yydefines.hh"
*/

char var_arg_cnt;
char cnt;

%}

%union {
    int ival;
    double fval;
    char *stval;
    short sval;
}



%type <fval> exp 
%type <fval> result
%type <fval> function
%type <stval> range
%type <stval> cell_id
%type <stval> string
%type <fval> float
%type <fval> date
%type <ival> integer
%type <stval> logicexp_int_cell, range_cell_value


%token <ival> L_INTEGER
%token <fval> L_FLOAT
%token <fval> L_DATE
%token <stval> L_CELL_ID 
%token L_COLON
%token L_DOUBLEQUOTE
%token L_COMMA
%token L_STRING
%token L_LEFTPAR
%token L_RIGHTPAR
%token L_EQUAL
%token L_GREATER
%token L_SMALLER
%token L_NEQUAL 
%token L_SMALLEREQ 
%token L_GREATEREQ 
%token L_AND
%token L_OR
%token L_NOT

%token L_ABS
%token L_INTF
%token L_SQRT
%token L_LOG
%token L_LN
%token L_PI
%token L_SIN
%token L_COS
%token L_TAN
%token L_ATAN2
%token L_ATAN
%token L_ASIN
%token L_ACOS
%token L_EXP
%token L_MOD
%token L_DAY
%token L_MONTH
%token L_ROUND
%token L_HOUR
%token L_MINUTE
%token L_SECOND

%token L_UPPER
%token L_LOWER
%token L_PROPER

%token L_SUMIF

%token L_SUM
%token L_AVG
%token L_COUNT
%token L_MIN
%token L_MAX
%token L_VLOOKUP
%token L_NPV
%token L_VAR
%token L_STD
%token L_IRR
%token L_HLOOKUP
%token L_DSUM
%token L_DAVG
%token L_DCOUNT
%token L_DMIN
%token L_DMAN
%token L_DVAR
%token L_DSTD
%token L_INDEX
%token L_COLS
%token L_COLS
%token L_ROWS
%token L_REPEAT
%token L_IF
%token L_ETA
%token L_COLON
%token L_MINUS
%token L_HAT
%token L_LABEL
%token L_QUOTE
%left L_MINUS L_PLUS
%left L_TIMES L_DIVIDE
%right L_POWER 
%left NEG     

%%
 result: L_EQUAL stringexp {act_parser->code = CODE_FORMULA;
                            act_parser->cell->append(NULL,FORM_RETURN);}
 result: L_EQUAL exp       {act_parser->code = CODE_FORMULA;
                            act_parser->cell->append(NULL,FORM_RETURN);}
 result: L_EQUAL logicexp       {act_parser->code = CODE_FORMULA;
                            act_parser->cell->append(NULL,FORM_RETURN);}
| integer                {
    if ($1 <= 32767 && $1 > -32766) {
        act_parser->code = CODE_INTEGER;
        act_parser->integ = (short)$1;
    }
    else {
        act_parser->code = CODE_NUMBER;
        act_parser->number = (double)($1);
    }}
| L_MINUS integer                {
    if ($2 <= 32767 && $2 > -32766) {
        act_parser->code = CODE_INTEGER;
        act_parser->integ =  - ((short)$2);
    }
    else {
        act_parser->code = CODE_NUMBER;
        act_parser->number = - (double)($2);
    }}
| float                  {act_parser->code = CODE_NUMBER; 
                            act_parser->number = $1;}
| L_MINUS float                  {act_parser->code = CODE_NUMBER; 
                                  act_parser->number = -($2);}
| date                   {act_parser->code = CODE_NUMBER; 
                            act_parser->number = $1;}
| L_LABEL                  {act_parser->code = CODE_LABEL;}
;

logicexp_int_cell : 
logicexp {$$=NULL;}
| integer {$$=NULL;}
| cell_id {$$=NULL;}
;

logicexp: 
L_ETA L_NOT L_LEFTPAR logicexp_int_cell L_RIGHTPAR     
                           {act_parser->cell->append(NULL,FORM_NOT);}
| exp L_GREATER exp
                           {act_parser->cell->append(NULL,FORM_GREATER);}
| exp L_EQUAL exp
                           {act_parser->cell->append(NULL,FORM_EQUAL);}
| exp L_SMALLER exp                  
                           {act_parser->cell->append(NULL,FORM_SMALLER);}
| exp L_GREATEREQ exp                  
                           {act_parser->cell->append(NULL,FORM_GREATEREQ);}
| exp L_SMALLEREQ exp                  
                           {act_parser->cell->append(NULL,FORM_SMALLEREQ);}
| exp L_NEQUAL exp                  
                           {act_parser->cell->append(NULL,FORM_NEQUAL);}
| L_ETA L_AND L_LEFTPAR logicexp_int_cell L_COMMA logicexp_int_cell L_RIGHTPAR
                           {act_parser->cell->append(NULL,FORM_AND);}
| L_ETA L_OR L_LEFTPAR logicexp_int_cell L_COMMA logicexp_int_cell L_RIGHTPAR
                           {act_parser->cell->append(NULL,FORM_OR);}
;
 

stringexp: 
string 
            {}
| L_ETA string_function   {} ;

string_cell_id:
string
            {}       
| cell_id 
            {}
;


stringexp_exp: stringexp {} | exp {};

string_function:
L_UPPER L_LEFTPAR string_cell_id L_RIGHTPAR 
                           {act_parser->cell->append(NULL,FORM_UPPER);}
| L_LOWER L_LEFTPAR string_cell_id L_RIGHTPAR 
                           {act_parser->cell->append(NULL,FORM_LOWER);}
| L_PROPER L_LEFTPAR string_cell_id L_RIGHTPAR 
                           {act_parser->cell->append(NULL,FORM_PROPER);}
;


string:
L_STRING 
                           {act_parser->cell->append($$,FORM_STRING);};

exp:      cell_id         
                           {}
| L_MINUS exp                  
                           {act_parser->cell->append(NULL,FORM_UNARY_MINUS);}
| exp L_POWER exp                  
                           {act_parser->cell->append(NULL,FORM_POWER);}
| exp L_PLUS exp                  
                           {act_parser->cell->append(NULL,FORM_PLUS);}
| exp L_MINUS exp                  
                           {act_parser->cell->append(NULL,FORM_SUB);}
| exp L_TIMES exp                  
                           {act_parser->cell->append(NULL,FORM_MULT);}
| exp L_DIVIDE exp                  
                           {act_parser->cell->append(NULL,FORM_DIV);}
| L_LEFTPAR exp L_RIGHTPAR          
                           {act_parser->cell->append(NULL,FORM_PAR);}
| L_ETA function                     
                           {}
| integer                         
                           {}
| float                           
                           {}
| date                  
                           {}
;


function: L_SUM L_LEFTPAR list_range_cell_value L_RIGHTPAR 
                            {act_parser->cell->append(&var_arg_cnt,
                                                         FORM_SUM);}
| L_VLOOKUP L_LEFTPAR exp L_COMMA range L_COMMA 
                      integer L_RIGHTPAR
                            {act_parser->cell->append(&cnt,
                                                         FORM_VLOOKUP);}
| L_HLOOKUP L_LEFTPAR exp L_COMMA range L_COMMA 
                      integer L_RIGHTPAR
                            {act_parser->cell->append(&cnt,
                                                         FORM_HLOOKUP);}
| L_MAX L_LEFTPAR list_range_cell_value L_RIGHTPAR 
                            {act_parser->cell->append(&var_arg_cnt,
                                                         FORM_MAX);}
| L_MIN L_LEFTPAR list_range_cell_value L_RIGHTPAR 
                            {act_parser->cell->append(&var_arg_cnt,
                                                         FORM_MIN);}
| L_AVG L_LEFTPAR list_range_cell_value L_RIGHTPAR 
                            {act_parser->cell->append(&var_arg_cnt,
                                                         FORM_AVG);}
| L_COUNT L_LEFTPAR list_range_cell_value L_RIGHTPAR 
                            {act_parser->cell->append(&var_arg_cnt,
                                                      FORM_COUNT);}
| L_IF L_LEFTPAR logicexp_int_cell L_COMMA stringexp_exp  L_COMMA stringexp_exp L_RIGHTPAR 
                            {var_arg_cnt = 3; 
                            act_parser->cell->append(&var_arg_cnt,
                                                      FORM_IF);}
| L_ROUND L_LEFTPAR exp L_COMMA exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_ROUND);}
| L_ABS L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_ABS);}
| L_INTF L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_INTF);}
| L_SQRT L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_SQRT);}
| L_LOG L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_LOG);}
| L_LN L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_LN);}
| L_PI L_LEFTPAR L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_PI);}
| L_SIN L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_SIN);}
| L_COS L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_COS);}
| L_TAN L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_TAN);}
| L_ATAN2 L_LEFTPAR exp L_COMMA exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_ATAN2);}
| L_ATAN L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_ATAN);}
| L_ASIN L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_ASIN);}
| L_ACOS L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_ACOS);}
| L_EXP L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_EXP);}
| L_MOD L_LEFTPAR exp L_COMMA exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_MOD);}
| L_DAY L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_DAY);}
| L_MONTH L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_MONTH);}
| L_HOUR L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_HOUR);}
| L_MINUTE L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_MINUTE);}
| L_SECOND L_LEFTPAR exp L_RIGHTPAR 
                            {act_parser->cell->append(&cnt,
                                                      FORM_SECOND);}
| L_SUMIF L_LEFTPAR range L_COMMA stringexp  L_COMMA exp L_COMMA range L_RIGHTPAR 
                            {var_arg_cnt = 4; act_parser->cell->append(&var_arg_cnt,
                                                      FORM_SUMIF);}


       ;

list_range_cell_value : range_cell_value L_COMMA list_range_cell_value {var_arg_cnt++;}
| range_cell_value {var_arg_cnt = 1;};



range_cell_value : 
range {$$=NULL;}
| exp {$$=NULL;}
;


range: L_CELL_ID L_COLON L_CELL_ID {Range *rg = range_reference($1,$3);
                                    act_parser->cell->append(rg,FORM_RANGE);}
; 

cell_id : L_CELL_ID 
                      {Ref *ref = cell_reference($1); 
                       act_parser->cell->append(ref,FORM_REF);}

float : L_FLOAT  {$$ = $1; act_parser->cell->append(&($1),FORM_FP);}
;

date : L_DATE  {$$ = $1; act_parser->cell->append(&($1),FORM_FP);
                act_parser->cell->setformat(DEFAULT_DATE_FORMAT);}
;



integer : L_INTEGER                       
                   {$$ = $1; 
                    if ($1 <= 32767 && $1 > -32766) 
                        act_parser->cell->append(&($1),FORM_INT);
                    else {
                        double x;
                        x = $1;
                        act_parser->cell->append(&(x),FORM_FP);
                   }}
;



%%



/* $Log: gram.y,v $
 * Revision 1.28  1998/10/20 13:20:47  cthulhu
 * Added dummy types and actions to two rules so bison wouldn't type clash on
 * 	default action ($$=$1).
 *
 * Revision 1.27  1998/08/06 21:05:21  aml
 * Released alpha version of Abacus.
 *
 * Revision 1.26  1997/02/10 15:09:56  aml
 * Print settings now are saved to file.
 * Fixed buggy error message when loading sheets.
 *
 * Revision 1.25  1997/01/02 16:15:27  aml
 * Fixed unsufficient range of colunm width.
 * First cut of vlookup and hlookup functions.
 * Fixed bug in display routines.
 *
 * Revision 1.24  1996/12/11 21:39:40  aml
 * Sumif implemented.
 * Diverse time functions implemented.
 * Fixed needtoscroll2 to avoid out of control scroll.
 *
 * Revision 1.23  1996/10/07 12:35:21  aml
 * First cut at error handling.
 * Date formats are in.
 * Fixed problem with blank cell drawing.
 *
 * Revision 1.22  1996/08/28  17:17:06  aml
 * Load and save now accept string_value for formula cells.
 * This fixes previous thought problem of formula values not
 * being stored.
 * Functions upper,lower and proper created.
 * Function if can now return labels.
 * Fixed problem with function count.
 * Reasonably stable version, very used to manipulate notas.wk1.
 *
 * Revision 1.21  1996/08/27 17:18:41  aml
 * First version of regressive tests created.
 * Changes were made to allow for string functions.
 * String function upper created. Raises the problem
 * that formulas do NOT have a space for string values,
 * and therefore have to be evaluated upon loading.
 *
 * Revision 1.20  1996/08/26 17:22:20  aml
 * Function round fixed.
 * Many other functions added, from power to mod.
 *
 * Revision 1.19  1996/07/23 14:00:30  aml
 * Changed canvas widget to handle special items like cell borders.
 * Seems to work well. Spreadsheet size is no more limited now.
 *
 * Revision 1.18  1996/03/11 15:47:41  aml
 * Made redraw more efficient by removing at once all cells before redrawing.
 * Fixed problem with unsufficient difinition of logical expressions.
 * Added >=, <=, <>, @and and @or functions.
 *
 * Revision 1.17  1996/03/09 08:32:35  aml
 * Fixed problem in string_single_arg macro
 * Created if function, boolean evaluations and so on.
 * Improved print controls.
 *
 * Revision 1.16  1996/03/08  19:00:15  aml
 * Fixed problem in string_single_arg macro
 * Created if function, boolean evaluations and so on.
 *
 * Revision 1.15  1996/03/07 20:32:44  aml
 * Created print range ability.
 * Set in gray non-working menus.
 * Created RangeKill command.
 * Created round function and macros for single argument functions.
 *
 * Revision 1.14  1996/03/01 13:08:27  aml
 * Stack references are now pushed instead of double value.
 * Fixed problem with integers too large on formulas.
 * Scroll with cursors now works better.
 *
 * Revision 1.13  1996/02/19  15:47:30  aml
 * Fixed abnormality with mouse click.
 * Variable width columns implemented, but not yet saved.
 * Labels are now a lex element, fixing some aberrant behavior that existed.
 *
 * Revision 1.12  1996/02/16 23:09:25  aml
 * Improved user interf state machine.
 * Centralized range definitions.
 * Range defined outiside current view work properly.
 *
 * Revision 1.11  1996/02/13  12:03:19  aml
 * Fixed bug with range definition via mouse.
 * Fixed bug in range iterators.
 *
 * Revision 1.10  1996/01/11  22:48:38  aml
 * Range iterators created.
 * Functions sum, max and min now work properly.
 * Negative numbers now allowed by flex (oops :-)
 *
 * Revision 1.9  1996/01/10  18:53:36  aml
 * Fixed limited integer range of cells.
 * Fixed incorrect code in spreadsheet type.
 * Users interface improved. Cursors and mouse clicks
 * now work in the most basic modes.
 *
 * Revision 1.8  1996/01/07  09:07:23  aml
 * Sheet::save and Sheet::load created.
 * Program can now write and read wk1 files.
 * Slight changes made to relative references. Bit 14 is now always 0.
 *
 * Revision 1.7  1996/01/05  23:05:52  aml
 * Cell references evaluated.
 * Spreadsheet is recalculated at every change, by an arbitrary order.
 * Reformulated program structure. Evaluation and reverse parsing
 * are member functions of Sheet.
 *
 * Revision 1.6  1996/01/04  20:27:11  aml
 * Range references parsed and reverse parsed.
 *
 * Revision 1.5  1996/01/03  23:07:03  aml
 * Absolute and relative references to cells introduced.
 * They are parsed and reverse parsed, not yet evaluated.
 *
 * Revision 1.4  1996/01/02  16:22:04  aml
 * Formula compilation, evaluation and decompilation now work.
 * Cells can be of type label, numerical formula or numbers.
 *
 * Revision 1.3  1995/12/30  16:40:21  aml
 * First cut of formula compilation.
 *
 * Revision 1.2  1995/12/28  19:20:34  aml
 * Created skeleton to merge calculation engine
 *
 * Revision 1.1  1995/12/28  18:23:09  aml
 * Initial revision
 *
 * Revision 1.7  1995/09/18  09:25:35  aml
 * Last working release with inline expressions.
 * Move to wk1 format will start after this.
 *
 * Revision 1.6  1995/08/18 19:39:32  aml
 *  Modularized to allow for multiple spreadsheets.
 *  Introduced bindings for cursors in main canvas.
 *  Introduced range_opers. Copy redone, cut created.
 *  Automatic positioning of active cell.
 *
 * Revision 1.5  1995/08/08 22:07:05  aml
 * Fixed copy operation.
 * Fixed parsing of ranges in operations.
 *
 * Revision 1.4  1995/06/26 22:52:25  aml
 * Change to C++
 *
 * Revision 1.3  1995/06/25  00:09:44  aml
 * First version of copy
 *
 * Revision 1.2  1995/06/23  16:10:17  aml
 * *** empty log message ***
 *
 * Revision 1.1  1995/06/23  15:41:34  aml
 * Initial revision
 * */
