123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357 |
- // Copyright (C) 2015-2017 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 ...
- #define YY_DECL isc::dhcp::Dhcp6Parser::symbol_type parser6_lex (Parser6Context& driver)
- // ... and declare it for the parser's sake.
- YY_DECL;
- namespace isc {
- namespace dhcp {
- /// @brief Evaluation error exception raised when trying to parse.
- ///
- /// @todo: This probably should be common for Dhcp4 and Dhcp6.
- class Dhcp6ParseError : public isc::Exception {
- public:
- Dhcp6ParseError(const char* file, size_t line, const char* what) :
- isc::Exception(file, line, what) { };
- };
- /// @brief Evaluation context, an interface to the expression evaluation.
- class Parser6Context
- {
- public:
- /// @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 PARSER_HOST_RESERVATION6.
- typedef enum {
- /// This parser will parse the content as generic JSON.
- PARSER_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 (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.
- SUBPARSER_DHCP6,
- /// This will parse the input as interfaces content.
- PARSER_INTERFACES,
- /// This will parse the input as Subnet6 content.
- PARSER_SUBNET6,
- /// This will parse the input as pool6 content.
- PARSER_POOL6,
- /// This will parse the input as pd-pool content.
- PARSER_PD_POOL,
- /// This will parse the input as host-reservation.
- PARSER_HOST_RESERVATION,
- /// This will parse the input as option definition.
- PARSER_OPTION_DEF,
- /// This will parse the input as option data.
- PARSER_OPTION_DATA,
- /// This will parse the input as hooks-library.
- PARSER_HOOKS_LIBRARY,
- /// This will parse the input as dhcp-ddns. (D2 client config)
- PARSER_DHCP_DDNS
- } ParserType;
- /// @brief Default constructor.
- Parser6Context();
- /// @brief destructor
- virtual ~Parser6Context();
- /// @brief JSON elements being parsed.
- std::vector<isc::data::ElementPtr> stack_;
- /// @brief Method called before scanning starts on a string.
- ///
- /// @param str string to be parsed
- /// @param type specifies expected content
- void scanStringBegin(const std::string& str, ParserType type);
- /// @brief Method called before scanning starts on a file.
- ///
- /// @param f stdio FILE pointer
- /// @param filename file to be parsed
- /// @param type specifies expected content
- void scanFileBegin(FILE* f, const std::string& filename, ParserType type);
- /// @brief Method called after the last tokens are scanned.
- void scanEnd();
- /// @brief Divert input to an include file.
- ///
- /// @param filename file to be included
- void includeFile(const std::string& filename);
- /// @brief Run the parser on the string specified.
- ///
- /// 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.
- ///
- /// @param str string to be parsed
- /// @param parser_type specifies expected content (usually DHCP6 or generic JSON)
- /// @return Element structure representing parsed text.
- isc::data::ElementPtr parseString(const std::string& str,
- ParserType parser_type);
- /// @brief Run the parser on the file specified.
- ///
- /// 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.
- isc::data::ElementPtr parseFile(const std::string& filename,
- ParserType parser_type);
- /// @brief Error handler
- ///
- /// @param loc location within the parsed file when experienced a problem.
- /// @param what string explaining the nature of the error.
- /// @throw Dhcp6ParseError
- void error(const isc::dhcp::location& loc, const std::string& what);
- /// @brief Error handler
- ///
- /// This is a simplified error reporting tool for possible future
- /// cases when the Dhcp6Parser is not able to handle the packet.
- ///
- /// @param what string explaining the nature of the error.
- /// @throw Dhcp6ParseError
- void error(const std::string& what);
- /// @brief Fatal error handler
- ///
- /// This is for should not happen but fatal errors.
- /// Used by YY_FATAL_ERROR macro so required to be static.
- ///
- /// @param what string explaining the nature of the error.
- /// @throw Dhcp6ParseError
- static void fatal(const std::string& what);
- /// @brief Converts bison's position to one understandable by isc::data::Element
- ///
- /// Convert a bison location into an element position
- /// (take the begin, the end is lost)
- ///
- /// @param loc location in bison format
- /// @return Position in format accepted by Element
- isc::data::Element::Position loc2pos(isc::dhcp::location& loc);
- /// @brief Defines syntactic contexts for lexical tie-ins
- typedef enum {
- ///< This one is used in pure JSON mode.
- NO_KEYWORD,
- ///< Used while parsing top level (that contains Dhcp6, Logging and others)
- CONFIG,
- ///< Used while parsing content of Dhcp6.
- DHCP6,
- // not yet Dhcp4, DhcpDdns,
- ///< Used while parsing content of Logging
- LOGGING,
- /// Used while parsing Dhcp6/interfaces structures.
- INTERFACES_CONFIG,
- /// Used while parsing Dhcp6/lease-database structures.
- LEASE_DATABASE,
- /// Used while parsing Dhcp6/hosts-database structures.
- HOSTS_DATABASE,
- /// Used while parsing Dhcp6/*-database/type.
- DATABASE_TYPE,
- /// Used while parsing Dhcp6/mac-sources structures.
- MAC_SOURCES,
- /// Used while parsing Dhcp6/host-reservation-identifiers.
- HOST_RESERVATION_IDENTIFIERS,
- /// Used while parsing Dhcp6/hooks-libraries.
- HOOKS_LIBRARIES,
- /// Used while parsing Dhcp6/Subnet6 structures.
- SUBNET6,
- /// Used while parsing Dhcp6/Subnet6/reservation-mode.
- RESERVATION_MODE,
- /// Used while parsing Dhcp6/option-def structures.
- OPTION_DEF,
- /// Used while parsing Dhcp6/option-data, Dhcp6/subnet6/option-data
- /// or anywhere option-data is present (client classes, host
- /// reservations and possibly others).
- OPTION_DATA,
- /// Used while parsing Dhcp6/client-classes structures.
- CLIENT_CLASSES,
- /// Used while parsing Dhcp6/expired-leases-processing.
- EXPIRED_LEASES_PROCESSING,
- /// Used while parsing Dhcp6/server-id structures.
- SERVER_ID,
- /// Used while parsing Dhcp6/server-id/type structures.
- DUID_TYPE,
- /// Used while parsing Dhcp6/control-socket structures.
- CONTROL_SOCKET,
- /// Used while parsing Dhcp6/subnet6/pools structures.
- POOLS,
- /// Used while parsing Dhcp6/subnet6/pd-pools structures.
- PD_POOLS,
- /// Used while parsing Dhcp6/reservations structures.
- RESERVATIONS,
- /// Used while parsing Dhcp6/subnet6/relay structures.
- RELAY,
- /// Used while parsing Dhcp6/client-classes structures.
- CLIENT_CLASS,
- /// Used while parsing Logging/loggers structures.
- LOGGERS,
- /// Used while parsing Logging/loggers/output_options structures.
- OUTPUT_OPTIONS,
- /// Used while parsing Dhcp6/dhcp-ddns.
- DHCP_DDNS,
- /// Used while parsing Dhcp6/dhcp-ddns/ncr-protocol
- NCR_PROTOCOL,
- /// Used while parsing Dhcp6/dhcp-ddns/ncr-format
- NCR_FORMAT,
- /// Used while parsing Dhcp6/dhcp-ddns/replace-client-name.
- REPLACE_CLIENT_NAME
- } ParserContext;
- /// @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_;
- /// @brief Lexer state stack
- std::vector<struct yy_buffer_state*> states_;
- /// @brief sFile (aka FILE)
- FILE* sfile_;
- /// @brief sFile (aka FILE) stack
- ///
- /// 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.
- std::vector<FILE*> sfiles_;
- /// @brief Current syntactic context
- ParserContext ctx_;
- /// @brief Enter a new syntactic context
- ///
- /// Entering a new 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 syntactic context allows the
- /// error message to be more descriptive if the input string
- /// does not parse properly.
- ///
- /// @param ctx the syntactic context to enter into
- void enter(const ParserContext& ctx);
- /// @brief Leave a syntactic context
- ///
- /// @throw isc::Unexpected if unbalanced
- void leave();
- /// @brief Get the syntactic context name
- ///
- /// @return printable name of the context.
- const std::string contextName();
- private:
- /// @brief Flag determining scanner debugging.
- bool trace_scanning_;
- /// @brief Flag determining parser debugging.
- bool trace_parsing_;
- /// @brief Syntactic context stack
- std::vector<ParserContext> cstack_;
- /// @brief Common part of parseXXX
- ///
- /// @return Element structure representing parsed text.
- isc::data::ElementPtr parseCommon();
- };
- }; // end of isc::eval namespace
- }; // end of isc namespace
- #endif
|