parser_context.h 9.97 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
// Copyright (C) 2015-2016 Internet Systems Consortium, Inc. ("ISC")
//
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

#ifndef PARSER_CONTEXT_H
#define PARSER_CONTEXT_H
#include <string>
#include <map>
#include <vector>
#include <dhcp6/dhcp6_parser.h>
#include <dhcp6/parser_context_decl.h>
#include <exceptions/exceptions.h>

// Tell Flex the lexer's prototype ...
17
#define YY_DECL isc::dhcp::Dhcp6Parser::symbol_type parser6_lex (Parser6Context& driver)
18 19 20 21 22 23 24

// ... and declare it for the parser's sake.
YY_DECL;

namespace isc {
namespace dhcp {

25
/// @brief Evaluation error exception raised when trying to parse.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
26 27
///
/// @todo: This probably should be common for Dhcp4 and Dhcp6.
28
class Dhcp6ParseError : public isc::Exception {
29
public:
30
    Dhcp6ParseError(const char* file, size_t line, const char* what) :
31 32 33 34 35 36 37 38
        isc::Exception(file, line, what) { };
};


/// @brief Evaluation context, an interface to the expression evaluation.
class Parser6Context
{
public:
39

Tomek Mrugalski's avatar
Tomek Mrugalski committed
40 41 42 43 44 45 46 47 48
    /// @brief Defines currently supported scopes
    ///
    /// Dhcp6Parser is able to parse several types of scope. Usually, when it
    /// parses a config file, it expects the data to have a map with Dhcp6 in it
    /// and all the parameters within that Dhcp6 map. However, sometimes the
    /// parser is expected to parse only a subset of that information. For example,
    /// it may be asked to parse a structure that is host-reservation only, without
    /// the global 'Dhcp6' or 'reservations' around it. In such case the parser
    /// is being told to start parsing as SUBPARSER_HOST_RESERVATION6.
49
    typedef enum {
Tomek Mrugalski's avatar
Tomek Mrugalski committed
50
        /// This parser will parse the content as generic JSON.
51
        PARSER_JSON,
Tomek Mrugalski's avatar
Tomek Mrugalski committed
52

53 54
        /// This parser will parse the content as Dhcp6 config wrapped in a map
        /// (that's the regular config file)
Tomek Mrugalski's avatar
Tomek Mrugalski committed
55 56
        PARSER_DHCP6,

57 58 59 60
        /// This parser will parse the content of Dhcp6 (without outer { } and
        /// without "Dhcp6"). It is mostly used in unit-tests as most of the
        /// unit-tests do not define the outer map and Dhcp6 entity, just the
        /// contents of it.
61
        SUBPARSER_DHCP6,
Tomek Mrugalski's avatar
Tomek Mrugalski committed
62

63
        /// This will parse the input as Subnet6 content.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
64 65
        PARSER_SUBNET6,

66
        /// This will parse the input as pool6 content.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
67 68
        PARSER_POOL6,

69
        /// This will parse the input as interfaces content.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
70 71
        PARSER_INTERFACES,

72
        /// This will parse the input as pd-pool content.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
73 74
        PARSER_PD_POOL,

75
        /// This will parse the input as host-reservation.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
76 77
        PARSER_HOST_RESERVATION,

78
        /// This will parse the input as option definition.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
79 80
        PARSER_OPTION_DEF,

81
        /// This will parse the input as option data.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
82 83
        PARSER_OPTION_DATA,

84
        /// This will parse the input as hooks-library.
Tomek Mrugalski's avatar
Tomek Mrugalski committed
85
        PARSER_HOOKS_LIBRARY
86
    } ParserType;
87

88 89 90 91 92 93 94
    /// @brief Default constructor.
    Parser6Context();

    /// @brief destructor
    virtual ~Parser6Context();

    /// @brief JSON elements being parsed.
95
    std::vector<isc::data::ElementPtr> stack_;
96 97

