2
0
mirror of https://github.com/boostorg/parser.git synced 2026-01-19 04:22:13 +00:00
Files
parser/example/user_error_handler.cpp
Zach Laine d59e0528b2 Consolidate documentation on eror handlers into the Error Handling and
Debugging section, and add an example of how to write your own error handler.

Fixes #43.
2024-01-15 02:28:50 -06:00

97 lines
2.9 KiB
C++

// Copyright (C) 2020 T. Zachary Laine
//
// Distributed under the Boost Software License, Version 1.0. (See
// accompanying file LICENSE_1_0.txt or copy at
// http://www.boost.org/LICENSE_1_0.txt)
#include <boost/parser/parser.hpp>
#include <iostream>
#include <fstream>
#include <string>
namespace bp = boost::parser;
//[ logging_error_handler
struct logging_error_handler
{
logging_error_handler() {}
logging_error_handler(std::string_view filename) :
filename_(filename), ofs_(filename_)
{
if (!ofs_)
throw std::runtime_error("Could not open file.");
}
// This is the function called by Boost.Parser after a parser fails the
// parse at an expectation point and throws a parse_error. It is expected
// to create a diagnostic message, and put it where it needs to go. In
// this case, we're writing it to a log file. This function returns a
// bp::error_handler_result, which is an enum with two enumerators -- fail
// and rethrow. Returning fail fails the top-level parse; returning
// rethrow just re-throws the parse_error exception that got us here in
// the first place.
template<typename Iter, typename Sentinel>
bp::error_handler_result
operator()(Iter first, Sentinel last, bp::parse_error<Iter> const & e) const
{
bp::write_formatted_expectation_failure_error_message(
ofs_, filename_, first, last, e);
return bp::error_handler_result::fail;
}
// This function is for users to call within a semantic action to produce
// a diagnostic.
template<typename Context, typename Iter>
void diagnose(
bp::diagnostic_kind kind,
std::string_view message,
Context const & context,
Iter it) const
{
bp::write_formatted_message(
ofs_,
filename_,
bp::_begin(context),
it,
bp::_end(context),
message);
}
// This is just like the other overload of diagnose(), except that it
// determines the Iter parameter for the other overload by calling
// _where(ctx).
template<typename Context>
void diagnose(
bp::diagnostic_kind kind,
std::string_view message,
Context const & context) const
{
diagnose(kind, message, context, bp::_where(context).begin());
}
std::string filename_;
mutable std::ofstream ofs_;
};
//]
//[ using_logging_error_handler
int main()
{
std::cout << "Enter a list of integers, separated by commas. ";
std::string input;
std::getline(std::cin, input);
constexpr auto parser = bp::int_ >> *(',' > bp::int_);
logging_error_handler error_handler("parse.log");
auto const result = bp::parse(input, bp::with_error_handler(parser, error_handler));
if (result) {
std::cout << "It looks like you entered:\n";
for (int x : *result) {
std::cout << x << "\n";
}
}
}
//]