text.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
#include "crucible/parsing/text.hpp" #include <sstream> namespace crucible::parsing::text { TextState::TextState(std::string_view const &input) : my_input { input } { } TextState::TextState(std::string_view const &input, std::size_t const code_unit_offset) : my_input { input }, my_code_unit_offset { code_unit_offset } { } auto TextState::is_finished() const -> bool { return my_code_unit_offset >= my_input.size(); } auto TextState::get_remaining_code_units_in_input() const -> std::string_view { return my_input.substr(my_code_unit_offset); } auto TextState::advance_by_code_units(std::size_t const code_unit_count) const -> TextState { return TextState { my_input, my_code_unit_offset + code_unit_count }; } auto TextState::format_location() const -> std::string { std::ostringstream buffer {}; buffer << "{ \"source_type\" : \"text\", \"code_unit\" : " << my_code_unit_offset << " }"; return buffer.str(); } CharacterSequence::CharacterSequence(std::string_view character_sequence) : my_character_sequence { character_sequence } { } auto CharacterSequence::operator()(StateType const &state) const -> ResultType { auto const &remaining_code_units { state.get_remaining_code_units_in_input() }; if (remaining_code_units.size() < my_character_sequence.size()) { return errors::make_reject(state, errors::UnexpectedEndOfInput {}); } auto const sequence_begin { my_character_sequence.begin() }; auto const sequence_end { my_character_sequence.end() }; auto const input_begin { remaining_code_units.begin() }; bool const is_equal { std::equal(sequence_begin, sequence_end, input_begin) }; if (is_equal) { auto const next_state { state.advance_by_code_units(my_character_sequence.size()) }; return errors::make_accept(next_state, core::none::None {}); } else { return errors::make_reject(state, errors::UnexpectedInput {}); } } }