    /// @brief Method called before scanning starts on a string.
98
    void scanStringBegin(const std::string& str, ParserType type);
99

100
    /// @brief Method called before scanning starts on a file.
Francis Dupont's avatar
Francis Dupont committed
101
    void scanFileBegin(FILE * f, const std::string& filename, ParserType type);
102

103 104
    /// @brief Method called after the last tokens are scanned.
    void scanEnd();
105

Francis Dupont's avatar
Francis Dupont committed
106
    /// @brief Divert input to an include file.
107
    void includeFile(const std::string& filename);
Francis Dupont's avatar
Francis Dupont committed
108

109 110
    /// @brief Run the parser on the string specified.
    ///
111 112 113 114 115
    /// This method parses specified string. Depending on the value of
    /// parser_type, parser may either check only that the input is valid
    /// JSON, or may do more specific syntax checking. See @ref ParserType
    /// for supported syntax checkers.
    ///
116
    /// @param str string to be parsed
117 118
    /// @param parser_type specifies expected content (usually DHCP6 or generic JSON)
    /// @return Element structure representing parsed text.
119 120
    isc::data::ConstElementPtr parseString(const std::string& str,
                                           ParserType parser_type);
121

122
    /// @brief Run the parser on the file specified.
123 124 125 126 127 128 129 130 131
    ///
    /// This method parses specified file. Depending on the value of
    /// parser_type, parser may either check only that the input is valid
    /// JSON, or may do more specific syntax checking. See @ref ParserType
    /// for supported syntax checkers.
    ///
    /// @param filename file to be parsed
    /// @param parser_type specifies expected content (usually DHCP6 or generic JSON)
    /// @return Element structure representing parsed text.
132 133
    isc::data::ConstElementPtr parseFile(const std::string& filename,
                                         ParserType parser_type);
134

135 136 137 138
    /// @brief Error handler
    ///
    /// @param loc location within the parsed file when experienced a problem.
    /// @param what string explaining the nature of the error.
139
    void error(const isc::dhcp::location& loc, const std::string& what);
140 141 142 143

    /// @brief Error handler
    ///
    /// This is a simplified error reporting tool for possible future
144
    /// cases when the Dhcp6Parser is not able to handle the packet.
145
    void error(const std::string& what);
146 147 148

    /// @brief Fatal error handler
    ///
149 150
    /// This is for should not happen but fatal errors.
    /// Used by YY_FATAL_ERROR macro so required to be static.
151 152
    static void fatal(const std::string& what);

Tomek Mrugalski's avatar
Tomek Mrugalski committed
153
    /// @brief Converts bison's position to one understandable by isc::data::Element
154 155 156
    ///
    /// Convert a bison location into an element position
    /// (take the begin, the end is lost)
157 158
    /// @brief loc location in bison format
    /// @return Position in format accepted by Element
159 160
    isc::data::Element::Position loc2pos(isc::dhcp::location& loc);

161 162
    /// @brief Defines syntactic contexts for lexical tie-ins
    typedef enum {
163
        ///< This one is used in pure JSON mode.
164
        NO_KEYWORD,
165 166

        ///< Used while parsing top level (that contains Dhcp6, Logging and others)
167
        CONFIG,
168 169

        ///< Used while parsing content of Dhcp6.
170
        DHCP6,
171

172 173
        // not yet DHCP4,
        // not yet DHCP_DDNS,
174 175

        ///< Used while parsing content of Logging
176
        LOGGING,
177 178

        /// Used while parsing Dhcp6/interfaces structures.
179
        INTERFACES_CONFIG,
180 181

        /// Used while parsing Dhcp6/hosts-database structures.
182
        HOSTS_DATABASE,
183 184 185 186 187

        /// Used while parsing Dhcp6/lease-database structures.
        LEASE_DATABASE,

        /// Used while parsing Dhcp6/mac-sources structures.
188
        MAC_SOURCES,
189 190

        /// Used while parsing Dhcp6/host-reservation-identifiers.
191
        HOST_RESERVATION_IDENTIFIERS,
192 193

        /// Used while parsing Dhcp6/hooks-libraries.
194
        HOOKS_LIBRARIES,
195 196

        /// Used while parsing Dhcp6/Subnet6 structures.
197
        SUBNET6,
198 199

        /// Used while parsing Dhcp6/option-def structures.
200
        OPTION_DEF,
201 202 203 204

        /// Used while parsing Dhcp6/option-data, Dhcp6/subnet6/option-data
        /// or anywhere option-data is present (client classes, host
        /// reservations and possibly others).
205
        OPTION_DATA,
206 207

        /// Used while parsing Dhcp6/client-classes structures.
208
        CLIENT_CLASSES,
209 210

        /// Used while parsing Dhcp6/server-id structures.
211
        SERVER_ID,
212 213

        /// Used while parsing Dhcp6/control-socket structures.
214
        CONTROL_SOCKET,
215 216

        /// Used while parsing Dhcp6/subnet6/pools structures.
217
        POOLS,
218 219

        /// Used while parsing Dhcp6/subnet6/pd-pools structures.
220
        PD_POOLS,
221 222

        /// Used while parsing Dhcp6/reservations structures.
223
        RESERVATIONS,
224 225

        /// Used while parsing Dhcp6/subnet6/relay structures.
226
        RELAY,
227 228

        /// Used while parsing Dhcp6/client-classes structures.
229
        CLIENT_CLASS,
230 231

        /// Used while parsing Logging/loggers structures.
232
        LOGGERS,
233 234

        /// Used while parsing Logging/loggers/output_options structures.
235
        OUTPUT_OPTIONS
236
    } ParserContext;
237

238 239 240 241 242 243 244 245 246 247 248 249 250 251 252
    /// @brief File name
    std::string file_;

