/* -*- C++ -*- */
/*
* Copyright © 2019 Dynare Team
*
* This file is part of Dynare.
*
* Dynare 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.
*
* Dynare 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 Dynare. If not, see .
*/
%{
#include "Driver.hh"
// Announce to Flex the prototype we want for lexing function
#define YY_DECL \
Tokenizer::parser::token_type \
TokenizerFlex::lex(Tokenizer::parser::semantic_type *yylval, \
Tokenizer::parser::location_type *yylloc, \
macro::Driver &driver)
// Shortcut to access tokens defined by Bison
using token = Tokenizer::parser::token;
/* By default yylex returns int, we use token_type.
Unfortunately yyterminate by default returns 0, which is
not of token_type. */
#define yyterminate() return Tokenizer::parser::token_type (0);
%}
%option c++
%option prefix="Tokenizer"
%option case-insensitive noinput noyywrap nounput batch debug never-interactive noyymore
%x directive
%x eval
%x expr
%x end_line
%{
// Increments location counter for every token read
# define YY_USER_ACTION yylloc->columns(yyleng);
%}
SPC [ \t]+
EOL (\r)?\n
CONT \\\\{SPC}*
%%
/* Code put at the beginning of yylex() */
%{
// Reset location before reading token
yylloc->step();
%}
line { BEGIN(expr); return token::LINE; }
include { BEGIN(expr); return token::INCLUDE; }
includepath { BEGIN(expr); return token::INCLUDEPATH; }
define { BEGIN(expr); return token::DEFINE; }
echo { BEGIN(expr); return token::D_ECHO; }
error { BEGIN(expr); return token::ERROR; }
if { BEGIN(expr); return token::IF; }
ifdef { BEGIN(expr); return token::IFDEF; }
ifndef { BEGIN(expr); return token::IFNDEF; }
elseif { BEGIN(expr); return token::ELSEIF; }
else { BEGIN(end_line); return token::ELSE; }
endif { BEGIN(end_line); return token::ENDIF; }
for { BEGIN(expr); return token::FOR; }
endfor { BEGIN(end_line); return token::ENDFOR; }
echomacrovars { BEGIN(expr); return token::ECHOMACROVARS; }
\+ { return token::PLUS; }
- { return token::MINUS; }
\* { return token::TIMES; }
\/ { return token::DIVIDE; }
= { return token::EQUAL; }
\^ { return token::POWER; }
< { return token::LESS; }
> { return token::GREATER; }
>= { return token::GREATER_EQUAL; }
<= { return token::LESS_EQUAL; }
== { return token::EQUAL_EQUAL; }
!= { return token::NOT_EQUAL; }
&& { return token::AND; }
"||" { return token::OR; }
! { return token::NOT; }
\| { return token::UNION; }
& { return token::INTERSECTION; }
, { return token::COMMA; }
: { return token::COLON; }
\( { return token::LPAREN; }
\) { return token::RPAREN; }
\[ { return token::LBRACKET; }
\] { return token::RBRACKET; }
in { return token::IN; }
for { return token::FOR; }
when { return token::WHEN; }
save { return token::SAVE; }
true { return token::TRUE; }
false { return token::FALSE; }
exp { return token::EXP; }
log { return token::LOG; }
ln { return token::LN; }
log10 { return token::LOG10; }
sin { return token::SIN; }
cos { return token::COS; }
tan { return token::TAN; }
asin { return token::ATAN; }
acos { return token::ACOS; }
atan { return token::ATAN; }
sqrt { return token::SQRT; }
cbrt { return token::CBRT; }
sign { return token::SIGN; }
max { return token::MAX; }
min { return token::MIN; }
floor { return token::FLOOR; }
ceil { return token::CEIL; }
trunc { return token::TRUNC; }
mod { return token::MOD; }
sum { return token::SUM; }
erf { return token::ERF; }
erfc { return token::ERFC; }
gamma { return token::GAMMA; }
lgamma { return token::LGAMMA; }
round { return token::ROUND; }
length { return token::LENGTH; }
normpdf { return token::NORMPDF; }
normcdf { return token::NORMCDF; }
isempty { return token::ISEMPTY; }
isboolean { return token::ISBOOLEAN; }
isreal { return token::ISREAL; }
isstring { return token::ISSTRING; }
istuple { return token::ISTUPLE; }
isarray { return token::ISARRAY; }
bool { return token::BOOL; }
real { return token::REAL; }
string { return token::STRING; }
tuple { return token::TUPLE; }
array { return token::ARRAY; }
defined { return token::DEFINED; }
((([0-9]*\.[0-9]+)|([0-9]+\.))([ed][-+]?[0-9]+)?)|([0-9]+([ed][-+]?[0-9]+)?)|nan|inf {
yylval->build(yytext);
return token::NUMBER;
}
[A-Za-z_][A-Za-z0-9_]* {
yylval->build(yytext);
return token::NAME;
}
\"[^\"]*\" {
yylval->build(yytext + 1).pop_back();
return token::QUOTED_STRING;
}
{SPC}+ { }
{EOL}+ { yylloc->lines(yyleng); yylloc->lines(yyleng); }
\} { BEGIN(INITIAL); return token::END_EVAL; }
{CONT}("//".*)?{SPC}*{EOL} { yylloc->lines(1); yylloc->step(); }
{SPC}*("//".*)?{EOL} {
yylval->build("\n");
yylloc->lines(1);
BEGIN(INITIAL);
return token::EOL;
}
^{SPC}*@#{SPC}* { BEGIN(directive); }
@\{ { BEGIN(eval); return token::BEGIN_EVAL; }
{SPC}*{EOL} {
yylval->build(yytext);
yylloc->lines(1);
return token::EOL;
}
<> { yyterminate(); }
<> { driver.error(*yylloc, "unexpected end of file"); }
<*>. { yylval->build(yytext); return token::TEXT; }
<*>.|{EOL} { driver.error(*yylloc, "character unrecognized by lexer"); }
%%
/* This implementation of TokenizerFlexLexer::yylex() is required to fill the
* vtable of the class TokenizerFlexLexer. We define the scanner's main yylex
* function via YY_DECL to reside in the TokenizerFlex class instead. */
#ifdef yylex
# undef yylex
#endif
int
TokenizerFlexLexer::yylex()
{
cerr << "TokenizerFlexLexer::yylex() has been called; shouldn't arrive here." << endl;
exit(EXIT_FAILURE);
}