Функция без скобок lua ​​c++

Я создаю приложение, которое воспроизводит музыку на основе функций, вызываемых в скрипте Lua. Я называю это музыкой. Проблема в том, что мне нужна функция, которая не нуждается в скобках. Как это:

play note("A")

Это мой полный код:

#include <iostream>
#include <string>

extern "C"
{
#include "../lua/include/lua.h"
#include "../lua/include/lauxlib.h"
#include "../lua/include/lualib.h"
}
/*
Message codes

M8I5H: Information
MSKIE: Syntax error
M3UET: Unknown error

*/
enum class MUSICA_NOTE_ENUM
{
A,B,C,D,E,F,G,H,I,J,K,L,M,N,O,P,Q,R,S,T,U,V,W,X,Y,Z
};

int musica_play(lua_State *L)
{
// Not added yet
return 1;
}

int musica_note(lua_State *L)
{
  std::string note = lua_tostring(L, 1);

  lua_pushnumber(L, (lua_Number)((MUSICA_NOTE_ENUM)(note.at(0) & 31)));
  return 1;
}

int main(){
std::string music = R"(a = 75
play note("A")
play note("B")
play note("C")
-- play melody(melody_piono_tune)
)";
std::string m = "play note(\"A\")";

lua_State *L = luaL_newstate();

lua_register(L, "note", musica_note);
lua_register(L, "play", musica_play);

int r = luaL_dostring(L, m.c_str());


if(r == LUA_OK)
{

}else{
printf("[Line: %d, File: %s, MessageCode: MSKIE] MUSICA: There was a problem interperting the file:\n%s\n\n", __LINE__, __FILE__, lua_tostring(L, -1));
}

}

Как сделать функцию воспроизведения без скобок?

заранее спасибо


person Community    schedule 14.07.2020    source источник


Ответы (1)


Стандартный Lua поддерживает только вызов функций без круглых скобок, когда функция вызывается с конструктором таблицы или строковым литералом в качестве единственного аргумента. Поскольку вы хотите иметь возможность вызывать его с другими значениями, ваш единственный вариант заставить это работать — это исправить парсер Lua. Вот как это можно сделать, взломав исходный код Lua (этот патч был подготовлен для версии Lua 5.4.1):

diff --git a/src/lparser.c b/src/lparser.c
index bc7d9a4..d917687 100644
--- a/src/lparser.c
+++ b/src/lparser.c
@@ -1795,6 +1795,44 @@ static void localstat (LexState *ls) {
 }


+static void playstat (LexState *ls) {
+  FuncState *fs = ls->fs;
+  struct LHS_assign v;
+  expdesc *f = &v.v;
+  int line = ls->linenumber;
+  expdesc args;
+  int base, nparams;
+  Instruction *inst;
+
+  /* get the function ready to call like suffixedexp does */
+  singlevar(ls, f);
+  luaK_exp2nextreg(fs, f);
+
+  /* this section taken from the else inside case '(' in funcargs */
+  explist(ls, &args);
+  if (hasmultret(args.k))
+    luaK_setmultret(fs, &args);
+
+  /* this section taken from after the switch statement in funcargs */
+  lua_assert(f->k == VNONRELOC);
+  base = f->u.info;  /* base register for call */
+  if (hasmultret(args.k))
+    nparams = LUA_MULTRET;  /* open call */
+  else {
+    luaK_exp2nextreg(fs, &args);  /* close last argument */
+    nparams = fs->freereg - (base+1);
+  }
+  init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2));
+  luaK_fixline(fs, line);
+  fs->freereg = base+1;  /* call remove function and arguments and leaves
+                            (unless changed) one result */
+
+  /* this section taken from the else block in exprstat */
+  inst = &getinstruction(fs, &v.v);
+  SETARG_C(*inst, 1);  /* call statement uses no results */
+}
+
+
 static int funcname (LexState *ls, expdesc *v) {
   /* funcname -> NAME {fieldsel} [':' NAME] */
   int ismethod = 0;
@@ -1932,6 +1970,13 @@ static void statement (LexState *ls) {
       gotostat(ls);
       break;
     }
+    case TK_NAME: {
+      if (!strcmp(getstr(ls->t.seminfo.ts), "play")) {
+        playstat(ls);
+        break;
+      }
+    }
+    /* FALLTHROUGH */
     default: {  /* stat -> func | assignment */
       exprstat(ls);
       break;

Это заставляет play действовать как ключевое слово в начале оператора. Он фиксирует выражения после него аналогично тому, как это делает local foo, bar, baz =. Я должен подчеркнуть, что это действительно настоящий хак. Другой вариант — сделать то же самое с Metalua, но это ограничивает вас Lua 5.1, который был EOL в течение 8 лет и знал о проблемах с безопасностью.

person Joseph Sible-Reinstate Monica    schedule 13.11.2020