User Guide
nmodl_lexer.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 Lexer implementations
13  */
14 
15 #include "ast/ast.hpp"
16 #include "parser/nmodl/nmodl_parser.hpp"
17 
18 
19 /**
20  * Flex expects the declaration of yylex() to be defined in the macro YY_DECL
21  * and C++ parser class expects it to be declared.
22  */
23 #ifndef YY_DECL
24 #define YY_DECL nmodl::parser::NmodlParser::symbol_type nmodl::parser::NmodlLexer::next_token()
25 #endif
26 
27 /**
28  * For creating multiple (different) lexer classes, we can use `-P` flag
29  * (or prefix option) to rename each `NmodlFlexLexer` to some other name like
30  * `xxFlexLexer`. And then include <FlexLexer.h> in other sources once per
31  * lexer class, first renaming `yyFlexLexer` as shown below.
32  */
33 #ifndef __FLEX_LEXER_H
34 #define yyFlexLexer NmodlFlexLexer
35 #include "FlexLexer.h"
36 #endif
37 
38 namespace nmodl {
39 namespace parser {
40 
41 /**
42  * @defgroup lexer Lexer Implementation
43  * @brief All lexer classes implementation
44  *
45  * @addtogroup lexer
46  * @{
47  */
48 
49 /**
50  * \class NmodlLexer
51  * \brief Represent Lexer/Scanner class for NMODL language parsing
52  *
53  * Lexer defined to add some extra function to the scanner class from flex.
54  * Flex itself creates yyFlexLexer class, which we renamed using macros to
55  * NmodlFlexLexer. But we change the context of the generated yylex() function
56  * because the yylex() defined in NmodlFlexLexer has no parameters. Also, note
57  * that implementation of the member functions are in nmodl.l file due to use
58  * of macros.
59  */
60 class NmodlLexer: public NmodlFlexLexer {
61  /**
62  * \brief Reference to driver object where this lexer resides
63  *
64  * The driver object is used for macro definitions and error checking
65  */
67 
68  /// Units are stored in the scanner (could be stored in the driver though)
69  ast::String* last_unit = nullptr;
70 
71  /**
72  * \brief Context of the reaction (`~`) token
73  *
74  * For reaction (`~`) we return different token based on one of the following
75  * lexical context:
76  * - NONLINEAR
77  * - LINEAR
78  * - KINETIC
79  */
80  int lexical_context = 0;
81 
82  std::string cur_line;
83 
84  public:
85  /// location of the parsed token
86  location loc;
87 
88  /// \name Ctor & dtor
89  /// \{
90 
91  /**
92  * \brief NmodlLexer constructor
93  *
94  * @param driver NmodlDriver where this lexer resides
95  * @param in Input stream from where tokens will be read
96  * @param out Output stream where output will be sent
97  */
99  std::istream* in = nullptr,
100  std::ostream* out = nullptr)
101  : NmodlFlexLexer(in, out)
102  , driver(driver) {}
103 
104  ~NmodlLexer() override = default;
105 
106  /// \}
107 
108  /**
109  * \brief Reset the column position of lexer to 0
110  *
111  * Due to COPY mode the end position is not accurate. Set column to 0 to
112  * avoid confusion (see JIRA issue NOCMODL-25)
113  */
115  loc.end.column = 0;
116  }
117 
118  /**
119  * \brief Function for lexer to scan token (replacement for \c yylex())
120  *
121  * This is main lexing function generated by `flex` according to the macro
122  * declaration \c YY_DECL. The generated bison parser then calls this virtual
123  * function to fetch new tokens. Note that \c yylex() has different declaration
124  * and hence can't be used for new lexer.
125  *
126  * @return Symbol encapsulating parsed token
127  */
129 
130  /**
131  * \brief Scan subsequent text as unit
132  *
133  * For units we have to consume string until end of closing parenthesis
134  * and store it in the scanner. This will be later returned by get_unit().
135  */
136  void scan_unit();
137 
138  /**
139  * \brief Input text until end of line
140  *
141  * For construct like TITLE we have to scan text until end of line
142  */
143  std::string input_line();
144 
145  /// Return last scanned unit as ast::String
147 
148  /// Return current line as string
149  std::string get_curr_line() const;
150 
151  /// Enable debug output (via yyout) if compiled into the scanner.
152  void set_debug(bool b);
153 };
154 
155 /** @} */ // end of lexer
156 
157 } // namespace parser
158 } // namespace nmodl
nmodl::parser::NmodlDriver
Class that binds all pieces together for parsing nmodl file.
Definition: nmodl_driver.hpp:67
nmodl::parser::NmodlLexer::~NmodlLexer
~NmodlLexer() override=default
nmodl::parser::NmodlLexer::NmodlLexer
NmodlLexer(NmodlDriver &driver, std::istream *in=nullptr, std::ostream *out=nullptr)
NmodlLexer constructor.
Definition: nmodl_lexer.hpp:98
nmodl::parser::NmodlLexer::last_unit
ast::String * last_unit
Units are stored in the scanner (could be stored in the driver though)
Definition: nmodl_lexer.hpp:69
nmodl::parser::NmodlLexer::loc
location loc
location of the parsed token
Definition: nmodl_lexer.hpp:86
nmodl
encapsulates code generation backend implementations
Definition: ast_common.hpp:26
nmodl::parser::NmodlLexer::get_unit
ast::String * get_unit()
Return last scanned unit as ast::String.
nmodl::parser::NmodlLexer::reset_end_position
void reset_end_position()
Reset the column position of lexer to 0.
Definition: nmodl_lexer.hpp:114
nmodl::parser::NmodlLexer::cur_line
std::string cur_line
Definition: nmodl_lexer.hpp:82
nmodl::parser::NmodlLexer::set_debug
void set_debug(bool b)
Enable debug output (via yyout) if compiled into the scanner.
nmodl::parser::NmodlLexer::lexical_context
int lexical_context
Context of the reaction (~) token.
Definition: nmodl_lexer.hpp:80
nmodl::parser::NmodlLexer
Represent Lexer/Scanner class for NMODL language parsing.
Definition: nmodl_lexer.hpp:60
ast.hpp
Auto generated AST classes declaration.
nmodl::parser::NmodlLexer::next_token
virtual NmodlParser::symbol_type next_token()
Function for lexer to scan token (replacement for yylex())
nmodl::parser::NmodlLexer::get_curr_line
std::string get_curr_line() const
Return current line as string.
nmodl::parser::NmodlLexer::driver
NmodlDriver & driver
Reference to driver object where this lexer resides.
Definition: nmodl_lexer.hpp:66
symbol_type
void symbol_type(const std::string &name, T &value)
Definition: modtoken.cpp:32
nmodl::parser::NmodlLexer::input_line
std::string input_line()
Input text until end of line.
nmodl::ast::String
Represents a string.
Definition: string.hpp:52
nmodl::parser::NmodlLexer::scan_unit
void scan_unit()
Scan subsequent text as unit.