From e6414e113db8cddc731e90d33a4ed3f1b4240087 Mon Sep 17 00:00:00 2001 From: jyelon Date: Fri, 22 Jul 2022 16:04:14 -0400 Subject: [PATCH] No, really, this is the code for the new keyword parsing. --- luprex/core/cpp/luastack.hpp | 58 +++++++++++++++++++++++++++++------- luprex/core/cpp/planemap.hpp | 6 ++-- 2 files changed, 51 insertions(+), 13 deletions(-) diff --git a/luprex/core/cpp/luastack.hpp b/luprex/core/cpp/luastack.hpp index 4c5d852c..09523431 100644 --- a/luprex/core/cpp/luastack.hpp +++ b/luprex/core/cpp/luastack.hpp @@ -155,6 +155,8 @@ #define LUASTACK_HPP #include "wrap-string.hpp" +#include "wrap-set.hpp" +#include extern "C" { #include "lua.h" @@ -351,6 +353,8 @@ private: static void delete_pointer(void *p) { delete (T*)p; } static void do_not_delete(void *p) { } + void argerr(const char *arg, const char *tp) const; + public: template LuaStack(lua_State *L, SS & ... stackslots) { @@ -386,20 +390,23 @@ public: bool isint(LuaSlot s) const; bool isthread(LuaSlot s) const { return lua_type(L_, s) == LUA_TTHREAD; } bool isfunction(LuaSlot s) const { return lua_type(L_, s) == LUA_TFUNCTION; } + bool iscfunction(LuaSlot s) const { return lua_iscfunction(L_, s) != 0; } bool isboolean(LuaSlot s) const { return lua_type(L_, s) == LUA_TBOOLEAN; } bool isnil(LuaSlot s) const { return lua_type(L_, s) == LUA_TNIL; } - bool iscfunction(LuaSlot s) const { return lua_iscfunction(L_, s) != 0; } bool istoken(LuaSlot s) const { return lua_islightuserdata(L_, s) != 0; } - void checktable(LuaSlot index) const { checktype(index, LUA_TTABLE); } - void checkstring(LuaSlot index) const { checktype(index, LUA_TSTRING); } - void checknumber(LuaSlot index) const { checktype(index, LUA_TNUMBER); } - void checkthread(LuaSlot index) const { checktype(index, LUA_TTHREAD); } - void checkfunction(LuaSlot index) const { checktype(index, LUA_TFUNCTION); } - void checkboolean(LuaSlot index) const { checktype(index, LUA_TBOOLEAN); } - void checknil(LuaSlot index) const { checktype(index, LUA_TNIL); } - void checktoken(LuaSlot index) const { checktype(index, LUA_TLIGHTUSERDATA); } - + void checktable(LuaSlot s, const char *n) const { if (!istable(s)) argerr(n, "table"); } + void checkstring(LuaSlot s, const char *n) const { if (!isstring(s)) argerr(n, "string"); } + void checknumber(LuaSlot s, const char *n) const { if (!isnumber(s)) argerr(n, "number"); } + void checkinteger(LuaSlot s, const char *n) const { if (!isinteger(s)) argerr(n, "integer"); } + void checkint(LuaSlot s, const char *n) const { if (!isint(s)) argerr(n, "int"); } + void checkthread(LuaSlot s, const char *n) const { if (!isthread(s)) argerr(n, "thread"); } + void checkfunction(LuaSlot s, const char *n) const { if (!isfunction(s)) argerr(n, "function"); } + void checkcfunction(LuaSlot s, const char *n) const { if (!iscfunction(s)) argerr(n, "cfunction"); } + void checkboolean(LuaSlot s, const char *n) const { if (!isboolean(s)) argerr(n, "boolean"); } + void checknil(LuaSlot s, const char *n) const { if (!isnil(s)) argerr(n, "nil"); } + void checktoken(LuaSlot s, const char *n) const { if (!istoken(s)) argerr(n, "token"); } + bool ckboolean(LuaSlot s) const; lua_Integer ckinteger(LuaSlot s) const; int ckint(LuaSlot s) const; @@ -516,6 +523,37 @@ public: static bool int64_storable(int64_t v) { return (v <= MAXINT) && (v >= -MAXINT); } }; +// This is a helper class to help parse tables full of keywords. +class LuaKeywordParser { + struct cmp_char { + bool operator () (const char *s1, const char *s2) const { + return strcmp(s1, s2) < 0; + }; + }; +private: + lua_State *L_; + int slot_; + eng::set parsed_; + + void init(const lua_State *L, int slot); +public: + // The constructor will throw a lua error if the + // slot is not a table. + LuaKeywordParser(lua_State *L, int slot); + LuaKeywordParser(const LuaStack &LS, LuaSlot slot) : LuaKeywordParser(LS.state(), slot.index()) {} + + // Fetch a value from the table. This never throws. + // Return true if the value is non-nil. + bool parse(LuaSlot slot, const char *kw); + + // Check if there are any keywords in the table that + // were never parsed. If so, throw an error. + void check_unparsed_keywords(); + + // Fetch the state pointer. + lua_State *state() const { return L_; } +}; + class LuaConstantReg : public eng::nevernew { private: const char *name_; diff --git a/luprex/core/cpp/planemap.hpp b/luprex/core/cpp/planemap.hpp index ffdbd741..1a8cac50 100644 --- a/luprex/core/cpp/planemap.hpp +++ b/luprex/core/cpp/planemap.hpp @@ -131,8 +131,8 @@ public: // Convert a lua table into a scan configuration. // - // If there is an error in the configuration, returns an - // error message, otherwise returns empty string. + // If there is an error in the configuration, + // throws a lua error message. // // Caution: if this detects the configuration flag 'near', // then it stores the near ID. However, it doesn't fetch @@ -141,7 +141,7 @@ public: // and plane. This is admittedly ugly, but it eliminates // a dependency on the world module. // - eng::string configure(const LuaStack &LS, LuaSlot slot); + void configure(LuaKeywordParser &kw); void set_bbox_given_center_radius(const util::XYZ ¢er, float r) { set_center(center);