/* * 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