mirror of
https://github.com/boostorg/parser.git
synced 2026-01-22 05:22:32 +00:00
in *parse_impl(); add support to the error handlers and their support functions directly instead. There are simply too many APIs there that need the translation to leave it to other code. Add lex_error exception type, and add support for all the APIs that used to take a parse_error param to now take either a parse_error or a lex_error. Throw lex_error from failed parsing of lexed tokens in detail::make_token(). See #202.
97 lines
2.9 KiB
C++
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, template<class> class Exception>
|
|
bp::error_handler_result
|
|
operator()(Iter first, Sentinel last, Exception<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";
|
|
}
|
|
}
|
|
}
|
|
//]
|