1
0
mirror of https://github.com/aportelli/LatAnalyze.git synced 2024-11-10 17:05:35 +00:00
LatAnalyze/latan/IoAsciiParser.ypp

154 lines
3.9 KiB
Plaintext

/*
* 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 <memory>
#include <sstream>
#include <utility>
#include <cstring>
#include <latan/Global.hpp>
#include <latan/IO.hpp>
#include <latan/Mat.hpp>
#include <latan/RandGen.hpp>
#include <latan/Sample.hpp>
using namespace std;
using namespace Latan;
#define STORE(ref) (*state->data)[(ref).first] = std::move((ref).second)
%}
%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 <val_char> ERR
%token <val_double> FLOAT
%token <val_int> INT
%token <val_str> ID
%token OPEN CLOSE MAT RG_STATE
%type <val_str> mat rg_state
%{
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 data
;
data:
mat
{(*state->data)[$1].reset(new DMat(state->dMatBuf));}
| rg_state
{(*state->data)[$1].reset(new RandGen::State(state->stateBuf));}
;
mat:
OPEN MAT ID INT floats CLOSE MAT
{
const int nRow = state->doubleStack.size()/$INT, nCol = $INT;
int r, i, j;
r = 0;
state->dMatBuf.resize(nRow, nCol);
while (!state->doubleStack.empty())
{
j = r % nCol;
i = (r - j)/nCol;
state->dMatBuf(i, j) = state->doubleStack.top();
state->doubleStack.pop();
++r;
}
if (r != nRow*nCol)
{
LATAN_ERROR(Range, "matrix '" + *state->streamName + ":" + $ID +
"' has a wrong size");
}
strcpy($$, $ID);
}
;
rg_state:
OPEN RG_STATE ID ints CLOSE RG_STATE
{
for (int i = 0; i < RLXG_STATE_SIZE; ++i)
{
if (!state->intStack.empty())
{
state->stateBuf[i] = state->intStack.top();
state->intStack.pop();
}
else
{
LATAN_ERROR(Range, "random generator state '" +
*state->streamName + ":" + $ID + "' is too short");
}
}
if (!state->intStack.empty())
{
LATAN_ERROR(Range, "random generator state '" +
*state->streamName + ":" + $ID + "' is too long");
}
strcpy($$, $ID);
}
;
floats:
FLOAT floats {state->doubleStack.push($1);}
| INT floats {state->doubleStack.push(static_cast<double>($1));}
| FLOAT {state->doubleStack.push($1);}
| INT {state->doubleStack.push(static_cast<double>($1));}
;
ints:
INT ints {state->intStack.push($1);}
| INT {state->intStack.push($1);}
;