Browse Source

more liberal syntax for expressions

Roberto Ierusalimschy 24 years ago
parent
commit
40f4e931f3
1 changed files with 70 additions and 81 deletions
  1. 70 81
      lparser.c

+ 70 - 81
lparser.c

@@ -1,5 +1,5 @@
 /*
-** $Id: lparser.c,v 1.131 2001/02/09 18:37:33 roberto Exp roberto $
+** $Id: lparser.c,v 1.132 2001/02/09 20:22:29 roberto Exp roberto $
 ** LL(1) Parser and code generator for Lua
 ** See Copyright Notice in lua.h
 */
@@ -352,7 +352,7 @@ static void close_func (LexState *ls) {
   luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->nlineinfo+1, int);
   f->lineinfo[fs->nlineinfo++] = MAX_INT;  /* end flag */
   f->sizelineinfo = fs->nlineinfo;
-  lua_assert(luaG_checkcode(f));
+  lua_assert(luaG_checkcode(L, f));
   ls->fs = fs->prev;
   lua_assert(fs->bl == NULL);
 }
@@ -433,60 +433,6 @@ static void funcargs (LexState *ls, int slf) {
 }
 
 
-static void var_or_func_tail (LexState *ls, expdesc *v) {
-  for (;;) {
-    switch (ls->t.token) {
-      case '.': {  /* var_or_func_tail -> '.' NAME */
-        next(ls);
-        luaK_tostack(ls, v, 1);  /* `v' must be on stack */
-        luaK_kstr(ls, checkname(ls));
-        v->k = VINDEXED;
-        break;
-      }
-      case '[': {  /* var_or_func_tail -> '[' exp1 ']' */
-        next(ls);
-        luaK_tostack(ls, v, 1);  /* `v' must be on stack */
-        v->k = VINDEXED;
-        exp1(ls);
-        check(ls, ']');
-        break;
-      }
-      case ':': {  /* var_or_func_tail -> ':' NAME funcargs */
-        next(ls);
-        luaK_tostack(ls, v, 1);  /* `v' must be on stack */
-        luaK_code1(ls->fs, OP_PUSHSELF, checkname(ls));
-        funcargs(ls, 1);
-        v->k = VEXP;
-        v->u.l.t = v->u.l.f = NO_JUMP;
-        break;
-      }
-      case '(': case TK_STRING: case '{': {  /* var_or_func_tail -> funcargs */
-        luaK_tostack(ls, v, 1);  /* `v' must be on stack */
-        funcargs(ls, 0);
-        v->k = VEXP;
-        v->u.l.t = v->u.l.f = NO_JUMP;
-        break;
-      }
-      default: return;  /* should be follow... */
-    }
-  }
-}
-
-
-static void var_or_func (LexState *ls, expdesc *v) {
-  /* var_or_func -> ['%'] NAME var_or_func_tail */
-  if (optional(ls, '%')) {  /* upvalue? */
-    pushupvalue(ls, str_checkname(ls));
-    v->k = VEXP;
-    v->u.l.t = v->u.l.f = NO_JUMP;
-  }
-  else  /* variable name */
-    singlevar(ls, str_checkname(ls), v);
-  var_or_func_tail(ls, v);
-}
-
-
-
 /*
 ** {======================================================================
 ** Rules for Constructors
@@ -615,47 +561,51 @@ static void constructor (LexState *ls) {
 ** =======================================================================
 */
 
