7#include "skeleton_node.hpp"
8#include "skeleton_parse_context.hpp"
9#include "skeleton_node.hpp"
10#include "skeleton_block_node.hpp"
11#include "skeleton_break_node.hpp"
12#include "skeleton_continue_node.hpp"
13#include "skeleton_do_node.hpp"
14#include "skeleton_expression_node.hpp"
15#include "skeleton_for_node.hpp"
16#include "skeleton_function_node.hpp"
17#include "skeleton_if_node.hpp"
18#include "skeleton_placeholder_node.hpp"
19#include "skeleton_return_node.hpp"
20#include "skeleton_string_node.hpp"
21#include "skeleton_top_node.hpp"
22#include "skeleton_while_node.hpp"
23#include "../formula/formula.hpp"
24#include "../algorithm/module.hpp"
26#include "../macros.hpp"
30constexpr void parse_skeleton_hash(skeleton_parse_context &
context)
32 hilet &location =
context.location;
34 if (
context.starts_with(
"end")) {
38 throw parse_error(std::format(
"{}: Unexpected #end statement.", location));
41 context.start_of_text_segment();
43 }
else if (
context.starts_with_and_advance_over(
"if ")) {
44 context.push<skeleton_if_node>(location,
context.parse_expression_and_advance_over(
"\n"));
46 context.start_of_text_segment();
48 }
else if (
context.starts_with_and_advance_over(
"elif ")) {
49 if (!
context.found_elif(location,
context.parse_expression_and_advance_over(
"\n"))) {
50 throw parse_error(std::format(
"{}: Unexpected #elif statement.", location));
53 context.start_of_text_segment();
55 }
else if (
context.starts_with_and_advance_over(
"else")) {
58 if (!
context.found_else(location)) {
59 throw parse_error(std::format(
"{}: Unexpected #else statement.", location));
62 context.start_of_text_segment();
64 }
else if (
context.starts_with_and_advance_over(
"for ")) {
65 auto name_expression =
context.parse_expression_and_advance_over(
":");
66 auto list_expression =
context.parse_expression_and_advance_over(
"\n");
70 context.start_of_text_segment();
72 }
else if (
context.starts_with_and_advance_over(
"while ")) {
73 auto expression =
context.parse_expression_and_advance_over(
"\n");
75 if (
context.top_statement_is_do()) {
77 throw parse_error(std::format(
"{}: Unexpected #while statement; missing #do.", location));
85 context.start_of_text_segment();
87 }
else if (
context.starts_with_and_advance_over(
"do")) {
90 context.push<skeleton_do_node>(location);
92 context.start_of_text_segment();
94 }
else if (
context.starts_with_and_advance_over(
"function ")) {
95 context.push<skeleton_function_node>(
96 location,
context.post_process_context, *
context.parse_expression_and_advance_over(
"\n"));
98 context.start_of_text_segment();
100 }
else if (
context.starts_with_and_advance_over(
"block ")) {
101 context.push<skeleton_block_node>(
102 location,
context.post_process_context, *
context.parse_expression_and_advance_over(
"\n"));
104 context.start_of_text_segment();
106 }
else if (
context.starts_with_and_advance_over(
"break")) {
109 if (!
context.append<skeleton_break_node>(location)) {
110 throw parse_error(std::format(
"{}: Unexpected #break statement", location));
113 context.start_of_text_segment();
115 }
else if (
context.starts_with_and_advance_over(
"continue")) {
118 if (!
context.append<skeleton_continue_node>(location)) {
119 throw parse_error(std::format(
"{}: Unexpected #continue statement", location));
122 context.start_of_text_segment();
124 }
else if (
context.starts_with_and_advance_over(
"return ")) {
125 if (!
context.append<skeleton_return_node>(location,
context.parse_expression_and_advance_over(
"\n"))) {
126 throw parse_error(std::format(
"{}: Unexpected #return statement", location));
129 context.start_of_text_segment();
131 }
else if (
context.starts_with_and_advance_over(
"include ")) {
132 context.include(location, *
context.parse_expression_and_advance_over(
"\n"));
133 context.start_of_text_segment();
136 if (!
context.append<skeleton_expression_node>(location,
context.parse_expression_and_advance_over(
"\n"))) {
137 throw parse_error(std::format(
"{}: Unexpected # (expression) statement.", location));
140 context.start_of_text_segment();
144constexpr void parse_skeleton_dollar(skeleton_parse_context &
context)
146 hilet &location =
context.location;
150 if (!
context.append<skeleton_placeholder_node>(location,
context.parse_expression_and_advance_over(
"}"))) {
151 throw parse_error(
"Unexpected placeholder.");
154 context.start_of_text_segment();
158 context.start_of_text_segment(-2);
162constexpr void parse_skeleton_escape(skeleton_parse_context &
context)
170 context.start_of_text_segment();
179 context.start_of_text_segment(-2);
183 throw parse_error(std::format(
"{}: Unexpected end-of-file after escape '\' character.",
context.location));
188 context.start_of_text_segment();
201 parse_skeleton_dollar(
context);
207 parse_skeleton_escape(
context);
215 if (
context.statement_stack.size() < 1) {
216 throw parse_error(std::format(
"{}: Found to many #end statements.",
context.location));
217 }
else if (
context.statement_stack.size() > 1) {
218 throw parse_error(std::format(
"{}: Missing #end statement.",
context.location));
222 context.statement_stack.pop_back();
224 top->post_process(
context.post_process_context);
229parse_skeleton(std::filesystem::path path, std::string_view::const_iterator first, std::string_view::const_iterator last)
232 auto e = parse_skeleton(
context);
238 return parse_skeleton(
std::move(path), text.cbegin(), text.cend());
243 hilet
fv = file_view(path);
244 hilet
sv = as_string_view(
fv);
246 return parse_skeleton(
std::move(path),
sv.cbegin(),
sv.cend());
DOXYGEN BUG.
Definition algorithm.hpp:16
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377