parser_context.cc 3.82 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
// Copyright (C) 2018 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/.

#include <config.h>

#include <netconf/parser_context.h>
#include <netconf/netconf_parser.h>
#include <exceptions/exceptions.h>
//#include <cc/dhcp_config_error.h>
#include <cc/data.h>
#include <fstream>
#include <limits>

namespace isc {
namespace netconf {

ParserContext::ParserContext()
  : sfile_(0), ctx_(NO_KEYWORDS), trace_scanning_(false), trace_parsing_(false)
{
}

ParserContext::~ParserContext()
{
}

isc::data::ElementPtr
ParserContext::parseString(const std::string& str, ParserType parser_type)
{
    scanStringBegin(str, parser_type);
    return (parseCommon());
}

isc::data::ElementPtr
ParserContext::parseFile(const std::string& filename, ParserType parser_type) {
    FILE* f = fopen(filename.c_str(), "r");
    if (!f) {
        isc_throw(ParseError, "Unable to open file " << filename);
    }
    scanFileBegin(f, filename, parser_type);
    return (parseCommon());
}

isc::data::ElementPtr
ParserContext::parseCommon() {
    isc::netconf::NetconfParser parser(*this);
    // Uncomment this to get detailed parser logs.
    // trace_parsing_ = true;
    parser.set_debug_level(trace_parsing_);
    try {
        int res = parser.parse();
        if (res != 0) {
            isc_throw(ParseError, "Parser abort");
        }
        scanEnd();
    }
    catch (...) {
        scanEnd();
        throw;
    }
    if (stack_.size() == 1) {
        return (stack_[0]);
    } else {
        isc_throw(ParseError, "Expected exactly one terminal Element expected, found "
                  << stack_.size());
    }
}


void
ParserContext::error(const isc::netconf::location& loc, const std::string& what)
{
    isc_throw(ParseError, loc << ": " << what);
}

void
ParserContext::error(const std::string& what)
{
    isc_throw(ParseError, what);
}

void
ParserContext::fatal(const std::string& what)
{
    isc_throw(ParseError, what);
}

isc::data::Element::Position
ParserContext::loc2pos(isc::netconf::location& loc)
{
    const std::string& file = *loc.begin.filename;
    const uint32_t line = loc.begin.line;
    const uint32_t pos = loc.begin.column;
    return (isc::data::Element::Position(file, line, pos));
}

void
ParserContext::require(const std::string& name,
                       isc::data::Element::Position open_loc,
                       isc::data::Element::Position close_loc)
{
    ConstElementPtr value = stack_.back()->get(name);
    if (!value) {
        isc_throw(ParseError,
                  "missing parameter '" << name << "' ("
                  << stack_.back()->getPosition() << ") ["
                  << contextName() << " map between "
                  << open_loc << " and " << close_loc << "]");
    }
}

void
ParserContext::enter(const LexerContext& ctx)
{
    cstack_.push_back(ctx_);
    ctx_ = ctx;
}

void
ParserContext::leave()
{
    if (cstack_.empty()) {
        fatal("unbalanced syntactic context");
    }
    ctx_ = cstack_.back();
    cstack_.pop_back();
}

const std::string
ParserContext::contextName()
{
    switch (ctx_) {
    case NO_KEYWORDS:
        return ("__no keywords__");
    case CONFIG:
        return ("toplevel");
    case NETCONF:
        return ("Netconf");
    case LOGGING:
        return ("Logging");
    case MANAGED_SERVERS:
        return ("managed-servers");
    case SERVER:
146
        return ("managed-servers/*");
147 148 149
    case CONTROL_SOCKET:
        return ("control-socket");
    case SOCKET_TYPE:
150
        return ("socket-type");
151 152 153 154 155 156 157 158 159 160 161 162 163
    case HOOKS_LIBRARIES:
        return ("hooks-libraries");
    case LOGGERS:
        return ("loggers");
    case OUTPUT_OPTIONS:
        return ("output-options");
    default:
        return ("__unknown__");
    }
}

};
};