preprocessor/src/macro/Tokenizer.ll

219 lines
8.5 KiB
LLVM

/* -*- 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 <https://www.gnu.org/licenses/>.
*/
%{
#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();
%}
<directive>line { BEGIN(expr); return token::LINE; }
<directive>include { BEGIN(expr); return token::INCLUDE; }
<directive>includepath { BEGIN(expr); return token::INCLUDEPATH; }
<directive>define { BEGIN(expr); return token::DEFINE; }
<directive>echo { BEGIN(expr); return token::D_ECHO; }
<directive>error { BEGIN(expr); return token::ERROR; }
<directive>if { BEGIN(expr); return token::IF; }
<directive>ifdef { BEGIN(expr); return token::IFDEF; }
<directive>ifndef { BEGIN(expr); return token::IFNDEF; }
<directive>elseif { BEGIN(expr); return token::ELSEIF; }
<directive>else { BEGIN(end_line); return token::ELSE; }
<directive>endif { BEGIN(end_line); return token::ENDIF; }
<directive>for { BEGIN(expr); return token::FOR; }
<directive>endfor { BEGIN(end_line); return token::ENDFOR; }
<directive>echomacrovars { BEGIN(expr); return token::ECHOMACROVARS; }
<expr,eval>\+ { return token::PLUS; }
<expr,eval>- { return token::MINUS; }
<expr,eval>\* { return token::TIMES; }
<expr,eval>\/ { return token::DIVIDE; }
<expr,eval>= { return token::EQUAL; }
<expr,eval>\^ { return token::POWER; }
<expr,eval>< { return token::LESS; }
<expr,eval>> { return token::GREATER; }
<expr,eval>>= { return token::GREATER_EQUAL; }
<expr,eval><= { return token::LESS_EQUAL; }
<expr,eval>== { return token::EQUAL_EQUAL; }
<expr,eval>!= { return token::NOT_EQUAL; }
<expr,eval>&& { return token::AND; }
<expr,eval>"||" { return token::OR; }
<expr,eval>! { return token::NOT; }
<expr,eval>\| { return token::UNION; }
<expr,eval>& { return token::INTERSECTION; }
<expr,eval>, { return token::COMMA; }
<expr,eval>: { return token::COLON; }
<expr,eval>\( { return token::LPAREN; }
<expr,eval>\) { return token::RPAREN; }
<expr,eval>\[ { return token::LBRACKET; }
<expr,eval>\] { return token::RBRACKET; }
<expr,eval>in { return token::IN; }
<expr,eval>for { return token::FOR; }
<expr,eval>when { return token::WHEN; }
<expr,eval>save { return token::SAVE; }
<expr,eval>true { return token::TRUE; }
<expr,eval>false { return token::FALSE; }
<expr,eval>exp { return token::EXP; }
<expr,eval>log { return token::LOG; }
<expr,eval>ln { return token::LN; }
<expr,eval>log10 { return token::LOG10; }
<expr,eval>sin { return token::SIN; }
<expr,eval>cos { return token::COS; }
<expr,eval>tan { return token::TAN; }
<expr,eval>asin { return token::ATAN; }
<expr,eval>acos { return token::ACOS; }
<expr,eval>atan { return token::ATAN; }
<expr,eval>sqrt { return token::SQRT; }
<expr,eval>cbrt { return token::CBRT; }
<expr,eval>sign { return token::SIGN; }
<expr,eval>max { return token::MAX; }
<expr,eval>min { return token::MIN; }
<expr,eval>floor { return token::FLOOR; }
<expr,eval>ceil { return token::CEIL; }
<expr,eval>trunc { return token::TRUNC; }
<expr,eval>mod { return token::MOD; }
<expr,eval>sum { return token::SUM; }
<expr,eval>erf { return token::ERF; }
<expr,eval>erfc { return token::ERFC; }
<expr,eval>gamma { return token::GAMMA; }
<expr,eval>lgamma { return token::LGAMMA; }
<expr,eval>round { return token::ROUND; }
<expr,eval>length { return token::LENGTH; }
<expr,eval>normpdf { return token::NORMPDF; }
<expr,eval>normcdf { return token::NORMCDF; }
<expr,eval>isempty { return token::ISEMPTY; }
<expr,eval>isboolean { return token::ISBOOLEAN; }
<expr,eval>isreal { return token::ISREAL; }
<expr,eval>isstring { return token::ISSTRING; }
<expr,eval>istuple { return token::ISTUPLE; }
<expr,eval>isarray { return token::ISARRAY; }
<expr,eval>bool { return token::BOOL; }
<expr,eval>real { return token::REAL; }
<expr,eval>string { return token::STRING; }
<expr,eval>tuple { return token::TUPLE; }
<expr,eval>array { return token::ARRAY; }
<expr,eval>defined { return token::DEFINED; }
<expr,eval>((([0-9]*\.[0-9]+)|([0-9]+\.))([ed][-+]?[0-9]+)?)|([0-9]+([ed][-+]?[0-9]+)?)|nan|inf {
yylval->build<string>(yytext);
return token::NUMBER;
}
<expr,eval>[A-Za-z_][A-Za-z0-9_]* {
yylval->build<string>(yytext);
return token::NAME;
}
<expr,eval>\"[^\"]*\" {
yylval->build<string>(yytext + 1).pop_back();
return token::QUOTED_STRING;
}
<expr,eval>{SPC}+ { }
<eval>{EOL}+ { yylloc->lines(yyleng); yylloc->lines(yyleng); }
<eval>\} { BEGIN(INITIAL); return token::END_EVAL; }
<expr,end_line>{CONT}("//".*)?{SPC}*{EOL} { yylloc->lines(1); yylloc->step(); }
<expr,end_line>{SPC}*("//".*)?{EOL} {
yylval->build<string>("\n");
yylloc->lines(1);
BEGIN(INITIAL);
return token::EOL;
}
<INITIAL>^{SPC}*@#{SPC}* { BEGIN(directive); }
<INITIAL>@\{ { BEGIN(eval); return token::BEGIN_EVAL; }
<INITIAL>{SPC}*{EOL} {
yylval->build<string>(yytext);
yylloc->lines(1);
return token::EOL;
}
<INITIAL><<EOF>> { yyterminate(); }
<directive,expr,eval,end_line><<EOF>> { driver.error(*yylloc, "unexpected end of file"); }
<*>. { yylval->build<string>(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);
}