/*
 * IoAsciiParser.ypp, part of LatAnalyze 3
 *
 * Copyright (C) 2013 - 2014 Antonin Portelli
 *
 * LatAnalyze 3 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.
 *
 * LatAnalyze 3 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 LatAnalyze 3.  If not, see <http://www.gnu.org/licenses/>.
 */

%{
    #include <iostream>
    #include <sstream>
    #include <cstring>
    #include <latan/Global.hpp>
	#include <latan/IO.hpp>
    #include <latan/Sample.hpp>

    using namespace std;
    using namespace Latan;
%}

%pure-parser
%name-prefix="_ioAscii_"
%locations
%defines
%error-verbose
%parse-param { Latan::AsciiFile::AsciiParserState* state }
%initial-action {yylloc.last_column = 0;}
%lex-param { void* scanner }

%union
{
	int     val_int;
	double  val_double;
    char    val_char;
    char    val_str[256];
}

%token              CLOSE
%token <val_char>   ERR
%token <val_double> FLOAT
%token <val_int>    INT
%token <val_str>    ID
%token              MAT
%token              OPEN

%{
	int _ioAscii_lex(YYSTYPE* lvalp, YYLTYPE* llocp, void* scanner);

	void _ioAscii_error(YYLTYPE* locp, AsciiFile::AsciiParserState* state,
                        const char* err)
	{
        stringstream buf;
        
        buf << *state->streamName << ":" << locp->first_line << ":"\
            << locp->first_column << ": " << err;
        LATAN_ERROR(Parsing, buf.str());
	}

	#define scanner state->scanner
%}

%%

datas:
      /* empty string */
    | datas mat
	;

mat:
      OPEN MAT ID INT floats CLOSE MAT
    {
        const int nRow = state->doubleBuf.size()/$INT, nCol = $INT;
        (*state->data)[$ID] = new DMat(nRow,nCol);
        DMat &M = static_cast<DMat &>(*((*state->data)[$ID]));
        int r,i,j;
        
        r = 0;
        while (!state->doubleBuf.empty())
        {
            j = r % nCol;
            i = (r - j)/nCol;
            M(i,j) = state->doubleBuf.top();
            state->doubleBuf.pop();
            ++r;
        }
    }
    ;

floats:
      FLOAT floats {state->doubleBuf.push($1);}
    | INT   floats {state->doubleBuf.push(static_cast<double>($1));}
    | FLOAT {state->doubleBuf.push($1);}
    | INT   {state->doubleBuf.push(static_cast<double>($1));}
    ;
