parser_context.h 7.1 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 51 52 53 54 55 56 57 58 59 60 61
        /// This parser will parse the content as generic JSON.
        //PARSER_GENERIC_JSON,

        SUBPARSER_JSON,

        /// This parser will parse the content as Dhcp6 config wrapped in a map (that's
        /// the regular config file)
        PARSER_DHCP6,

        /// This parser will parse the content of 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.
62
        SUBPARSER_DHCP6,
Tomek Mrugalski's avatar
Tomek Mrugalski committed
63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86

        /// This will parse the conde as Subnet6 content.
        PARSER_SUBNET6,

        /// This parser will parse pool6 content.
        PARSER_POOL6,

        /// This parser will parse the interfaces content.
        PARSER_INTERFACES,

        /// This parser will parse the content as pd-pool.
        PARSER_PD_POOL,

        /// This parser will parse the content as host-reservation
        PARSER_HOST_RESERVATION,

        /// This parser will parse the content as option definition.
        PARSER_OPTION_DEF,

        /// This parser will parse the content as option data.
        PARSER_OPTION_DATA,

        /// This parser will parse the content as hooks-library
        PARSER_HOOKS_LIBRARY
87
    } ParserType;
88

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

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

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

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

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

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

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

110 111
    /// @brief Run the parser on the string specified.
    ///
112 113
    /// @param str string to be parsed
    /// @param parser_type specifies expected content (either DHCP6 or generic JSON)
114
    /// @return true on success.
115 116
    isc::data::ConstElementPtr parseString(const std::string& str,
                                           ParserType parser_type);
117

118
    /// @brief Run the parser on the file specified.
119 120
    isc::data::ConstElementPtr parseFile(const std::string& filename,
                                         ParserType parser_type);
121

122 123 124 125
    /// @brief Error handler
    ///
    /// @param loc location within the parsed file when experienced a problem.
    /// @param what string explaining the nature of the error.
126
    void error(const isc::dhcp::location& loc, const std::string& what);
127 128 129 130

    /// @brief Error handler
    ///
    /// This is a simplified error reporting tool for possible future
131
    /// cases when the Dhcp6Parser is not able to handle the packet.
132
    void error(const std::string& what);
133 134 135

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

Tomek Mrugalski's avatar
Tomek Mrugalski committed
140
    /// @brief Converts bison's position to one understandable by isc::data::Element
141 142 143 144 145
    ///
    /// Convert a bison location into an element position
    /// (take the begin, the end is lost)
    isc::data::Element::Position loc2pos(isc::dhcp::location& loc);

146 147 148 149 150 151 152 153 154 155 156 157
    /// @brief Defines syntactic contexts for lexical tie-ins
    typedef enum {
        /// at toplevel
        NO_KEYWORD,
        CONFIG,
        /// in config
        DHCP6,
        // not yet DHCP4,
        // not yet DHCP_DDNS,
        LOGGING,
        /// Dhcp6
        INTERFACES_CONFIG,
158 159
        LEASE_DATABASE,
        HOSTS_DATABASE,
160 161 162 163
        MAC_SOURCES,
        HOST_RESERVATION_IDENTIFIERS,
        HOOKS_LIBRARIES,
        SUBNET6,
164
        OPTION_DEF,
165 166 167
        OPTION_DATA,
        CLIENT_CLASSES,
        SERVER_ID,
168
        CONTROL_SOCKET,
169 170 171 172
        /// subnet6
        POOLS,
        PD_POOLS,
        RESERVATIONS,
173
        RELAY,
174 175
        /// client-classes
        CLIENT_CLASS,
176 177 178 179 180 181
        /// Logging
        LOGGERS,
        /// loggers
        OUTPUT_OPTIONS
    } ParserContext;    

182 183 184 185 186 187 188 189 190 191 192 193 194 195 196
    /// @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_;

197
    /// @brief Lexer state stack
Tomek Mrugalski's avatar
Tomek Mrugalski committed
198
    std::vector<struct yy_buffer_state*> states_;
199

200 201 202 203 204 205
    /// @brief sFile (aka FILE)
    FILE* sfile_;

    /// @brief sFile (aka FILE) stack
    std::vector<FILE*> sfiles_;

206 207 208 209 210 211 212 213 214 215
    /// @brief Current syntactic context
    ParserContext ctx_;

    /// @brief Enter a new syntactic context
    void enter(const ParserContext& ctx);

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

216 217 218
    /// @brief Get the syntactix context name
    const std::string context_name();

219 220 221 222 223 224
 private:
    /// @brief Flag determining scanner debugging.
    bool trace_scanning_;

    /// @brief Flag determing parser debugging.
    bool trace_parsing_;
225 226 227

    /// @brief Syntactic context stack
    std::vector<ParserContext> cstack_;
228 229 230

    /// @brief Common part of parseXXX
    isc::data::ConstElementPtr parseCommon();
231 232 233 234 235 236
};

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

#endif