User Guide
nmodl_driver.hpp
Go to the documentation of this file.
1 /*
2  * Copyright 2023 Blue Brain Project, EPFL.
3  * See the top-level LICENSE file for details.
4  *
5  * SPDX-License-Identifier: Apache-2.0
6  */
7 
8 #pragma once
9 
10 /**
11  * \dir
12  * \brief Parser implementations
13  */
14 
15 #include <filesystem>
16 #include <string>
17 #include <unordered_map>
18 
19 #include "ast/include.hpp"
20 #include "utils/file_library.hpp"
21 
22 
23 /// encapsulates everything related to NMODL code generation framework
24 namespace nmodl {
25 /// encapsulate lexer and parsers implementations
26 namespace parser {
27 
28 // Declared in: lexer/nmodl_lexer.hpp
29 class NmodlLexer;
30 
31 // Declared in generated file: ${BUILD_DIR}/src/parser/nmodl/location.hh
32 class location;
33 
34 /**
35  * \defgroup parser Parser Implementation
36  * \brief All parser and driver classes implementation
37  *
38  *
39  *
40  * \addtogroup parser
41  * \{
42  */
43 
44 /**
45  * \class NmodlDriver
46  * \brief Class that binds all pieces together for parsing nmodl file
47  *
48  * Driver class bind components required for lexing, parsing and ast
49  * generation from nmodl file. We create an instance of lexer, parser
50  * and provides different methods to parse from file, stream or string.
51  * The scanner also gets reference to driver object for two purposes :
52  * scanner store/query the macro definitions into/from driver class
53  * and erros can be propogated back to driver (not implemented yet).
54  * Parser class also gets a reference to driver class as a parameter.
55  * Parsing actions generate ast and it's pointer is stored in driver
56  * class.
57  *
58  * \todo Lexer, parser and ast member variables are used inside lexer/
59  * parser instances. The local instaces are created inside parse_stream
60  * and hence the pointers are no longer valid except ast. Need better
61  * way to handle this.
62  *
63  * \todo Stream name is not used as it will need better support as
64  * location object used in scanner takes string pointer which could
65  * be invalid when we copy location object.
66  */
67 class NmodlDriver {
68  private:
69  /// all macro defined in the mod file
70  std::unordered_map<std::string, int> defined_var;
71 
72  /// enable debug output in the flex scanner
73  bool trace_scanner = false;
74 
75  /// enable debug output in the bison parser
76  bool trace_parser = true;
77 
78  /// print messages from lexer/parser
79  bool verbose = false;
80 
81  /// root of the ast
82  std::shared_ptr<ast::Program> astRoot = nullptr;
83 
84  /// The file library for IMPORT directives
86 
87  /// The list of open files, and the location of the request.
88  /// \a nullptr is pushed as location for the top NMODL file
89  std::unordered_map<std::string, const location*> open_files;
90 
91  /// The stream where Bison will dump its logs
92  std::ostringstream parser_stream;
93 
94  public:
95  /// file or input stream name (used by scanner for position), see todo
96  std::string stream_name;
97 
98  NmodlDriver() = default;
99  NmodlDriver(bool strace, bool ptrace);
100 
101  /// add macro definition and it's value (DEFINE keyword of nmodl)
102  void add_defined_var(const std::string& name, int value);
103 
104  /// check if particular text is defined as macro
105  bool is_defined_var(const std::string& name) const;
106 
107  /// return variable's value defined as macro (always an integer)
108  int get_defined_var_value(const std::string& name) const;
109 
110  std::shared_ptr<ast::Program> parse_stream(std::istream& in);
111 
112  /// parser nmodl provided as string (used for testing)
113  std::shared_ptr<ast::Program> parse_string(const std::string& input);
114 
115  /**
116  * \brief parse NMODL file
117  * \param filename path to the file to parse
118  * \param loc optional location when \a filename is dictated
119  * by an `INCLUDE` NMODL directive.
120  */
121  std::shared_ptr<ast::Program> parse_file(const std::filesystem::path& filename,
122  const location* loc = nullptr);
123  //// parse file specified in nmodl include directive
124  std::shared_ptr<ast::Include> parse_include(const std::filesystem::path& filename,
125  const location& loc);
126 
127  void set_verbose(bool b) {
128  verbose = b;
129  }
130 
131  bool is_verbose() const noexcept {
132  return verbose;
133  }
134 
135  /// return previously parsed AST otherwise nullptr
136  const std::shared_ptr<ast::Program>& get_ast() const noexcept {
137  return astRoot;
138  }
139 
140  /// set new ast root
141  void set_ast(ast::Program* node) noexcept {
142  astRoot.reset(node);
143  }
144 
145  /**
146  * Emit a parsing error
147  * \throw std::runtime_error
148  */
149  void parse_error(const location& location, const std::string& message);
150 
151  /**
152  * Emit a parsing error. Takes additionally a Lexer instance to print code context
153  * \throw std::runtime_error
154  */
155  void parse_error(const NmodlLexer& scanner,
156  const location& location,
157  const std::string& message);
158 
159  /**
160  * Ensure \a file argument given to the INCLUDE directive is valid:
161  * - between double-quotes
162  * - not empty ""
163  *
164  * \return unquoted string
165  */
166  std::string check_include_argument(const location& location, const std::string& filename);
167 };
168 
169 /** \} */ // end of parser
170 
171 } // namespace parser
172 } // namespace nmodl
nmodl::parser::NmodlDriver
Class that binds all pieces together for parsing nmodl file.
Definition: nmodl_driver.hpp:67
nmodl::parser::NmodlDriver::NmodlDriver
NmodlDriver()=default
nmodl::parser::NmodlDriver::set_ast
void set_ast(ast::Program *node) noexcept
set new ast root
Definition: nmodl_driver.hpp:141
nmodl::parser::NmodlDriver::parse_include
std::shared_ptr< ast::Include > parse_include(const std::filesystem::path &filename, const location &loc)
Definition: nmodl_driver.cpp:95
nmodl::parser::NmodlDriver::stream_name
std::string stream_name
file or input stream name (used by scanner for position), see todo
Definition: nmodl_driver.hpp:96
nmodl::parser::NmodlDriver::get_ast
const std::shared_ptr< ast::Program > & get_ast() const noexcept
return previously parsed AST otherwise nullptr
Definition: nmodl_driver.hpp:136
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
nmodl::parser::NmodlDriver::parser_stream
std::ostringstream parser_stream
The stream where Bison will dump its logs.
Definition: nmodl_driver.hpp:92
nmodl::parser::NmodlDriver::trace_scanner
bool trace_scanner
enable debug output in the flex scanner
Definition: nmodl_driver.hpp:73
file_library.hpp
Manage search path.
nmodl::parser::NmodlDriver::get_defined_var_value
int get_defined_var_value(const std::string &name) const
return variable's value defined as macro (always an integer)
Definition: nmodl_driver.cpp:141
nmodl::parser::NmodlDriver::add_defined_var
void add_defined_var(const std::string &name, int value)
add macro definition and it's value (DEFINE keyword of nmodl)
Definition: nmodl_driver.cpp:133
nmodl::parser::NmodlDriver::parse_stream
std::shared_ptr< ast::Program > parse_stream(std::istream &in)
parse nmodl file provided as istream
Definition: nmodl_driver.cpp:26
nmodl::parser::NmodlDriver::check_include_argument
std::string check_include_argument(const location &location, const std::string &filename)
Ensure file argument given to the INCLUDE directive is valid:
Definition: nmodl_driver.cpp:168
nmodl::parser::NmodlDriver::parse_file
std::shared_ptr< ast::Program > parse_file(const std::filesystem::path &filename, const location *loc=nullptr)
parse NMODL file
Definition: nmodl_driver.cpp:43
nmodl::parser::NmodlDriver::parse_error
void parse_error(const location &location, const std::string &message)
Emit a parsing error.
Definition: nmodl_driver.cpp:149
nmodl::parser::NmodlLexer
Represent Lexer/Scanner class for NMODL language parsing.
Definition: nmodl_lexer.hpp:60
nmodl::parser::NmodlDriver::set_verbose
void set_verbose(bool b)
Definition: nmodl_driver.hpp:127
include.hpp
Auto generated AST classes declaration.
nmodl::parser::NmodlDriver::trace_parser
bool trace_parser
enable debug output in the bison parser
Definition: nmodl_driver.hpp:76
nmodl::parser::NmodlDriver::is_defined_var
bool is_defined_var(const std::string &name) const
check if particular text is defined as macro
Definition: nmodl_driver.cpp:137
nmodl::parser::NmodlDriver::is_verbose
bool is_verbose() const noexcept
Definition: nmodl_driver.hpp:131
nmodl::FileLibrary::default_instance
static FileLibrary default_instance()
Initialize the library with the following path:
Definition: file_library.cpp:21
nmodl::FileLibrary
Manage search path.
Definition: file_library.hpp:30
nmodl::parser::NmodlDriver::library
FileLibrary library
The file library for IMPORT directives.
Definition: nmodl_driver.hpp:85
nmodl::parser::NmodlDriver::parse_string
std::shared_ptr< ast::Program > parse_string(const std::string &input)
parser nmodl provided as string (used for testing)
Definition: nmodl_driver.cpp:89
nmodl::parser::NmodlDriver::astRoot
std::shared_ptr< ast::Program > astRoot
root of the ast
Definition: nmodl_driver.hpp:82
nmodl::parser::NmodlDriver::verbose
bool verbose
print messages from lexer/parser
Definition: nmodl_driver.hpp:79
nmodl::parser::NmodlDriver::defined_var
std::unordered_map< std::string, int > defined_var
all macro defined in the mod file
Definition: nmodl_driver.hpp:70
nmodl::ast::Program
Represents top level AST node for whole NMODL input.
Definition: program.hpp:39
nmodl::parser::NmodlDriver::open_files
std::unordered_map< std::string, const location * > open_files
The list of open files, and the location of the request.
Definition: nmodl_driver.hpp:89