/*
* Copyright © 2019-2020 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 .
*/
#ifndef _MACRO_DRIVER_HH
#define _MACRO_DRIVER_HH
#ifdef _PARSING_DRIVER_HH
# error Impossible to include both ../ParsingDriver.hh and Driver.hh
#endif
#include "Parser.hh"
#include "Environment.hh"
#include "Expressions.hh"
#include
// Declare TokenizerFlexLexer class
#ifndef __FLEX_LEXER_H
# define yyFlexLexer TokenizerFlexLexer
# include
# undef yyFlexLexer
#endif
namespace macro
{
/* The lexer class
* It was necessary to subclass the TokenizerFlexLexer class generated by Flex,
* since the prototype for TokenizerFlexLexer::yylex() was not convenient.
*/
class TokenizerFlex : public TokenizerFlexLexer
{
public:
TokenizerFlex(istream *in) : TokenizerFlexLexer{in} { }
TokenizerFlex(const TokenizerFlex &) = delete;
TokenizerFlex(TokenizerFlex &&) = delete;
TokenizerFlex &operator=(const TokenizerFlex &) = delete;
TokenizerFlex &operator=(TokenizerFlex &&) = delete;
//! The main lexing function
Tokenizer::parser::token_type lex(Tokenizer::parser::semantic_type *yylval,
Tokenizer::parser::location_type *yylloc,
macro::Driver &driver);
};
//! Implements the macro expansion using a Flex scanner and a Bison parser
class Driver
{
private:
vector statements;
stack> directive_stack;
public:
Driver() = default;
Driver(const Driver &) = delete;
Driver(Driver &&) = delete;
Driver &operator=(const Driver &) = delete;
Driver &operator=(Driver &&) = delete;
//! Exception thrown when value of an unknown variable is requested
class UnknownVariable
{
public:
const string name;
explicit UnknownVariable(string name_arg) : name{move(name_arg)}
{
}
};
//! Starts parsing a file, modifies `env`, `paths` and `output`
//! as they are modified by various macro directives
void parse(const string &file, const string &basename, const istream &modfile,
bool debug, const vector> &defines,
Environment &env, vector &paths, ostream &output);
//! Name of main file being parsed
string file;
//! Basename of main file being parsed
string basename;
//! Reference to the lexer
unique_ptr lexer;
//! Error handler
void error(const Tokenizer::parser::location_type &location, const string &message) const;
inline bool
inContext() const
{
return !directive_stack.empty();
}
inline void
pushContext()
{
directive_stack.emplace(vector());
}
inline void
pushContextTop(DirectivePtr statement)
{
directive_stack.top().emplace_back(move(statement));
}
inline void
pushStatements(DirectivePtr statement)
{
statements.emplace_back(move(statement));
}
inline vector
popContext()
{
auto top = move(directive_stack.top());
directive_stack.pop();
return top;
}
};
}
#endif