1 /* 2 * Copyright © 2019-2020 Dynare Team 3 * 4 * This file is part of Dynare. 5 * 6 * Dynare is free software: you can redistribute it and/or modify 7 * it under the terms of the GNU General Public License as published by 8 * the Free Software Foundation, either version 3 of the License, or 9 * (at your option) any later version. 10 * 11 * Dynare is distributed in the hope that it will be useful, 12 * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 * GNU General Public License for more details. 15 * 16 * You should have received a copy of the GNU General Public License 17 * along with Dynare. If not, see <http://www.gnu.org/licenses/>. 18 */ 19 20 #ifndef _MACRO_DRIVER_HH 21 #define _MACRO_DRIVER_HH 22 23 #ifdef _PARSING_DRIVER_HH 24 # error Impossible to include both ../ParsingDriver.hh and Driver.hh 25 #endif 26 27 #include "Parser.hh" 28 #include "Environment.hh" 29 #include "Expressions.hh" 30 31 #include <stack> 32 33 // Declare TokenizerFlexLexer class 34 #ifndef __FLEX_LEXER_H 35 # define yyFlexLexer TokenizerFlexLexer 36 # include <FlexLexer.h> 37 # undef yyFlexLexer 38 #endif 39 40 namespace macro 41 { 42 /* The lexer class 43 * It was necessary to subclass the TokenizerFlexLexer class generated by Flex, 44 * since the prototype for TokenizerFlexLexer::yylex() was not convenient. 45 */ 46 class TokenizerFlex : public TokenizerFlexLexer 47 { 48 public: TokenizerFlex(istream * in)49 TokenizerFlex(istream *in) : TokenizerFlexLexer{in} { } 50 TokenizerFlex(const TokenizerFlex &) = delete; 51 TokenizerFlex(TokenizerFlex &&) = delete; 52 TokenizerFlex &operator=(const TokenizerFlex &) = delete; 53 TokenizerFlex &operator=(TokenizerFlex &&) = delete; 54 55 //! The main lexing function 56 Tokenizer::parser::token_type lex(Tokenizer::parser::semantic_type *yylval, 57 Tokenizer::parser::location_type *yylloc, 58 macro::Driver &driver); 59 }; 60 61 //! Implements the macro expansion using a Flex scanner and a Bison parser 62 class Driver 63 { 64 public: 65 Environment &env; 66 private: 67 vector<DirectivePtr> statements; 68 stack<vector<DirectivePtr>> directive_stack; 69 public: Driver(Environment & env_arg)70 Driver(Environment &env_arg) : 71 env{env_arg} { } 72 Driver(const Driver &) = delete; 73 Driver(Driver &&) = delete; 74 Driver &operator=(const Driver &) = delete; 75 Driver &operator=(Driver &&) = delete; 76 77 //! Exception thrown when value of an unknown variable is requested 78 class UnknownVariable 79 { 80 public: 81 const string name; UnknownVariable(string name_arg)82 explicit UnknownVariable(string name_arg) : name{move(name_arg)} 83 { 84 } 85 }; 86 87 //! Starts parsing a file, returns output in out 88 void parse(const string &file_arg, const string &basename_arg, istream &modfile, 89 ostream &output, bool debug, const vector<pair<string, string>> &defines, 90 vector<filesystem::path> &paths_arg); 91 92 //! Name of main file being parsed 93 string file; 94 95 //! Basename of main file being parsed 96 string basename; 97 98 //! Reference to the lexer 99 unique_ptr<TokenizerFlex> lexer; 100 101 //! Error handler 102 void error(const Tokenizer::parser::location_type &location, const string &message) const; 103 104 inline bool inContext() const105 inContext() const 106 { 107 return !directive_stack.empty(); 108 } 109 110 inline void pushContext()111 pushContext() 112 { 113 directive_stack.emplace(vector<DirectivePtr>()); 114 } 115 116 inline void pushContextTop(DirectivePtr statement)117 pushContextTop(DirectivePtr statement) 118 { 119 directive_stack.top().emplace_back(move(statement)); 120 } 121 122 inline void pushStatements(DirectivePtr statement)123 pushStatements(DirectivePtr statement) 124 { 125 statements.emplace_back(move(statement)); 126 } 127 128 inline vector<DirectivePtr> popContext()129 popContext() 130 { 131 auto top = move(directive_stack.top()); 132 directive_stack.pop(); 133 return top; 134 } 135 }; 136 } 137 #endif 138