You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

94 lines
2.1 KiB
C++

#include <cctype>
#include <sstream>
#include <cassert>
#include <exception>
#include "driver.hh"
sexp::driver::~driver()
{
delete(scanner);
scanner = nullptr;
delete(parser);
parser = nullptr;
}
bool sexp::driver::parse(const char *text, std::ostream *debug = nullptr)
{
assert(text != nullptr);
std::istringstream stream{std::string(text)};
return parse(stream, debug);
}
bool sexp::driver::parse(std::istream &stream, std::ostream *debug = nullptr)
{
if(!stream.good() && stream.eof())
{
return false;
}
return parse_helper(stream, debug);
}
bool sexp::driver::parse_helper(std::istream &stream, std::ostream *debug)
{
delete(scanner);
try
{
scanner = new sexp::scanner(&stream);
}
catch(std::bad_alloc &ba)
{
throw std::runtime_error("Failed to allocate scanner");
}
delete(parser);
try
{
parser = new sexp::parser((*scanner) /* scanner */,
(*this) /* driver */);
}
catch(std::bad_alloc &ba)
{
throw std::runtime_error("Failed to allocate parser");
}
const int accept = 0;
if (debug)
{
parser->set_debug_level(1);
parser->set_debug_stream(*debug);
}
return parser->parse() == accept;
}
void sexp::driver::start_tag(const std::string &name)
{
auto *stanza = xmpp_stanza_new(context);
xmpp_stanza_set_name(stanza, name.data());
stack.push_back(stanza);
}
void sexp::driver::end_tag()
{
auto *stanza = stack.back();
stack.pop_back();
if (stack.empty())
elements.push_back(stanza);
else
xmpp_stanza_add_child_ex(stack.back(), stanza, false);
}
void sexp::driver::add_text(const std::string &text)
{
auto *stanza = xmpp_stanza_new(context);
xmpp_stanza_set_text(stanza, text.substr(1,text.length()-2).data());
xmpp_stanza_add_child_ex(stack.back(), stanza, false);
}
void sexp::driver::add_attr(const std::string &name, const std::string &value)
{
xmpp_stanza_set_attribute(stack.back(), name.data(),
value.substr(1,value.length()-2).data());
}