Modify lua's Code Resolution

Original Link: https://my.oschina.net/gal/blog/200205

Sometimes you want to add custom-style code to your lua, such as simplifying a commonly used function to a symbol. When you develop a GAL engine, you need a lot of commands that echo text, so you want to simplify the command to greatly improve the efficiency of scripting. For example:

//Existing script implementation
echo("It's a really bad thing","Person 1");
echo("It's a really bad thing","Person 2");
echo("It's a really bad thing","Person 3");
echo("It's a really bad thing","Person 4");
...

//Modified implementation
@Person 1:"That's a really good thing"
@Person 2:"That's a really good thing"
@Person 3:"That's a really good thing"
@Person 4:"That's a really good thing"
...

It looks like a good thing, ^^ Imagine a word game, basically commands that echo text. Simplified efficiency improves.

Of course, this is to take the source code of lua (following the GPL protocol). Lua's script parsing is mainly in the llex.c file. By analyzing each character, extract keywords, symbols, variables and so on, and pass them to lparser.c to check the syntax.

The main function in llex.c is static int llex (LexState *ls, SemInfo *seminfo), which is responsible for splitting and parsing each WORD and returning it to the grammar checker, where we need to manually parse the symbol @not defined in lua into echo commands and return two parameters.

//Translate and pass echo commands           
char *str_echo=0,*str_rolename=0;           
int len_echo=0,len_rolename=0;           
int trans_echo_command_step = -1;           
                        
