#pragma once
#include <string>
#include <utility>
#include <vector>
#include "llex.h"
#ifdef PLUTO_PARSER_SUGGESTIONS
struct SuggestionsState {
struct Suggestion {
const char* type;
const char* name;
std::string extra;
};
LexState* const ls;
const char* str = "";
size_t len = 0;
std::vector<Suggestion> suggestions;
SuggestionsState(LexState* ls)
: ls(ls) {
if (ls->t.token != TK_SUGGEST_0) {
luaX_next(ls);
str = luaX_token2str_noq(ls, ls->t.token);
len = strlen(str);
}
luaX_next(ls);
}
void push(const char* type, const char* name, std::string extra = {}) {
suggestions.emplace_back(Suggestion{ type, name, std::move(extra) });
}
void pushLocals() {
for (int i = ls->fs->nactvar - 1; i >= 0; i--) {
Vardesc *vd = getlocalvardesc(ls->fs, i);
if (strcmp(getstr(vd->vd.name), "Pluto_operator_new") != 0
&& strcmp(getstr(vd->vd.name), "Pluto_operator_extends") != 0
&& strcmp(getstr(vd->vd.name), "Pluto_operator_instanceof") != 0
&& strcmp(getstr(vd->vd.name), "(for state)") != 0
&& strcmp(getstr(vd->vd.name), "(switch control value)") != 0
&& strcmp(getstr(vd->vd.name), "(try results)") != 0
) {
push("local", getstr(vd->vd.name));
}
}
}
~SuggestionsState() {
for (auto i = suggestions.begin(); i != suggestions.end(); ) {
if (strncmp(i->name, str, len) == 0)
++i;
else
i = suggestions.erase(i);
}
if (!suggestions.empty()) {
std::string msg = "suggest: ";
for (const auto& suggestion : suggestions) {
msg.append(suggestion.type);
msg.push_back(',');
msg.append(suggestion.name);
if (!suggestion.extra.empty()) {
msg.push_back(',');
msg.append(suggestion.extra);
}
msg.push_back(';');
}
msg.pop_back();
lua_warning(ls->L, msg.c_str(), 0);
}
}
};
#endif