13std::string
nearest(
const std::string& want,
const std::map<std::string, std::string>&
table) {
14 auto close = [&](
const std::string&
a,
const std::string&
b) {
15 const size_t la =
a.size(), lb =
b.size();
18 for (
size_t i = 0; i < la; i++)
19 if (
a[i] !=
b[i] && ++
diff > 1)
23 if (la + 1 != lb && lb + 1 != la)
25 const std::string& s = (la < lb) ?
a :
b;
26 const std::string& l = (la < lb) ?
b :
a;
29 while (i < s.size() && j < l.size()) {
33 }
else if (!skipped) {
42 for (
const auto& [slug, canonical] :
table)
43 if (close(want, slug))
48std::string
suffixFor(
const std::string& want,
const std::map<std::string, std::string>&
table) {
51 return " — did you mean " +
near +
"?";
55 std::string s =
" — known names include ";
57 for (
const auto& [slug, canonical] :
table) {
70 std::vector<Diagnostic> out;
79 const std::map<std::string, std::string>*
table =
nullptr;
96 out.push_back({code, ref.
line, ref.
col,
106 "this state is not allowed to transition to " + ref.
slug +
107 " — state_transitions.csv does not permit it"});
116 for (
const std::string& var : program.
variables) {
117 const std::string slug =
slugify(var);
118 const char* where =
nullptr;
119 if (
tables.actuators.count(slug))
120 where =
"an actuator";
121 else if (
tables.sensors.count(slug))
123 else if (
tables.states.count(slug))
125 if (where ==
nullptr)
128 uint32_t line = 0, col = 0;
138 "variable '" + var +
"' has the same name as " + where +
" (" + slug +
139 ") — rename the variable"});
143 if (a.line != b.line)
144 return a.line < b.line;
145 return a.col < b.col;
TOML_PURE_INLINE_GETTER bool empty() const noexcept
*brief create JSON pointer *sa reference_tokens const string_t const string_t & b
*brief create JSON pointer *sa reference_tokens const string_t & a
std::string suffixFor(const std::string &want, const std::map< std::string, std::string > &table)
std::string nearest(const std::string &want, const std::map< std::string, std::string > &table)
A short "did you mean" for a slug that did not resolve.
std::string slugify(const std::string &name)
Canonical name -> slug: trim, uppercase, collapse internal whitespace runs to a single '_'.
const char * ns_name(Ns ns)
std::vector< Diagnostic > validate(const ScriptProgram &program, const SlugTables &tables)
Config-dependent checks.
Motorized ball valve position: raw ADC counts -> % open.
*brief user defined string literal for JSON values *sa std::size_t n
A parsed script, as a flat arena.
std::vector< Stmt > stmts
std::vector< std::string > variables
std::vector< SlugRef > slugs
Every slug reference in SOURCE ORDER, with spans.
One slug reference, with its source span so a rename can rewrite exactly this token.
What a script's slugs are allowed to name, built from the loaded config.
int32_t var
Assign: index into ScriptProgram::variables.
static bool near(double a, double b, double tol)
static int32_t diff(uint32_t a, uint32_t b)
static SlugTables tables()
The tables every case validates against.