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::u8string_view const &input) : my_input(input) { } TextState::TextState(std::u8string_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::u8string_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::u8string_view const &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 result::reject(state, TextError { CharacterSequenceMismatch {} }); } 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 result::accept(next_state, core::none::None {}); } else { return result::reject(state, TextError { CharacterSequenceMismatch {} }); } } }