-
-static void simpleexp (LexState *ls, expdesc *v) {
+static void primaryexp (LexState *ls, expdesc *v) {
   FuncState *fs = ls->fs;
   switch (ls->t.token) {
-    case TK_NUMBER: {  /* simpleexp -> NUMBER */
+    case TK_NUMBER: {
       lua_Number r = ls->t.seminfo.r;
       next(ls);
       luaK_number(fs, r);
       break;
     }
-    case TK_STRING: {  /* simpleexp -> STRING */
+    case TK_STRING: {
       code_string(ls, ls->t.seminfo.ts);  /* must use `seminfo' before `next' */
       next(ls);
       break;
     }
-    case TK_NIL: {  /* simpleexp -> NIL */
+    case TK_NIL: {
       luaK_adjuststack(fs, -1);
       next(ls);
       break;
     }
-    case '{': {  /* simpleexp -> constructor */
+    case '{': {  /* constructor */
       constructor(ls);
       break;
     }
-    case TK_FUNCTION: {  /* simpleexp -> FUNCTION body */
+    case TK_FUNCTION: {
       next(ls);
       body(ls, 0, ls->linenumber);
       break;
     }
-    case '(': {  /* simpleexp -> '(' expr ')' */
+    case '(': {
       next(ls);
       expr(ls, v);
       check(ls, ')');
       return;
     }
-    case TK_NAME: case '%': {
-      var_or_func(ls, v);
+    case TK_NAME: {
+      singlevar(ls, str_checkname(ls), v);
       return;
     }
+    case '%': {
+      next(ls);  /* skip `%' */
+      pushupvalue(ls, str_checkname(ls));
+      break;
+    }
     default: {
-      luaK_error(ls, "<expression> expected");
+      luaK_error(ls, "unexpected symbol");
       return;
     }
   }
@@ -664,10 +614,46 @@ static void simpleexp (LexState *ls, expdesc *v) {
 }
 
 
-static void exp1 (LexState *ls) {
-  expdesc v;
-  expr(ls, &v);
-  luaK_tostack(ls, &v, 1);
+static void simpleexp (LexState *ls, expdesc *v) {
+  /* simpleexp ->
+        primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */
+  primaryexp(ls, v);
+  for (;;) {
+    switch (ls->t.token) {
+      case '.': {  /* '.' NAME */
+        next(ls);
+        luaK_tostack(ls, v, 1);  /* `v' must be on stack */
+        luaK_kstr(ls, checkname(ls));
+        v->k = VINDEXED;
+        break;
+      }
+      case '[': {  /* '[' exp1 ']' */
+        next(ls);
+        luaK_tostack(ls, v, 1);  /* `v' must be on stack */
+        v->k = VINDEXED;
+        exp1(ls);
+        check(ls, ']');
+        break;
+      }
+      case ':': {  /* ':' NAME funcargs */
+        next(ls);
+        luaK_tostack(ls, v, 1);  /* `v' must be on stack */
+        luaK_code1(ls->fs, OP_PUSHSELF, checkname(ls));
+        funcargs(ls, 1);
+        v->k = VEXP;
+        v->u.l.t = v->u.l.f = NO_JUMP;
+        break;
+      }
+      case '(': case TK_STRING: case '{': {  /* funcargs */
+        luaK_tostack(ls, v, 1);  /* `v' must be on stack */
+        funcargs(ls, 0);
+        v->k = VEXP;
+        v->u.l.t = v->u.l.f = NO_JUMP;
+        break;
+      }
+      default: return;  /* should be follow... */
+    }
+  }
 }
 
 
@@ -748,6 +734,13 @@ static void expr (LexState *ls, expdesc *v) {
   subexpr(ls, v, -1);
 }
 
+
+static void exp1 (LexState *ls) {
+  expdesc v;
+  expr(ls, &v);
+  luaK_tostack(ls, &v, 1);
+}
+
 /* }==================================================================== */
 
 
@@ -781,10 +774,10 @@ static void block (LexState *ls) {
 static int assignment (LexState *ls, expdesc *v, int nvars) {
   int left = 0;  /* number of values left in the stack after assignment */
   luaX_checklimit(ls, nvars, MAXVARSLH, "variables in a multiple assignment");
-  if (ls->t.token == ',') {  /* assignment -> ',' NAME assignment */
+  if (ls->t.token == ',') {  /* assignment -> ',' simpleexp assignment */
     expdesc nv;
     next(ls);
-    var_or_func(ls, &nv);
+    simpleexp(ls, &nv);
     check_condition(ls, (nv.k != VEXP), "syntax error");
     left = assignment(ls, &nv, nvars+1);
   }
@@ -998,15 +991,15 @@ static void funcstat (LexState *ls, int line) {
 
 
 static void namestat (LexState *ls) {
-  /* stat -> func | ['%'] NAME assignment */
+  /* stat -> func | assignment */
   FuncState *fs = ls->fs;
   expdesc v;
-  var_or_func(ls, &v);
+  simpleexp(ls, &v);
   if (v.k == VEXP) {  /* stat -> func */
     check_condition(ls, luaK_lastisopen(fs), "syntax error");  /* an upvalue? */
     luaK_setcallreturns(fs, 0);  /* call statement uses no results */
   }
-  else {  /* stat -> ['%'] NAME assignment */
+  else {  /* stat -> assignment */
     int left = assignment(ls, &v, 1);
     luaK_adjuststack(fs, left);  /* remove eventual garbage left on stack */
   }
@@ -1072,10 +1065,6 @@ static int stat (LexState *ls) {
       localstat(ls);
       return 0;
     }
-    case TK_NAME: case '%': {  /* stat -> namestat */
-      namestat(ls);
-      return 0;
-    }
     case TK_RETURN: {  /* stat -> retstat */
       retstat(ls);
       return 1;  /* must be last statement */
@@ -1085,7 +1074,7 @@ static int stat (LexState *ls) {
       return 1;  /* must be last statement */
     }
     default: {
-      luaK_error(ls, "<statement> expected");
+      namestat(ls);
       return 0;  /* to avoid warnings */
     }
   }