%skeleton "lalr1.cc"                          /*  -*- C++ -*- */
%define "parser_class_name" "Calculator_parser"
%defines
%{
# include <string>
# include "Calculator_driver.hpp"
%}

// The parsing context.
%parse-param { Calculator_driver & driver }
%lex-param   { Calculator_driver & driver }
%locations
%initial-action
{
  // Initialize the initial location.
  @$.begin.filename = @$.end.filename = & driver.file;
};

%debug
%error-verbose

// Symbols.
%union
{
  int          ival;
  std::string * sval;
};

%token        TOKEN_EOF      0 "end of file"
%token        TOKEN_ASSIGN     ":="
%token <sval> TOKEN_IDENTIFIER "identifier"
%token <ival> TOKEN_NUMBER     "number"
%type  <ival> exp              "expression"

%printer    { debug_stream () << * $$; } "identifier"
%destructor { delete $$; } "identifier"

%printer    { debug_stream () << $$; } "number" "expression"

%%
%start unit;
unit: assignments exp  { driver.result = $2; };

assignments: assignments assignment {}
           | /* Nothing. */         {};

assignment: TOKEN_IDENTIFIER ":=" exp { driver.variables[*$1] = $3; };

%left '+' '-';
%left '*' '/';
exp: exp '+' exp   { $$ = $1 + $3; }
   | exp '-' exp   { $$ = $1 - $3; }
   | exp '*' exp   { $$ = $1 * $3; }
   | exp '/' exp   { $$ = $1 / $3; }
   | TOKEN_IDENTIFIER  { $$ = driver.variables[*$1]; }
   | TOKEN_NUMBER      { $$ = $1; };
%%

void yy::Calculator_parser::error (const yy::Calculator_parser::location_type & l, const std::string & m)
{
	driver.error (l, m);
}
