Можно ли получить все ошибки в стеке lua из C / C ++? вот что я пробовал
C ++
int main()
{
lua_State* L = luaL_newstate();
luaL_openlibs(L);
if (luaL_loadfile(L, "LuaBridgeScript.lua"))
{
throw std::runtime_error("Unable to find lua file");
}
int error = lua_pcall(L, 0, 0, 0);
while (error && lua_gettop(L))
{
std::cout << "stack = " << lua_gettop(L) << "\n";
std::cout << "error = " << error << "\n";
std::cout << "message = " << lua_tostring(L, -1) << "\n";
lua_pop(L, 1);
error = lua_pcall(L, 0, 0, 0);
}
}
Lua:
printMessage("hi")
printMessage2("hi2")
выход:
stack = 1
error = 2
message = LuaBridgeScript.lua:1: attempt to call global 'printMessage' <a nil value>
Я также пытался зацикливаться, даже если размер стека равен 0 или отрицателен, но я не понимаю, как этот стек может быть отрицательным, и после нескольких попыток программа падает.
Чтобы обернуть мои комментарии в ответ:
В соответствии с Lua Docs на lua_pcall
pcall возвращает либо успешное завершение (конец фрагмента), либо первую выданную ошибку. Так что в последнем случае это подтолкнет только один сообщение в стек. Он никогда не продолжит выполнение после первой ошибки.
То, что вы пытаетесь достичь, это проверка возможных ошибок в файле. В статически типизированных языках, таких как C, каждая переменная должна быть определена во время компиляции, чтобы компилятор мог обнаружить случаи вызова несуществующей функции.
Lua, однако, является языком с динамической типизацией, в котором переменные не имеют типов, а являются заполнителями для значений (которые имеют типы). Это означает, что Луа не может заранее сказать, printMessage
является функцией, строкой, значением или, если оно не существует (ноль). Lua проверяет ее тип только во время выполнения.
Поэтому невозможно достичь того, чего вы хотите таким образом. Запуск кода после первой необработанной ошибки также не имеет смысла, так как ошибка может сделать предположения в последующих фрагментах недействительными (например, о глобальных переменных, которые должна была установить несуществующая функция) — это будет беспорядок.
Что касается синтаксических ошибок, они обычно обнаруживаются при компиляции исходного файла, то есть во время загрузки. Однако анализатор Lua останавливается при первой синтаксической ошибке. Это связано с тем, что много раз синтаксические ошибки в одном месте делают недействительным все, что следует за ним. Как отметил Этан в своем комментарии, многие парсеры сообщают о последующих ошибках, которые исчезают или изменяются после того, как вы исправили предшествующие им ошибки. Это также справедливо для парсеров с большим весом, таких как MSVS.
(исходя из вопроса, который вы пояснили в комментариях) Невозможно сообщить о множественных синтаксических ошибках (сообщается только о первой); поэтому в следующем фрагменте сообщается только о первой ошибке в строке 1:
if true the --<-- first syntax error
end
if false the --<-- second syntax error
end
Однако вы можете написать свой собственный анализатор (или изменить один из существующих анализаторов Lua), который продолжит обработку даже после обнаружения ошибки. Например, вы можете посмотреть, как Дэвид Манура свободный парсер работает.
Невозможно сообщить о множественных ошибках во время выполнения (сообщается только о первой); поэтому в следующем фрагменте pcall сообщит только о первой ошибке:
pcall(function()
nonExistingFunction1() --<-- only this error will be reported
nonExistingFunction2()
end)