    /// @brief File name stack
    std::vector<std::string> files_;

    /// @brief Location of the current token
    ///
    /// The lexer will keep updating it. This variable will be useful
    /// for logging errors.
    isc::dhcp::location loc_;

    /// @brief Location stack
    std::vector<isc::dhcp::location> locs_;

253
    /// @brief Lexer state stack
Tomek Mrugalski's avatar
Tomek Mrugalski committed
254
    std::vector<struct yy_buffer_state*> states_;
255

256 257 258 259
    /// @brief sFile (aka FILE)
    FILE* sfile_;

    /// @brief sFile (aka FILE) stack
260 261 262 263
    ///
    /// This is a stack of files. Typically there's only one file (the
    /// one being currently parsed), but there may be more if one
    /// file includes another.
264 265
    std::vector<FILE*> sfiles_;

266 267 268 269
    /// @brief Current syntactic context
    ParserContext ctx_;

    /// @brief Enter a new syntactic context
270 271 272 273 274 275 276 277
    ///
    /// Entering a nex syntactic context is useful in several ways.
    /// First, it allows the parser to avoid conflicts. Second, it
    /// allows the lexer to return different tokens depending on
    /// context (e.g. if "renew-timer" string is detected, the lexer
    /// will return STRING token if in JSON mode or RENEW_TIMER if
    /// in DHCP6 mode. Finally, the stntactic context allows the
    /// error message to be more descriptive.
278 279 280 281 282 283
    void enter(const ParserContext& ctx);

    /// @brief Leave a syntactic context
    /// @throw isc::Unexpected if unbalanced
    void leave();

284
    /// @brief Get the syntactix context name
285 286
    /// @return printable name of the context.
    const std::string contextName();
287

288 289 290 291 292 293
 private:
    /// @brief Flag determining scanner debugging.
    bool trace_scanning_;

    /// @brief Flag determing parser debugging.
    bool trace_parsing_;
294 295 296

    /// @brief Syntactic context stack
    std::vector<ParserContext> cstack_;
297 298 299

    /// @brief Common part of parseXXX
    isc::data::ConstElementPtr parseCommon();
300 301 302 303 304 305
};

}; // end of isc::eval namespace
}; // end of isc namespace

#endif