Explorar el Código

performance details.

Roberto Ierusalimschy hace 25 años
padre
commit
d83c2a8455
Se han modificado 4 ficheros con 146 adiciones y 133 borrados
  1. 88 83
      llex.c
  2. 2 2
      llex.h
  3. 9 8
      lobject.c
  4. 47 40
      lparser.c

+ 88 - 83
llex.c

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.c,v 1.47 1999/12/22 16:58:36 roberto Exp roberto $
+** $Id: llex.c,v 1.48 1999/12/30 12:40:29 roberto Exp roberto $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -33,7 +33,7 @@
 /* ORDER RESERVED */
 static const char *const reserved [] = {"and", "do", "else", "elseif", "end",
     "function", "if", "local", "nil", "not", "or", "repeat", "return", "then",
-    "until", "while"};
+    "until", "while", "", "..", "...", "==", ">=", "<=", "~=", "", "", ""};
 
 
 void luaX_init (lua_State *L) {
@@ -57,9 +57,15 @@ void luaX_syntaxerror (LexState *ls, const char *s, const char *token) {
 }
 
 
-void luaX_error (LexState *ls, const char *s) {
-  save(ls->L, '\0');
-  luaX_syntaxerror(ls, s, luaL_buffer(ls->L));
+void luaX_error (LexState *ls, const char *s, int token) {
+  char buff[TOKEN_LEN];
+  luaX_token2str(token, buff);
+  if (buff[0] == '\0') {
+    save(ls->L, '\0');
+    luaX_syntaxerror(ls, s, luaL_buffer(ls->L));
+  }
+  else
+    luaX_syntaxerror(ls, s, buff);
 }
 
 
@@ -156,7 +162,7 @@ static void ifskip (lua_State *L, LexState *LS) {
     if (LS->current == '\n')
       inclinenumber(L, LS);
     else if (LS->current == EOZ)
-      luaX_error(LS, "input ends inside a $if");
+      luaX_error(LS, "input ends inside a $if", EOS);
     else next(LS);
   }
 }
@@ -231,13 +237,13 @@ static void inclinenumber (lua_State *L, LexState *LS) {
 
 
 
-static int read_long_string (lua_State *L, LexState *LS) {
+static void read_long_string (lua_State *L, LexState *LS) {
   int cont = 0;
   for (;;) {
     switch (LS->current) {
       case EOZ:
-        luaX_error(LS, "unfinished long string");
-        return EOS;  /* to avoid warnings */
+        luaX_error(LS, "unfinished long string", STRING);
+        break;  /* to avoid warnings */
       case '[':
         save_and_next(L, LS);
         if (LS->current == '[') {
@@ -264,7 +270,52 @@ static int read_long_string (lua_State *L, LexState *LS) {
   save_and_next(L, LS);  /* skip the second ']' */
   LS->seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+2),
                           L->Mbuffnext-L->Mbuffbase-4);
-  return STRING;
+}
+
+
+static void read_string (lua_State *L, LexState *LS, int del) {
+  save_and_next(L, LS);
+  while (LS->current != del) {
+    switch (LS->current) {
+      case EOZ:  case '\n':
+        luaX_error(LS, "unfinished string", STRING);
+        break;  /* to avoid warnings */
+      case '\\':
+        next(LS);  /* do not save the '\' */
+        switch (LS->current) {
+          case 'a': save(L, '\a'); next(LS); break;
+          case 'b': save(L, '\b'); next(LS); break;
+          case 'f': save(L, '\f'); next(LS); break;
+          case 'n': save(L, '\n'); next(LS); break;
+          case 'r': save(L, '\r'); next(LS); break;
+          case 't': save(L, '\t'); next(LS); break;
+          case 'v': save(L, '\v'); next(LS); break;
+          case '\n': save(L, '\n'); inclinenumber(L, LS); break;
+          case '0': case '1': case '2': case '3': case '4':
+          case '5': case '6': case '7': case '8': case '9': {
+            int c = 0;
+            int i = 0;
+            do {
+              c = 10*c + (LS->current-'0');
+              next(LS);
+            } while (++i<3 && isdigit(LS->current));
+            if (c != (unsigned char)c)
+              luaX_error(LS, "escape sequence too large", STRING);
+            save(L, c);
+            break;
+          }
+          default:  /* handles \\, \", \', and \? */
+            save(L, LS->current);
+            next(LS);
+        }
+        break;
+      default:
+        save_and_next(L, LS);
+    }
+  }
+  save_and_next(L, LS);  /* skip delimiter */
+  LS->seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+1),
+                          L->Mbuffnext-L->Mbuffbase-2);
 }
 
 
@@ -283,10 +334,9 @@ int luaX_lex (LexState *LS) {
         continue;
 
       case '-':
-        save_and_next(L, LS);
+        next(LS);
         if (LS->current != '-') return '-';
         do { next(LS); } while (LS->current != '\n' && LS->current != EOZ);
-        luaL_resetbuffer(L);
         continue;
 
       case '[':
@@ -294,88 +344,41 @@ int luaX_lex (LexState *LS) {
         if (LS->current != '[') return '[';
         else {
           save_and_next(L, LS);  /* pass the second '[' */
-          return read_long_string(L, LS);
+          read_long_string(L, LS);
+          return STRING;
         }
 
       case '=':
-        save_and_next(L, LS);
+        next(LS);
         if (LS->current != '=') return '=';
-        else { save_and_next(L, LS); return EQ; }
+        else { next(LS); return EQ; }
 
       case '<':
-        save_and_next(L, LS);
+        next(LS);
         if (LS->current != '=') return '<';
-        else { save_and_next(L, LS); return LE; }
+        else { next(LS); return LE; }
 
       case '>':
-        save_and_next(L, LS);
+        next(LS);
         if (LS->current != '=') return '>';
-        else { save_and_next(L, LS); return GE; }
+        else { next(LS); return GE; }
 
       case '~':
-        save_and_next(L, LS);
+        next(LS);
         if (LS->current != '=') return '~';
-        else { save_and_next(L, LS); return NE; }
+        else { next(LS); return NE; }
 
       case '"':
-      case '\'': {
-        int del = LS->current;
-        save_and_next(L, LS);
-        while (LS->current != del) {
-          switch (LS->current) {
-            case EOZ:
-            case '\n':
-              luaX_error(LS, "unfinished string");
-              return EOS;  /* to avoid warnings */
-            case '\\':
-              next(LS);  /* do not save the '\' */
-              switch (LS->current) {
-                case 'a': save(L, '\a'); next(LS); break;
-                case 'b': save(L, '\b'); next(LS); break;
-                case 'f': save(L, '\f'); next(LS); break;
-                case 'n': save(L, '\n'); next(LS); break;
-                case 'r': save(L, '\r'); next(LS); break;
-                case 't': save(L, '\t'); next(LS); break;
-                case 'v': save(L, '\v'); next(LS); break;
-                case '\n': save(L, '\n'); inclinenumber(L, LS); break;
-                default : {
-                  if (isdigit(LS->current)) {
-                    int c = 0;
-                    int i = 0;
-                    do {
-                      c = 10*c + (LS->current-'0');
-                      next(LS);
-                    } while (++i<3 && isdigit(LS->current));
-                    if (c != (unsigned char)c)
-                      luaX_error(LS, "escape sequence too large");
-                    save(L, c);
-                  }
-                  else {  /* handles \, ", ', and ? */
-                    save(L, LS->current);
-                    next(LS);
-                  }
-                  break;
-                }
-              }
-              break;
-            default:
-              save_and_next(L, LS);
-          }
-        }
-        save_and_next(L, LS);  /* skip delimiter */
-        LS->seminfo.ts = luaS_newlstr(L, L->Mbuffer+(L->Mbuffbase+1),
-                                L->Mbuffnext-L->Mbuffbase-2);
+      case '\'':
+        read_string(L, LS, LS->current);
         return STRING;
-      }
 
       case '.':
         save_and_next(L, LS);
-        if (LS->current == '.')
-        {
-          save_and_next(L, LS);
-          if (LS->current == '.')
-          {
-            save_and_next(L, LS);
+        if (LS->current == '.') {
+          next(LS);
+          if (LS->current == '.') {
+            next(LS);
             return DOTS;   /* ... */
           }
           else return CONC;   /* .. */
@@ -392,14 +395,14 @@ int luaX_lex (LexState *LS) {
           save_and_next(L, LS);
           if (LS->current == '.') {
             save(L, '.');
-            luaX_error(LS, 
-              "ambiguous syntax (decimal point x string concatenation)");
+            luaX_error(LS, "ambiguous syntax"
+                       " (decimal point x string concatenation)", NUMBER);
           }
         }
       fraction:  /* LUA_NUMBER */
         while (isdigit(LS->current))
           save_and_next(L, LS);
-        if (toupper(LS->current) == 'E') {
+        if (LS->current == 'e' || LS->current == 'E') {
           save_and_next(L, LS);  /* read 'E' */
           if (LS->current == '+' || LS->current == '-')
             save_and_next(L, LS);  /* optional exponent sign */
@@ -408,23 +411,25 @@ int luaX_lex (LexState *LS) {
         }
         save(L, '\0');
         if (!luaO_str2d(L->Mbuffer+L->Mbuffbase, &LS->seminfo.r))
-          luaX_error(LS, "malformed number");
+          luaX_error(LS, "malformed number", NUMBER);
         return NUMBER;
 
       case EOZ:
         if (LS->iflevel > 0)
-          luaX_error(LS, "input ends inside a $if");
+          luaX_error(LS, "input ends inside a $if", EOS);
         return EOS;
 
+      case '_': goto tname;
+
       default:
-        if (LS->current != '_' && !isalpha(LS->current)) {
+        if (!isalpha(LS->current)) {
           int c = LS->current;
           if (iscntrl(c))
             luaX_invalidchar(LS, c);
-          save_and_next(L, LS);
+          next(LS);
           return c;
         }
-        else {  /* identifier or reserved word */
+        tname: {  /* identifier or reserved word */
           TaggedString *ts;
           do {
             save_and_next(L, LS);

+ 2 - 2
llex.h

@@ -1,5 +1,5 @@
 /*
-** $Id: llex.h,v 1.15 1999/11/22 13:12:07 roberto Exp roberto $
+** $Id: llex.h,v 1.16 1999/12/27 17:33:22 roberto Exp roberto $
 ** Lexical Analyzer
 ** See Copyright Notice in lua.h
 */
@@ -63,7 +63,7 @@ void luaX_init (lua_State *L);
 void luaX_setinput (lua_State *L, LexState *LS, ZIO *z);
 int luaX_lex (LexState *LS);
 void luaX_syntaxerror (LexState *ls, const char *s, const char *token);
-void luaX_error (LexState *ls, const char *s);
+void luaX_error (LexState *ls, const char *s, int token);
 void luaX_token2str (int token, char *s);
 
 

+ 9 - 8
lobject.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lobject.c,v 1.28 1999/12/23 18:19:57 roberto Exp roberto $
+** $Id: lobject.c,v 1.29 1999/12/30 18:28:40 roberto Exp roberto $
 ** Some generic functions over Lua objects
 ** See Copyright Notice in lua.h
 */
@@ -87,9 +87,9 @@ int luaO_str2d (const char *s, real *result) {  /* LUA_NUMBER */
   int point = 0;  /* number of decimal digits */
   int sig;
   while (isspace((unsigned char)*s)) s++;
-  sig = 1;
+  sig = 0;
   switch (*s) {
-    case '-': sig = -1;  /* go through */
+    case '-': sig = 1;  /* go through */
     case '+': s++;
   }
   if (! (isdigit((unsigned char)*s) ||
@@ -104,20 +104,21 @@ int luaO_str2d (const char *s, real *result) {  /* LUA_NUMBER */
       point++;
     }
   }
-  a *= sig;
-  if (toupper((unsigned char)*s) == 'E') {
+  if (sig) a = -a;
+  if (*s == 'e' || *s == 'E') {
     int e = 0;
     s++;
-    sig = 1;
+    sig = 0;
     switch (*s) {
-      case '-': sig = -1;  /* go through */
+      case '-': sig = 1;  /* go through */
       case '+': s++;
     }
     if (!isdigit((unsigned char)*s)) return 0;  /* no digit in the exponent? */
     do {
       e = 10*e + (*(s++)-'0');
     } while (isdigit((unsigned char)*s));
-    point -= sig*e;
+    if (sig) e = -e;
+    point -= e;
   }
   while (isspace((unsigned char)*s)) s++;
   if (*s != '\0') return 0;  /* invalid trailing characters? */

+ 47 - 40
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.54 2000/01/12 16:24:39 roberto Exp roberto $
+** $Id: lparser.c,v 1.55 2000/01/25 13:57:18 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -119,11 +119,16 @@ static void exp1 (LexState *ls);
 
 
 
+static void luaY_error (LexState *ls, const char *msg) {
+  luaX_error(ls, msg, ls->token);
+}
+
+
 static void checklimit (LexState *ls, int val, int limit, const char *msg) {
   if (val > limit) {
     char buff[100];
     sprintf(buff, "too many %.50s (limit=%d)", msg, limit);
-    luaX_error(ls, buff);
+    luaY_error(ls, buff);
   }
 }
 
@@ -145,7 +150,7 @@ static void deltastack (LexState *ls, int delta) {
   fs->stacksize += delta;
   if (fs->stacksize > fs->maxstacksize) {
     if (fs->stacksize > MAX_BYTE)
-      luaX_error(ls, "function/expression too complex");
+      luaY_error(ls, "function/expression too complex");
     fs->maxstacksize = fs->stacksize;
   }
 }
@@ -160,7 +165,7 @@ static void code_oparg_at (LexState *ls, int pc, OpCode op,
     code[pc+1] = (Byte)arg;
   }
   else if (arg > MAX_ARG)
-    luaX_error(ls, "code too long");
+    luaY_error(ls, "code too long");
   else {  /* MAX_BYTE < arg < MAX_ARG */
     if (arg > MAX_WORD) {
       code[pc] = (Byte)LONGARG;
@@ -599,20 +604,6 @@ static void close_func (LexState *ls) {
 }
 
 
-
-static const int expfollow [] = {ELSE, ELSEIF, THEN, IF, WHILE, REPEAT,
-   DO, NAME, LOCAL, FUNCTION, END, UNTIL, RETURN, ')', ']', '}', ';',
-   EOS, ',',  0};
-
-
-static int is_in (int tok, const int *toks) {
-  const int *t;
-  for (t=toks; *t; t++)
-    if (*t == tok) return t-toks;
-  return -1;
-}
-
-
 static void next (LexState *ls) {
   ls->token = luaX_lex(ls);
 }
@@ -622,12 +613,12 @@ static void error_expected (LexState *ls, int token) {
   char buff[100], t[TOKEN_LEN];
   luaX_token2str(token, t);
   sprintf(buff, "`%.20s' expected", t);
-  luaX_error(ls, buff);
+  luaY_error(ls, buff);
 }
 
 
 static void error_unexpected (LexState *ls) {
-  luaX_error(ls, "unexpected token");
+  luaY_error(ls, "unexpected token");
 }
 
 
@@ -641,7 +632,7 @@ static void error_unmatched (LexState *ls, int what, int who, int where) {
     luaX_token2str(who, t_who);
     sprintf(buff, "`%.20s' expected (to close `%.20s' at line %d)",
             t_what, t_who, where);
-    luaX_error(ls, buff);
+    luaY_error(ls, buff);
   }
 }
 
@@ -661,7 +652,7 @@ static void check_match (LexState *ls, int what, int who, int where) {
 static int checkname (LexState *ls) {
   int sc;
   if (ls->token != NAME)
-    luaX_error(ls, "<name> expected");
+    luaY_error(ls, "<name> expected");
   sc = string_constant(ls, ls->fs, ls->seminfo.ts);
   next(ls);
   return sc;
@@ -691,7 +682,7 @@ TProtoFunc *luaY_parser (lua_State *L, ZIO *z) {
   next(&lexstate);  /* read first token */
   chunk(&lexstate);
   if (lexstate.token != EOS)
-    luaX_error(&lexstate, "<eof> expected");
+    luaY_error(&lexstate, "<eof> expected");
   close_func(&lexstate);
   return funcstate.f;
 }
@@ -782,7 +773,7 @@ static int funcparams (LexState *ls, int slf, vardesc *v) {
       break;
 
     default:
-      luaX_error(ls, "function arguments expected");
+      luaY_error(ls, "function arguments expected");
       break;
   }
   code_setname(ls, v);
@@ -871,7 +862,7 @@ static void recfield (LexState *ls) {
       check(ls, ']');
       break;
 
-    default: luaX_error(ls, "<name> or `[' expected");
+    default: luaY_error(ls, "<name> or `[' expected");
   }
   check(ls, '=');
   exp1(ls);
@@ -977,7 +968,7 @@ static void constructor (LexState *ls) {
     next(ls);
     constructor_part(ls, &other_cd);
     if (cd.k == other_cd.k)  /* repeated parts? */
-      luaX_error(ls, "invalid constructor syntax");
+      luaY_error(ls, "invalid constructor syntax");
     nelems += other_cd.n;
   }
   check_match(ls, '}', '{', line);
@@ -992,8 +983,8 @@ static void constructor (LexState *ls) {
 /*
 ** {======================================================================
 ** For parsing expressions, we use a classic stack with priorities.
-** Each binary operator is represented by its index in `binop' + FIRSTBIN
-** (EQ=2, NE=3, ... '^'=13). The unary NOT is 0 and UNMINUS is 1.
+** Each binary operator is represented by an index: EQ=2, NE=3, ... '^'=13.
+** The unary NOT is 0 and UNMINUS is 1.
 ** =======================================================================
 */
 
@@ -1008,8 +999,6 @@ static void constructor (LexState *ls) {
 */
 #define POW	13
 
-static const int binop [] = {EQ, NE, '>', '<', LE, GE, CONC,
-                             '+', '-', '*', '/', '^', 0};
 
 static const int priority [POW+1] =  {5, 5, 1, 1, 1, 1, 1, 1, 2, 3, 3, 4, 4, 6};
 
@@ -1024,10 +1013,31 @@ typedef struct stack_op {
 } stack_op;
 
 
+/*
+** returns the index of a binary operator
+*/
+static int binop (int op) {
+  switch (op) {
+    case EQ: return FIRSTBIN;
+    case  NE: return FIRSTBIN+1;
+    case  '>': return FIRSTBIN+2;
+    case  '<': return FIRSTBIN+3;
+    case  LE: return FIRSTBIN+4;
+    case  GE: return FIRSTBIN+5;
+    case  CONC: return FIRSTBIN+6;
+    case  '+': return FIRSTBIN+7;
+    case  '-': return FIRSTBIN+8;
+    case  '*': return FIRSTBIN+9;
+    case  '/': return FIRSTBIN+10;
+    case  '^': return FIRSTBIN+11;
+    default: return -1;
+  }
+}
+
 
 static void push (LexState *ls, stack_op *s, int op) {
   if (s->top >= MAXOPS)
-    luaX_error(ls, "expression too complex");
+    luaY_error(ls, "expression too complex");
   s->ops[s->top++] = op;
 }
 
@@ -1086,7 +1096,7 @@ static void simpleexp (LexState *ls, vardesc *v, stack_op *s) {
       return;
 
     default:
-      luaX_error(ls, "<expression> expected");
+      luaY_error(ls, "<expression> expected");
       return;
   }
   v->k = VEXP; v->info = 0;
@@ -1108,8 +1118,7 @@ static void arith_exp (LexState *ls, vardesc *v) {
   int op;
   s.top = 0;
   prefixexp(ls, v, &s);
-  while ((op = is_in(ls->token, binop)) >= 0) {
-    op += FIRSTBIN;
+  while ((op = binop(ls->token)) >= 0) {
     lua_pushvar(ls, v);
     /* '^' is right associative, so must 'simulate' a higher priority */
     pop_to(ls, &s, (op == POW)?priority[op]+1:priority[op]);
@@ -1129,8 +1138,6 @@ static void exp1 (LexState *ls) {
   vardesc v;
   expr(ls, &v);
   lua_pushvar(ls, &v);
-  if (is_in(ls->token, expfollow) < 0)
-    luaX_error(ls, "malformed expression");
 }
 
 
@@ -1180,7 +1187,7 @@ static int assignment (LexState *ls, vardesc *v, int nvars) {
     next(ls);
     var_or_func(ls, &nv);
     if (nv.k == VEXP)
-      luaX_error(ls, "syntax error");
+      luaY_error(ls, "syntax error");
     left = assignment(ls, &nv, nvars+1);
   }
   else {  /* assignment -> '=' explist1 */
@@ -1313,7 +1320,7 @@ static void namestat (LexState *ls) {
   var_or_func(ls, &v);
   if (v.k == VEXP) {  /* stat -> func */
     if (v.info == 0)  /* is just an upper value? */
-      luaX_error(ls, "syntax error");
+      luaY_error(ls, "syntax error");
     close_exp(ls, v.info, 0);
   }
   else {  /* stat -> ['%'] NAME assignment */
@@ -1410,14 +1417,14 @@ static void parlist (LexState *ls) {
           case NAME:  /* tailparlist -> NAME [',' tailparlist] */
             goto init;
 
-          default: luaX_error(ls, "<name> or `...' expected");
+          default: luaY_error(ls, "<name> or `...' expected");
         }
       }
       break;
 
     case ')': break;  /* parlist -> empty */
 
-    default: luaX_error(ls, "<name> or `...' expected");
+    default: luaY_error(ls, "<name> or `...' expected");
   }
   code_args(ls, nparams, dots);
 }