Header lexy/input_location.hpp
Converts a position (iterator) into a human readable location (line/column number).
Class lexy::input_location
lexy/input_location.hppnamespace lexy
{
template <input Input, typename Counting = see-below>
class input_location
{
public:
// Location of the beginning.
constexpr explicit input_location(const Input& input);
constexpr input_location_anchor<Input> anchor() const;
constexpr unsigned line_nr() const;
constexpr unsigned column_nr() const;
constexpr auto position() const
-> lexy::input_reader<Input>::iterator;
// operator==, operator!=, operator<, operator<=, operator>=, operator>
};
}A human readable location in the input.
It combines the iterator based position with line/column number, according to some Counting strategy.
The Counting strategy defaults to lexy::code_unit_location_counting for text and lexy::byte_location_counting for bytes.
The constructor constructs an input location for the beginning of the input.
anchor() returns the latest anchor before that location to start the search.
Note | Use lexy::get_input_location to create location objects. |
Function lexy::get_input_location
lexy/input_location.hppnamespace lexy
{
template <input Input>
class input_location_anchor
{
public:
// Anchor to the beginning.
constexpr explicit input_location_anchor(const Input& input);
};
template <typename Counting = see-below>
constexpr auto get_input_location(const input auto& input,
lexy::input_reader<input>::iterator position,
input_location_anchor<input> anchor = see-below)
-> input_location<Input, Counting>;
}Gets the lexy::input_location for a position.
This is a linear search over the input that starts at the anchor.
If none is provided, it starts at the beginning.
As an optimization, pass an anchor of an existing location that is before position.
The result will be the location for the position as determined by the Counting strategy.
The Counting strategy defaults to lexy::code_unit_location_counting for text and lexy::byte_location_counting for bytes.
Calling position() on the resulting location will be the beginning of the last column before position.
Note | If position points inside a \r\n sequence, for example, the resulting position() will point to the initial \r. |
Counting strategies lexy::code_unit_location_counting, lexy::code_point_location_counting, lexy::byte_location_counting
lexy/input_location.hppnamespace lexy
{
struct code_unit_location_counting {};
struct code_point_location_counting {};
template <std::size_t LineWidth = 16>
struct byte_location_counting {};
}Strategies for counting column and line numbers.
code_unit_location_countingIncrements the column for every code unit; increments the line for every
lexy::dsl::newline. For example, UTF-8 encoded"abä"is a single line with four columns (two for each code unit ofä). This is the default for text.code_point_location_countingIncrements the column for every
lexy::dsl::code_point; increments the line for everylexy::dsl::newline. For example, UTF-8 encoded"abä"is a single line with three columns.byte_location_countingIncrements the column for every byte (requires
lexy::byte_encoding); increments the line for everyLineWidthbytes. This is the default for byte input.
See my blog post for an in-depth discussion about the choice of column units.
Function lexy::get_input_line_annotation
lexy/input_location.hppnamespace lexy
{
template <input Input>
struct input_line_annotation
{
lexy::lexeme_for<Input> before;
lexy::lexeme_for<Input> annotated;
lexy::lexeme_for<Input> after;
bool truncated_multiline;
bool rounded_end;
};
template <input Input, typename Counting>
constexpr auto get_input_line_annotation(const Input& input,
const input_location<Input, Counting>& begin_location,
lexy::input_reader<Input>::iterator end)
-> input_line_annotation<Input>;
template <typename Input, typename Counting>
constexpr auto get_input_line_annotation(const Input& input,
const input_location<Input, Counting>& location,
std::size_t size)
-> input_line_annotation<Input>;
{
auto end = std::next(location.position(), size);
return get_input_line_annotation(input, location, end);
}
}Computes the part of the input referenced by a [begin_location.position(), end) with surrounding input.
The result is an object of type input_line_annotation with the following values:
beforeA
lexy::lexemefor the range[line_begin, begin_location.position()), whereline_beginis the beginning of the line ofbegin_location, as determined byCounting.annotatedA
lexy::lexemefor the range[begin_location.position(), modified_end). Ifbegin_location.position() == end,modified_endis an incrementedend:If
endpoints to the beginning or inside of the newline, as determined byCounting, it is set to the end of the newline.Otherwise, it is set to the end of the current code point.
If
endis on a different line thenbegin_location,modified_endis the end of the newline, as determined byCounting. Otherwise,modified_endis the end of the code pointendpoints or multi character newline.afterA
lexy::lexemefor the range[modified_end, line_end), whereline_endis either the position of the newline or the end of the newline to ensuremodified_end ⇐ line_end, as determined byCounting.truncated_multilinetrueifendwas on a different line thanbegin_location,falseotherwise.rounded_endtrueifendpoints inside a code point and needed to be adjusted.
Tip | Use this function for error message generation.
Use lexy::visualize to print before, annotated, after;
and lexy::visualization_display_width to compute the indent below before and the number of underline characters for annotated. |