/*
 * Copyright (C) 1999, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2011,
 * 2012 Free Software Foundation, Inc.
 * 
 * This file is part of GNU libmatheval
 *
 * GNU libmatheval is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * GNU libmatheval is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNU libmatheval.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

%{
/*
 * Copyright (C) 1999, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2011,
 * 2012 Free Software Foundation, Inc.
 * 
 * GNU libmatheval is free software: you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation, either version 3 of the
 * License, or (at your option) any later version.
 *
 * GNU libmatheval is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with GNU libmatheval.  If not, see
 * <http://www.gnu.org/licenses/>.
 */

#if HAVE_CONFIG_H
#  include "config.h"
#endif

#include <stdlib.h>
#include "node.h"

/* Variables used to communicate with code using parser.  */
extern Node* root; /* Root of tree representation of function.  */
extern SymbolTable *symbol_table; /* Evaluator symbol table.  */
extern int ok; /* Flag representing success of parsing.  */

/* Report parsing error.  */
int yyerror (char *s);

/* Function used to tokenize string representing function (this function
 * is generated by scanner generator).  */
extern int yylex (void);

/* Function used to reset string representing function (this function is
 * generated by scanner generator).  */
extern void input_reset (void);
%}

/* Parser semantic values type.  */
%union {
  Node *node;
  Record *record;
}

/* Grammar terminal symbols.  */
%token <node> NUMBER CONSTANT VARIABLE
%token <record> FUNCTION
%left '-' '+'
%left '*' '/'
%left NEG
%left '^'
%token END

/* Grammar non-terminal symbols.  */
%type <node> expression

/* Grammar start non-terminal.  */
%start input

%%

input
: expression '\n' {
  root = $1;
}
;

expression
: NUMBER
| CONSTANT
| VARIABLE
| expression '+' expression {
        /* Create addition binary operation node.  */
        $$ = node_create ('b', '+', $1, $3);
}
| expression '-' expression {
        /* Create subtraction binary operation node.  */
        $$ = node_create ('b', '-', $1, $3);
}
| expression '*' expression {
        /* Create multiplication binary operation node.  */
        $$ = node_create ('b', '*', $1, $3);
}
| expression '/' expression {
        /* Create division binary operation node.  */
        $$ = node_create ('b', '/', $1, $3);
}
| '-' expression %prec NEG {
        /* Create minus unary operation node.  */
        $$ = node_create ('u', '-', $2);
}
| expression '^' expression {
        /* Create exponentiation unary operation node.  */
        $$ = node_create ('b', '^', $1, $3);
}
| FUNCTION '(' expression ')' {
        /* Create function node.  */
        $$ = node_create ('f', $1, $3);
}
| '(' expression ')' {
        $$ = $2;
}
;

%%

int yyerror(char* s)
{
        /* Indicate parsing error through appropriate flag, reset input
         * string and stop parsing.  */
        ok = 0;
        input_reset();
        return 0;
}
