1 /* 2 * Copyright (C) 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 _DIRECTIVES_HH 21 #define _DIRECTIVES_HH 22 23 #include "Expressions.hh" 24 25 #include <filesystem> 26 27 namespace macro 28 { 29 class Directive : public Node 30 { 31 // A Parent class just for clarity 32 public: Directive(Environment & env_arg,Tokenizer::location location_arg)33 Directive(Environment &env_arg, Tokenizer::location location_arg) : 34 Node(env_arg, move(location_arg)) { } 35 // Directives can be interpreted 36 virtual void interpret(ostream &output, vector<filesystem::path> &paths) = 0; 37 }; 38 39 40 class TextNode : public Directive 41 { 42 // Class for text not interpreted by macroprocessor 43 // Not a real directive node 44 // Treated as such as the output is only to be interpreted 45 private: 46 const string text; 47 public: TextNode(string text_arg,Environment & env_arg,Tokenizer::location location_arg)48 TextNode(string text_arg, Environment &env_arg, Tokenizer::location location_arg) : 49 Directive(env_arg, move(location_arg)), text{move(text_arg)} { } interpret(ostream & output,vector<filesystem::path> & paths)50 inline void interpret(ostream &output, vector<filesystem::path> &paths) override { output << text; } 51 }; 52 53 54 class Eval : public Directive 55 { 56 // Class for @{} statements 57 // Not a real directive node 58 // Treated as such as the output is only to be interpreted 59 private: 60 const ExpressionPtr expr; 61 public: Eval(ExpressionPtr expr_arg,Environment & env_arg,Tokenizer::location location_arg)62 Eval(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) : 63 Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { } 64 void interpret(ostream &output, vector<filesystem::path> &paths) override; 65 }; 66 67 68 class Include : public Directive 69 { 70 private: 71 const ExpressionPtr expr; 72 public: Include(ExpressionPtr expr_arg,Environment & env_arg,Tokenizer::location location_arg)73 Include(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) : 74 Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { } 75 void interpret(ostream &output, vector<filesystem::path> &paths) override; 76 }; 77 78 79 class IncludePath : public Directive 80 { 81 private: 82 const ExpressionPtr expr; 83 public: IncludePath(ExpressionPtr expr_arg,Environment & env_arg,Tokenizer::location location_arg)84 IncludePath(ExpressionPtr expr_arg, Environment &env_arg, Tokenizer::location location_arg) : 85 Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { } 86 void interpret(ostream &output, vector<filesystem::path> &paths) override; 87 }; 88 89 90 class Define : public Directive 91 { 92 private: 93 const VariablePtr var; 94 const FunctionPtr func; 95 const ExpressionPtr value; 96 public: Define(VariablePtr var_arg,ExpressionPtr value_arg,Environment & env_arg,Tokenizer::location location_arg)97 Define(VariablePtr var_arg, 98 ExpressionPtr value_arg, 99 Environment &env_arg, Tokenizer::location location_arg) : 100 Directive(env_arg, move(location_arg)), var{move(var_arg)}, value{move(value_arg)} { } Define(FunctionPtr func_arg,ExpressionPtr value_arg,Environment & env_arg,Tokenizer::location location_arg)101 Define(FunctionPtr func_arg, 102 ExpressionPtr value_arg, 103 Environment &env_arg, Tokenizer::location location_arg) : 104 Directive(env_arg, move(location_arg)), func{move(func_arg)}, value{move(value_arg)} { } 105 void interpret(ostream &output, vector<filesystem::path> &paths) override; 106 }; 107 108 109 class Echo : public Directive 110 { 111 private: 112 const ExpressionPtr expr; 113 public: Echo(ExpressionPtr expr_arg,Environment & env_arg,Tokenizer::location location_arg)114 Echo(ExpressionPtr expr_arg, 115 Environment &env_arg, Tokenizer::location location_arg) : 116 Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { } 117 void interpret(ostream &output, vector<filesystem::path> &paths) override; 118 }; 119 120 121 class Error : public Directive 122 { 123 private: 124 const ExpressionPtr expr; 125 public: Error(ExpressionPtr expr_arg,Environment & env_arg,Tokenizer::location location_arg)126 Error(ExpressionPtr expr_arg, 127 Environment &env_arg, Tokenizer::location location_arg) : 128 Directive(env_arg, move(location_arg)), expr{move(expr_arg)} { } 129 void interpret(ostream &output, vector<filesystem::path> &paths) override; 130 }; 131 132 133 class EchoMacroVars : public Directive 134 { 135 private: 136 const bool save; 137 const vector<string> vars; 138 public: EchoMacroVars(bool save_arg,Environment & env_arg,Tokenizer::location location_arg)139 EchoMacroVars(bool save_arg, 140 Environment &env_arg, Tokenizer::location location_arg) : 141 Directive(env_arg, move(location_arg)), save{save_arg} { } EchoMacroVars(bool save_arg,vector<string> vars_arg,Environment & env_arg,Tokenizer::location location_arg)142 EchoMacroVars(bool save_arg, vector<string> vars_arg, 143 Environment &env_arg, Tokenizer::location location_arg) : 144 Directive(env_arg, move(location_arg)), save{save_arg}, vars{move(vars_arg)} { } 145 void interpret(ostream &output, vector<filesystem::path> &paths) override; 146 }; 147 148 149 class For : public Directive 150 { 151 private: 152 const vector<VariablePtr> index_vec; 153 const ExpressionPtr index_vals; 154 const vector<DirectivePtr> statements; 155 public: For(vector<VariablePtr> index_vec_arg,ExpressionPtr index_vals_arg,vector<DirectivePtr> statements_arg,Environment & env_arg,Tokenizer::location location_arg)156 For(vector<VariablePtr> index_vec_arg, 157 ExpressionPtr index_vals_arg, 158 vector<DirectivePtr> statements_arg, 159 Environment &env_arg, Tokenizer::location location_arg) : 160 Directive(env_arg, move(location_arg)), index_vec{move(index_vec_arg)}, 161 index_vals{move(index_vals_arg)}, statements{move(statements_arg)} { } 162 void interpret(ostream &output, vector<filesystem::path> &paths) override; 163 }; 164 165 166 class If : public Directive 167 { 168 protected: 169 /* Every if statement and the associated body to execute are stored in a 170 * pair<ExpressionPtr, vector<DirectivePtr>>, where the ExpressionPtr is the condition 171 * and vector<DirectivePtr> is the series of statements to execute if the condition evaluates 172 * to true. 173 * The `if` statement is the first element in the vector 174 * If there exist any `elseif` statements, they follow 175 * If there is an `else` statement it is the last element in the vector. Its condition is true. 176 */ 177 const vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body; 178 const bool ifdef, ifndef; 179 public: If(vector<pair<ExpressionPtr,vector<DirectivePtr>>> expr_and_body_arg,Environment & env_arg,Tokenizer::location location_arg,bool ifdef_arg=false,bool ifndef_arg=false)180 If(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg, 181 Environment &env_arg, Tokenizer::location location_arg, 182 bool ifdef_arg = false, bool ifndef_arg = false) : 183 Directive(env_arg, move(location_arg)), expr_and_body{move(expr_and_body_arg)}, 184 ifdef{ifdef_arg}, ifndef{ifndef_arg} { } 185 void interpret(ostream &output, vector<filesystem::path> &paths) override; 186 protected: 187 void interpretBody(const vector<DirectivePtr> &body, ostream &output, 188 vector<filesystem::path> &paths); 189 }; 190 191 class Ifdef : public If 192 { 193 public: Ifdef(vector<pair<ExpressionPtr,vector<DirectivePtr>>> expr_and_body_arg,Environment & env_arg,Tokenizer::location location_arg)194 Ifdef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg, 195 Environment &env_arg, Tokenizer::location location_arg) : 196 If(move(expr_and_body_arg), env_arg, move(location_arg), true, false) { } 197 }; 198 199 200 class Ifndef : public If 201 { 202 public: Ifndef(vector<pair<ExpressionPtr,vector<DirectivePtr>>> expr_and_body_arg,Environment & env_arg,Tokenizer::location location_arg)203 Ifndef(vector<pair<ExpressionPtr, vector<DirectivePtr>>> expr_and_body_arg, 204 Environment &env_arg, Tokenizer::location location_arg) : 205 If(move(expr_and_body_arg), env_arg, move(location_arg), false, true) { } 206 }; 207 } 208 #endif 209