driver.locs_.pop_back();
driver.file_ = driver.files_.back();
driver.files_.pop_back();
+ if (driver.sfile_) {
+ fclose(driver.sfile_);
+ driver.sfile_ = 0;
+ }
+ if (!driver.sfiles_.empty()) {
+ driver.sfile_ = driver.sfiles_.back();
+ driver.sfiles_.pop_back();
+ }
parser6__delete_buffer(YY_CURRENT_BUFFER);
parser6__switch_to_buffer(driver.states_.back());
driver.states_.pop_back();
void
Parser6Context::scanStringBegin(const std::string& str, ParserType parser_type)
{
- static_cast<void>(parser6_lex_destroy());
start_token_flag = true;
start_token_value = parser_type;
file_ = "<string>";
+ sfile_ = 0;
loc_.initialize(&file_);
yy_flex_debug = trace_scanning_;
YY_BUFFER_STATE buffer;
}
}
-void
-Parser6Context::scanStringEnd()
-{
- yy_delete_buffer(YY_CURRENT_BUFFER);
-}
-
void
Parser6Context::scanFileBegin(FILE * f,
const std::string& filename,
ParserType parser_type)
{
- static_cast<void>(parser6_lex_destroy());
start_token_flag = true;
start_token_value = parser_type;
file_ = filename;
+ sfile_ = f;
loc_.initialize(&file_);
yy_flex_debug = trace_scanning_;
YY_BUFFER_STATE buffer;
}
void
-Parser6Context::scanFileEnd(FILE * f) {
- fclose(f);
- yy_delete_buffer(YY_CURRENT_BUFFER);
+Parser6Context::scanEnd() {
+ if (sfile_)
+ fclose(sfile_);
+ sfile_ = 0;
+ static_cast<void>(parser6_lex_destroy());
+ // Close files
+ while (!sfiles_.empty()) {
+ FILE* f = sfiles_.back();
+ if (f) {
+ fclose(f);
+ }
+ sfiles_.pop_back();
+ }
+ // Delete states
+ while (!states_.empty()) {
+ parser6__delete_buffer(states_.back());
+ states_.pop_back();
+ }
}
void
if (!f) {
fatal("Can't open include file " + filename);
}
+ if (sfile_) {
+ sfiles_.push_back(sfile_);
+ }
+ sfile_ = f;
states_.push_back(YY_CURRENT_BUFFER);
YY_BUFFER_STATE buffer;
buffer = parser6__create_buffer(f, 65536 /*buffer size*/);
// This represents a single top level entry, e.g. Dhcp6 or DhcpDdns.
global_object: dhcp6_object
| logging_object
- | dhcp4_json_object
- | dhcpddns_json_object
- | unknown_map_entry
+ | dhcp4_json_object
+ | dhcpddns_json_object
+ | unknown_map_entry
;
dhcp6_object: DHCP6 {
Parser6Context::parseString(const std::string& str, ParserType parser_type)
{
scanStringBegin(str, parser_type);
- isc::dhcp::Dhcp6Parser parser(*this);
- // Uncomment this to get detailed parser logs.
- // trace_parsing_ = true;
- parser.set_debug_level(trace_parsing_);
- int res = parser.parse();
- if (res != 0) {
- // @todo: handle exception here
- }
- scanStringEnd();
- if (stack_.size() == 1) {
- return (stack_[0]);
- } else {
- isc_throw(Dhcp6ParseError, "Expected exactly one terminal Element expected, found "
- << stack_.size());
- }
+ return (parseCommon());
}
isc::data::ConstElementPtr
isc_throw(Dhcp6ParseError, "Unable to open file " << filename);
}
scanFileBegin(f, filename, parser_type);
+ return (parseCommon());
+}
+isc::data::ConstElementPtr
+Parser6Context::parseCommon() {
isc::dhcp::Dhcp6Parser parser(*this);
// Uncomment this to get detailed parser logs.
// trace_parsing_ = true;
parser.set_debug_level(trace_parsing_);
- int res = parser.parse();
- if (res != 0) {
- // @todo: handle exception here
+ try {
+ int res = parser.parse();
+ if (res != 0) {
+ isc_throw(Dhcp6ParseError, "Parser abort");
+ }
+ scanEnd();
+ }
+ catch (...) {
+ scanEnd();
+ throw;
}
- scanFileEnd(f);
if (stack_.size() == 1) {
return (stack_[0]);
} else {
/// @brief Method called before scanning starts on a string.
void scanStringBegin(const std::string& str, ParserType type);
- /// @brief Method called after the last tokens are scanned from a string.
- void scanStringEnd();
-
/// @brief Method called before scanning starts on a file.
void scanFileBegin(FILE * f, const std::string& filename, ParserType type);
- /// @brief Method called after the last tokens are scanned from a file.
- void scanFileEnd(FILE * f);
+ /// @brief Method called after the last tokens are scanned.
+ void scanEnd();
/// @brief Divert input to an include file.
void includeFile(const std::string& filename);
/// @brief Location stack
std::vector<isc::dhcp::location> locs_;
- /// @brief State stack
+ /// @brief Lexer state stack
std::vector<struct yy_buffer_state*> states_;;
+ /// @brief sFile (aka FILE)
+ FILE* sfile_;
+
+ /// @brief sFile (aka FILE) stack
+ std::vector<FILE*> sfiles_;
+
/// @brief Current syntactic context
ParserContext ctx_;
/// @brief Syntactic context stack
std::vector<ParserContext> cstack_;
+
+ /// @brief Common part of parseXXX
+ isc::data::ConstElementPtr parseCommon();
};
}; // end of isc::eval namespace