My Project
error.h
1 #ifndef ERROR_H_INCLUDED_
2 #define ERROR_H_INCLUDED_
3 
4 #include <exception>
5 #include <iomanip>
6 #include <map>
7 #include <memory>
8 #include <sstream>
9 #include <string>
10 
11 #include "kblib/containers.h"
12 #include "kblib/convert.h"
13 #include "kblib/stringops.h"
14 
15 enum class ec : unsigned {
16  // section 0: placeholder errors
17  unknown = 0,
18  internal,
19  no_feature,
20 
21  // section 1: system errors
22 
23  // section 2: YAML Format errors (load time)
24  y_internal = 200,
25  too_many_tnode_args,
26  invalid_stage_type,
27  invalid_normalization_form,
28  bad_regex,
29 
30  // section 3: noderef syntax errors (expansion time)
31  n_internal = 300,
32  unterminated_noderef,
33  extra_rb,
34  lb_in_name,
35  illegal_escape,
36 
37  // section 4: template string errors (load time)
38  p_internal = 400,
39  bad_format,
40  blank_fname,
41  invalid_fname,
42  call_arg,
43  eos = 405,
44  extra_rp,
45  extra_lp,
46  extra_p,
47  extra_ab,
48  extra_h = 410,
49  extra_c,
50  early_close,
51  escape_nostr,
52  overmarked_arg,
53  invalid_raw = 415,
54  no_function,
55 
56  // section 5: template evaluation errors (expansion time)
57  e_internal = 500,
58  bad_arg_type,
59  bad_arg_rank,
60  bad_randspec,
61  invoke_null,
62  invoke_type = 505,
63  node_bad_cvt,
64  unpaired_args,
65  too_many_args,
66  not_enough_args,
67  e_nonode = 510,
68  range_error,
69  bad_math,
70  m_divzero,
71  null_var,
72 
73  // section 6: transformation evaluation errors (transform time)
74  t_internal = 600,
75 };
76 
77 const std::map<ec, std::string> err_strs{
78  // E0
79  {ec::unknown, "Unknown error."},
80  {ec::internal, "Internal error."},
81  {ec::no_feature, "Feature not implemented yet."},
82 
83  // E200
84  {ec::y_internal, "Unknown load-time error."},
85  {ec::too_many_tnode_args, "Too many arguments specified for a node."},
86  {ec::invalid_stage_type, "Invalid replace stage type."},
87  {ec::invalid_normalization_form, "Invalid normalization form."},
88  {ec::bad_regex, "Invalid regular expression"},
89  // E205
90 
91  // E300
92  {ec::n_internal, "Internal error in noderef parser."},
93  {ec::unterminated_noderef, "Unterminated reference."},
94  {ec::extra_rb, "Encountered '}' outside reference."},
95  {ec::lb_in_name, "Encountered '{' inside reference."},
96  {ec::illegal_escape, "Illegal escape sequence."},
97 
98  // E400
99  {ec::p_internal, "Internal error in template parser."},
100  {ec::bad_format, "Invalid argref."},
101  {ec::blank_fname, "Function names cannot be blank."},
102  {ec::invalid_fname, "Invalid character in function name."},
103  {ec::call_arg, "Arguments cannot be used as functions."},
104  // E405
105  {ec::eos, "Unexpected end-of-input"},
106  {ec::extra_rp, "Unmatched )."},
107  {ec::extra_lp, "Unmatched (; or unexpected >."},
108  {ec::extra_p, "Unexpected top-level |."},
109  {ec::extra_ab, "unescaped < in template context."},
110  // E410
111  {ec::extra_h, "encountered unexpected # in argument context."},
112  {ec::extra_c, "encountered unexpected characters after )."},
113  {ec::early_close, "blank argref is invalid."},
114  {ec::escape_nostr, "escape sequence outside of string context."},
115  {ec::overmarked_arg, "Argrefs at topmost level do not need #."},
116  // E415
117  {ec::invalid_raw, "Invalid raw string syntax."},
118  {ec::no_function, "No function by this name exists."},
119 
120  // E500
121  {ec::e_internal, "Internal error in template evaluator."},
122  {ec::bad_arg_type,
123  "Template function received argument of incorrect type."},
124  {ec::bad_arg_rank,
125  "Template function received a list when it expected a single element."},
126  {ec::bad_randspec, "Bad parameters for a random function."},
127  {ec::invoke_null, "Invoke requires arguments."},
128  // E505
129  {ec::invoke_type,
130  "The first argument to invoke must be a string, not a list."},
131  {ec::node_bad_cvt,
132  "A synthesized node cannot be converted to another type."},
133  {ec::unpaired_args, "Template function expected arguments in sets, but "
134  "could not complete a set."},
135  {ec::too_many_args,
136  "Template function received more arguments than it expected."},
137  {ec::not_enough_args,
138  "Template function did not receive all expected arguments."},
139  // E510
140  {ec::e_nonode, "'node' function's argument does not name a node"},
141  {ec::range_error, "? or [] index out of range."},
142  {ec::bad_math, "Invalid mathematical expression."},
143  {ec::m_divzero, "Division by zero occurred."},
144  {ec::null_var, "get() of nonexistent variable."},
145 
146  // E600
147  {ec::t_internal, "Internal error in transformation processor"},
148 };
149 
150 inline std::string format_err(ec err) {
151  std::ostringstream out;
152  out << 'E' << std::setw(3) << std::setfill('0') << static_cast<int>(err)
153  << ": " << kblib::get_or(err_strs, err, err_strs.at(ec::unknown))
154  << '\n';
155  return out.str();
156 }
157 
158 class wordgen_error final {
159  public:
160  wordgen_error(std::string desc, std::string context, std::string loc,
161  std::string info)
162  : l1(std::make_shared<std::string>(std::move(desc))),
163  l2(std::make_shared<std::string>(std::move(context))),
164  l3(std::make_shared<std::string>(std::move(loc))),
165  l4(std::make_shared<std::string>(std::move(info))), c(ec::unknown) {}
166  wordgen_error(ec err, std::string context, std::string loc, std::string info)
167  : l1(std::make_shared<std::string>(format_err(err))),
168  l2(std::make_shared<std::string>(std::move(context))),
169  l3(std::make_shared<std::string>(std::move(loc))),
170  l4(std::make_shared<std::string>(std::move(info))), c(err) {}
171  std::shared_ptr<std::string> l1, l2, l3, l4;
172  ec c;
173  ec code() const { return c; }
174  std::string what() const { return kblib::concat(*l1, *l2, *l3, *l4); }
175 };
176 
177 inline bool operator==(const wordgen_error& l, const wordgen_error& r) {
178  return l.what() == r.what();
179 }
180 
181 inline bool operator!=(const wordgen_error& l, const wordgen_error& r) {
182  return l.what() != r.what();
183 }
184 
185 [[noreturn]] inline void parse_error(ec err, std::string_view str,
186  const char* epos, std::string msg = "") {
187  auto printable = kblib::escapify(str);
188  auto index = kblib::calculate_translated_index(str, epos);
189  throw wordgen_error(err, kblib::concat("\"", printable, "\"\n"),
190  kblib::concat(" ", kblib::repeat(' ', index), "^\n"),
191  std::move(msg));
192 }
193 
194 [[noreturn]] inline void parse_error(ec err, std::string_view str,
195  long long epos, std::string msg = "") {
196  parse_error(err, str, str.data() + epos, std::move(msg));
197 }
198 
199 #endif // ERROR_H_INCLUDED_
Definition: error.h:158