static int llex (LexState *ls, SemInfo *seminfo) {           
  luaZ_resetbuffer(ls->buff);           
                        
  if(trans_echo_command_step!=-1)           
  {           
      switch(trans_echo_command_step)           
      {           
      case 1:   //Return left parenthesis           
          trans_echo_command_step++;           
          return 40;           
                        
      case 2:   //Return echo string           
          trans_echo_command_step++;           
          seminfo->ts = luaX_newstring(ls, str_echo, len_echo);           
          return TK_STRING;           
                        
      case 3:   //Return Comma           
          trans_echo_command_step++;           
          return 44;           
                        
      case 4:   //Returns the rolename string           
          trans_echo_command_step++;           
          seminfo->ts = luaX_newstring(ls, str_rolename, len_rolename);           
          return TK_STRING;           
                        
      case 5:   //Return right parenthesis           
          trans_echo_command_step=-1;           
          return 41;           
      }           
  }           
                        
                        
  for (;;) {           
    switch (ls->current) {           
      case '\n': case '\r': {  /* line breaks */
        inclinenumber(ls);           
        break;           
      }           
      case ' ': case '\f': case '\t': case '\v': {  /* spaces */
        next(ls);           
        break;           
      }           
                        
    /*!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!           
                         fscript_echo_process                           */
      case '@':           
          {           
                  TString *ts;           
                  str_echo=0,str_rolename=0;           
                  len_echo=0,len_rolename=0;           
                        
                  next(ls);           
                        
                  if(ls->current != 34)   // Read rolename if it is not           
                  {           
                      // Read Names           
                      do
                      {              
                          save_and_next(ls);           
                      }              
                      while (ls->current != ':');           
                        
                      // Copy Name           
                      str_rolename = luaZ_buffer(ls->buff);           
                      len_rolename = ls->buff->n;           
                        
                      next(ls); // Skip:           
                  }           
                        
                  fs_get_string(ls, ls->current);           
                  str_echo = luaZ_buffer(ls->buff) + len_rolename + 1;           
                  len_echo = ls->buff->n - len_rolename - 2;           
                        
                  //First step return command           
                  trans_echo_command_step = 1;           
                        
                  ts = luaX_newstring(ls, "doecho",6);             
                  seminfo->ts = ts;           
                  if (isreserved(ts))  /* reserved word? */ 
                      return ts->tsv.extra - 1 + FIRST_RESERVED;              
                  else
                      return TK_NAME;           
          }           
                        
      case '-': {  /* '-' or '--' (comment) */
        next(ls);           
        if (ls->current != '-') return '-';           
        /* else is a comment */
        next(ls);           
        if (ls->current == '[') {  /* long comment? */
          int sep = skip_sep(ls);           
          luaZ_resetbuffer(ls->buff);  /* `skip_sep' may dirty the buffer */
          if (sep >= 0) {           
            read_long_string(ls, NULL, sep);  /* skip long comment */
            luaZ_resetbuffer(ls->buff);  /* previous call may dirty the buff. */
            break;           
          }           
        }           
        /* else short comment */
        while (!currIsNewline(ls) && ls->current != EOZ)           
          next(ls);  /* skip until end of line (or end of file) */
        break;           
      }           
      case '[': {  /* long string or simply '[' */
        int sep = skip_sep(ls);           
        if (sep >= 0) {           
          read_long_string(ls, seminfo, sep);           
          return TK_STRING;           
        }           
        else if (sep == -1) return '[';           
        else lexerror(ls, "invalid long string delimiter", TK_STRING);           
      }           
      case '=': {           
        next(ls);           
        if (ls->current != '=') return '=';           
        else { next(ls); return TK_EQ; }           
      }           
      case '<': {           
        next(ls);           
        if (ls->current != '=') return '<';           
        else { next(ls); return TK_LE; }           
      }           
      case '>': {           
        next(ls);           
        if (ls->current != '=') return '>';           
        else { next(ls); return TK_GE; }           
      }           
      case '~': {           
        next(ls);           
        if (ls->current != '=') return '~';           
        else { next(ls); return TK_NE; }           
      }           
      case ':': {           
        next(ls);           
        if (ls->current != ':') return ':';           
        else { next(ls); return TK_DBCOLON; }           
      }           
      case '"': case '\'': {  /* short literal strings */
        read_string(ls, ls->current, seminfo);           
        return TK_STRING;           
      }           
      case '.': {  /* '.', '..', '...', or number */
        save_and_next(ls);           
        if (check_next(ls, ".")) {           
          if (check_next(ls, "."))           
            return TK_DOTS;   /* '...' */
          else return TK_CONCAT;   /* '..' */
        }           
        else if (!lisdigit(ls->current)) return '.';           
        /* else go through */
      }           
      case '0': case '1': case '2': case '3': case '4':           
      case '5': case '6': case '7': case '8': case '9': {           
        read_numeral(ls, seminfo);           
        return TK_NUMBER;           
      }           
      case EOZ: {           
        return TK_EOS;           
      }           
      default: {           
          if (lislalpha(ls->current)||  ls->current > 0x80) {  /* identifier or reserved word? */ 
              TString *ts;              
              do {              
                  if(ls->current > 0x80)              
                  {              
                      save_and_next(ls);              
                      save_and_next(ls);              
                  }              
                  else  
                      save_and_next(ls);              
              }              
              while (lislalnum(ls->current) || ls->current > 0x80);              
              ts = luaX_newstring(ls, luaZ_buffer(ls->buff),              
                  luaZ_bufflen(ls->buff));              
              seminfo->ts = ts;              
              if (isreserved(ts))  /* reserved word? */ 
                  return ts->tsv.extra - 1 + FIRST_RESERVED;              
              else {              
                  return TK_NAME;              
              }              
          }              
          else {  /* single-char tokens (+ - / ...) */ 
              int c = ls->current;              
              next(ls);              
              return c;              
          }              
               }           
    }           
                        
  }           
}

The exclamation mark is where the @ symbol is parsed. Note that the commands, left and right parentheses, commas, and two parameters are passed back in sequence, exactly as lua does, otherwise the grammar checker will think the grammar is wrong!

In addition, Chinese support has been added here. Friends who want Chinese support can refer to lines 166 to 177 of the code ^^

Reprinted at: https://my.oschina.net/gal/blog/200205

Posted on Thu, 12 Sep 2019 11:25:12 -0700 by 7awaka