24 using const_iterator =
typename std::string_view::const_iterator;
32 std::optional<const_iterator> text_segment_start;
46 inline skeleton_parse_context(std::filesystem::path
const& path, const_iterator first, const_iterator last) :
47 location(path.string()), index(first), last(last)
49 push<skeleton_top_node>(location);
52 [[nodiscard]]
constexpr char const& operator*() const noexcept
57 [[nodiscard]]
constexpr bool atEOF() const noexcept
62 constexpr skeleton_parse_context& operator++() noexcept
64 hi_assert(not atEOF());
70 constexpr skeleton_parse_context& operator+=(ssize_t x)
noexcept
72 for (ssize_t i = 0; i != x; ++i) {
78 constexpr bool starts_with(std::string_view text)
const noexcept
80 return std::string_view{index, last}.starts_with(text);
83 constexpr bool starts_with_and_advance_over(std::string_view text)
noexcept
85 if (starts_with(text)) {
93 constexpr bool advance_to(std::string_view text)
noexcept
96 if (starts_with(text)) {
104 constexpr bool advance_over(std::string_view text)
noexcept
106 if (advance_to(text)) {
107 *
this += ssize(text);
124 throw parse_error(std::format(
"{}: Could not parse expression.\n{}", location, e.
what()));
133 auto expression = parse_expression(end_text);
135 if (!starts_with_and_advance_over(end_text)) {
136 throw parse_error(std::format(
"{}: Could not find '{}' after expression", location, end_text));
142 template<
typename T,
typename... Args>
143 constexpr void push(Args&&...args)
145 statement_stack.
push_back(std::make_unique<T>(std::forward<Args>(args)...));
153 template<
typename T,
typename... Args>
154 [[nodiscard]]
constexpr bool append(Args&&...args)
noexcept
156 if (statement_stack.
size() > 0) {
157 return append(std::make_unique<T>(std::forward<Args>(args)...));
167 [[nodiscard]]
constexpr bool pop() noexcept
169 if (statement_stack.
size() > 0) {
178 constexpr void start_of_text_segment(
int back_track = 0) noexcept
180 text_segment_start = index - back_track;
183 constexpr void end_of_text_segment()
185 if (text_segment_start) {
186 if (index > *text_segment_start) {
187 if (!append<skeleton_string_node>(location,
std::string(*text_segment_start, index))) {
188 throw parse_error(std::format(
"{}: Unexpected text segment.", location));
192 text_segment_start = {};
196 [[nodiscard]]
constexpr bool top_statement_is_do() const noexcept
198 if (statement_stack.
size() < 1) {
202 auto const *
const ptr =
dynamic_cast<skeleton_do_node
const *
>(statement_stack.
back().
get());
203 return ptr !=
nullptr;
208 if (statement_stack.
size() > 0) {
215 [[nodiscard]]
constexpr bool found_else(parse_location statement_location)
noexcept
217 if (statement_stack.
size() > 0) {
218 return statement_stack.
back()->found_else(
std::move(statement_location));
226 if (statement_stack.
size() > 0) {
233 inline void include(parse_location statement_location, formula_node& expression)
235 auto tmp_post_process_context = formula_post_process_context();
236 expression.post_process(tmp_post_process_context);
238 auto evaluation_context = formula_evaluation_context();
239 hilet argument = expression.evaluate(evaluation_context);
241 auto new_skeleton_path = std::filesystem::current_path();
242 if (statement_location.has_file()) {
244 new_skeleton_path = statement_location.file();
245 new_skeleton_path.remove_filename();
247 new_skeleton_path /=
static_cast<std::string>(argument);
249 if (ssize(statement_stack) > 0) {
250 if (!statement_stack.
back()->append(parse_skeleton(new_skeleton_path))) {
251 throw parse_error(std::format(
"{}: Unexpected #include statement.", statement_location));
254 throw parse_error(std::format(
"{}: Unexpected #include statement, missing top-level", statement_location));
constexpr std::string_view::const_iterator find_end_of_formula(std::string_view::const_iterator first, std::string_view::const_iterator last, std::string_view terminating_string) noexcept
Find the end of an formula.
Definition formula_parser.hpp:476