/* -*- 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); }