⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lparser.c

📁 Lua 语言解释器源码
💻 C
📖 第 1 页 / 共 3 页
字号:
        lh->v.aux = extra;  /* previous assignment will use safe copy */      }    }  }  if (conflict) {    luaK_codeABC(fs, OP_MOVE, fs->freereg, v->info, 0);  /* make copy */    luaK_reserveregs(fs, 1);  }}static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) {  expdesc e;  check_condition(ls, VLOCAL <= lh->v.k && lh->v.k <= VINDEXED,                      "syntax error");  if (testnext(ls, ',')) {  /* assignment -> `,' primaryexp assignment */    struct LHS_assign nv;    nv.prev = lh;    primaryexp(ls, &nv.v);    if (nv.v.k == VLOCAL)      check_conflict(ls, lh, &nv.v);    assignment(ls, &nv, nvars+1);  }  else {  /* assignment -> `=' explist1 */    int nexps;    check(ls, '=');    nexps = explist1(ls, &e);    if (nexps != nvars) {      adjust_assign(ls, nvars, nexps, &e);      if (nexps > nvars)        ls->fs->freereg -= nexps - nvars;  /* remove extra values */    }    else {      luaK_setcallreturns(ls->fs, &e, 1);  /* close last expression */      luaK_storevar(ls->fs, &lh->v, &e);      return;  /* avoid default */    }  }  init_exp(&e, VNONRELOC, ls->fs->freereg-1);  /* default assignment */  luaK_storevar(ls->fs, &lh->v, &e);}static void cond (LexState *ls, expdesc *v) {  /* cond -> exp */  expr(ls, v);  /* read condition */  if (v->k == VNIL) v->k = VFALSE;  /* `falses' are all equal here */  luaK_goiftrue(ls->fs, v);  luaK_patchtohere(ls->fs, v->t);}/*** The while statement optimizes its code by coding the condition** after its body (and thus avoiding one jump in the loop).*//*** maximum size of expressions for optimizing `while' code*/#ifndef MAXEXPWHILE#define MAXEXPWHILE	100#endif/*** the call `luaK_goiffalse' may grow the size of an expression by** at most this:*/#define EXTRAEXP	5static void whilestat (LexState *ls, int line) {  /* whilestat -> WHILE cond DO block END */  Instruction codeexp[MAXEXPWHILE + EXTRAEXP];  int lineexp;  int i;  int sizeexp;  FuncState *fs = ls->fs;  int whileinit, blockinit, expinit;  expdesc v;  BlockCnt bl;  next(ls);  /* skip WHILE */  whileinit = luaK_jump(fs);  /* jump to condition (which will be moved) */  expinit = luaK_getlabel(fs);  expr(ls, &v);  /* parse condition */  if (v.k == VK) v.k = VTRUE;  /* `trues' are all equal here */  lineexp = ls->linenumber;  luaK_goiffalse(fs, &v);  luaK_concat(fs, &v.f, fs->jpc);  fs->jpc = NO_JUMP;  sizeexp = fs->pc - expinit;  /* size of expression code */  if (sizeexp > MAXEXPWHILE)     luaX_syntaxerror(ls, "`while' condition too complex");  for (i = 0; i < sizeexp; i++)  /* save `exp' code */    codeexp[i] = fs->f->code[expinit + i];  fs->pc = expinit;  /* remove `exp' code */  enterblock(fs, &bl, 1);  check(ls, TK_DO);  blockinit = luaK_getlabel(fs);  block(ls);  luaK_patchtohere(fs, whileinit);  /* initial jump jumps to here */  /* move `exp' back to code */  if (v.t != NO_JUMP) v.t += fs->pc - expinit;  if (v.f != NO_JUMP) v.f += fs->pc - expinit;  for (i=0; i<sizeexp; i++)    luaK_code(fs, codeexp[i], lineexp);  check_match(ls, TK_END, TK_WHILE, line);  leaveblock(fs);  luaK_patchlist(fs, v.t, blockinit);  /* true conditions go back to loop */  luaK_patchtohere(fs, v.f);  /* false conditions finish the loop */}static void repeatstat (LexState *ls, int line) {  /* repeatstat -> REPEAT block UNTIL cond */  FuncState *fs = ls->fs;  int repeat_init = luaK_getlabel(fs);  expdesc v;  BlockCnt bl;  enterblock(fs, &bl, 1);  next(ls);  block(ls);  check_match(ls, TK_UNTIL, TK_REPEAT, line);  cond(ls, &v);  luaK_patchlist(fs, v.f, repeat_init);  leaveblock(fs);}static int exp1 (LexState *ls) {  expdesc e;  int k;  expr(ls, &e);  k = e.k;  luaK_exp2nextreg(ls->fs, &e);  return k;}static void forbody (LexState *ls, int base, int line, int nvars, int isnum) {  BlockCnt bl;  FuncState *fs = ls->fs;  int prep, endfor;  adjustlocalvars(ls, nvars);  /* scope for all variables */  check(ls, TK_DO);  enterblock(fs, &bl, 1);  /* loop block */  prep = luaK_getlabel(fs);  block(ls);  luaK_patchtohere(fs, prep-1);  endfor = (isnum) ? luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP) :                     luaK_codeABC(fs, OP_TFORLOOP, base, 0, nvars - 3);  luaK_fixline(fs, line);  /* pretend that `OP_FOR' starts the loop */  luaK_patchlist(fs, (isnum) ? endfor : luaK_jump(fs), prep);  leaveblock(fs);}static void fornum (LexState *ls, TString *varname, int line) {  /* fornum -> NAME = exp1,exp1[,exp1] DO body */  FuncState *fs = ls->fs;  int base = fs->freereg;  new_localvar(ls, varname, 0);  new_localvarstr(ls, "(for limit)", 1);  new_localvarstr(ls, "(for step)", 2);  check(ls, '=');  exp1(ls);  /* initial value */  check(ls, ',');  exp1(ls);  /* limit */  if (testnext(ls, ','))    exp1(ls);  /* optional step */  else {  /* default step = 1 */    luaK_codeABx(fs, OP_LOADK, fs->freereg, luaK_numberK(fs, 1));    luaK_reserveregs(fs, 1);  }  luaK_codeABC(fs, OP_SUB, fs->freereg - 3, fs->freereg - 3, fs->freereg - 1);  luaK_jump(fs);  forbody(ls, base, line, 3, 1);}static void forlist (LexState *ls, TString *indexname) {  /* forlist -> NAME {,NAME} IN explist1 DO body */  FuncState *fs = ls->fs;  expdesc e;  int nvars = 0;  int line;  int base = fs->freereg;  new_localvarstr(ls, "(for generator)", nvars++);  new_localvarstr(ls, "(for state)", nvars++);  new_localvar(ls, indexname, nvars++);  while (testnext(ls, ','))    new_localvar(ls, str_checkname(ls), nvars++);  check(ls, TK_IN);  line = ls->linenumber;  adjust_assign(ls, nvars, explist1(ls, &e), &e);  luaK_checkstack(fs, 3);  /* extra space to call generator */  luaK_codeAsBx(fs, OP_TFORPREP, base, NO_JUMP);  forbody(ls, base, line, nvars, 0);}static void forstat (LexState *ls, int line) {  /* forstat -> fornum | forlist */  FuncState *fs = ls->fs;  TString *varname;  BlockCnt bl;  enterblock(fs, &bl, 0);  /* block to control variable scope */  next(ls);  /* skip `for' */  varname = str_checkname(ls);  /* first variable name */  switch (ls->t.token) {    case '=': fornum(ls, varname, line); break;    case ',': case TK_IN: forlist(ls, varname); break;    default: luaX_syntaxerror(ls, "`=' or `in' expected");  }  check_match(ls, TK_END, TK_FOR, line);  leaveblock(fs);}static void test_then_block (LexState *ls, expdesc *v) {  /* test_then_block -> [IF | ELSEIF] cond THEN block */  next(ls);  /* skip IF or ELSEIF */  cond(ls, v);  check(ls, TK_THEN);  block(ls);  /* `then' part */}static void ifstat (LexState *ls, int line) {  /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */  FuncState *fs = ls->fs;  expdesc v;  int escapelist = NO_JUMP;  test_then_block(ls, &v);  /* IF cond THEN block */  while (ls->t.token == TK_ELSEIF) {    luaK_concat(fs, &escapelist, luaK_jump(fs));    luaK_patchtohere(fs, v.f);    test_then_block(ls, &v);  /* ELSEIF cond THEN block */  }  if (ls->t.token == TK_ELSE) {    luaK_concat(fs, &escapelist, luaK_jump(fs));    luaK_patchtohere(fs, v.f);    next(ls);  /* skip ELSE (after patch, for correct line info) */    block(ls);  /* `else' part */  }  else    luaK_concat(fs, &escapelist, v.f);  luaK_patchtohere(fs, escapelist);  check_match(ls, TK_END, TK_IF, line);}static void localfunc (LexState *ls) {  expdesc v, b;  FuncState *fs = ls->fs;  new_localvar(ls, str_checkname(ls), 0);  init_exp(&v, VLOCAL, fs->freereg);  luaK_reserveregs(fs, 1);  adjustlocalvars(ls, 1);  body(ls, &b, 0, ls->linenumber);  luaK_storevar(fs, &v, &b);  /* debug information will only see the variable after this point! */  getlocvar(fs, fs->nactvar - 1).startpc = fs->pc;}static void localstat (LexState *ls) {  /* stat -> LOCAL NAME {`,' NAME} [`=' explist1] */  int nvars = 0;  int nexps;  expdesc e;  do {    new_localvar(ls, str_checkname(ls), nvars++);  } while (testnext(ls, ','));  if (testnext(ls, '='))    nexps = explist1(ls, &e);  else {    e.k = VVOID;    nexps = 0;  }  adjust_assign(ls, nvars, nexps, &e);  adjustlocalvars(ls, nvars);}static int funcname (LexState *ls, expdesc *v) {  /* funcname -> NAME {field} [`:' NAME] */  int needself = 0;  singlevar(ls, v, 1);  while (ls->t.token == '.')    luaY_field(ls, v);  if (ls->t.token == ':') {    needself = 1;    luaY_field(ls, v);  }  return needself;}static void funcstat (LexState *ls, int line) {  /* funcstat -> FUNCTION funcname body */  int needself;  expdesc v, b;  next(ls);  /* skip FUNCTION */  needself = funcname(ls, &v);  body(ls, &b, needself, line);  luaK_storevar(ls->fs, &v, &b);  luaK_fixline(ls->fs, line);  /* definition `happens' in the first line */}static void exprstat (LexState *ls) {  /* stat -> func | assignment */  FuncState *fs = ls->fs;  struct LHS_assign v;  primaryexp(ls, &v.v);  if (v.v.k == VCALL) {  /* stat -> func */    luaK_setcallreturns(fs, &v.v, 0);  /* call statement uses no results */  }  else {  /* stat -> assignment */    v.prev = NULL;    assignment(ls, &v, 1);  }}static void retstat (LexState *ls) {  /* stat -> RETURN explist */  FuncState *fs = ls->fs;  expdesc e;  int first, nret;  /* registers with returned values */  next(ls);  /* skip RETURN */  if (block_follow(ls->t.token) || ls->t.token == ';')    first = nret = 0;  /* return no values */  else {    nret = explist1(ls, &e);  /* optional return values */    if (e.k == VCALL) {      luaK_setcallreturns(fs, &e, LUA_MULTRET);      if (nret == 1) {  /* tail call? */        SET_OPCODE(getcode(fs,&e), OP_TAILCALL);        lua_assert(GETARG_A(getcode(fs,&e)) == fs->nactvar);      }      first = fs->nactvar;      nret = LUA_MULTRET;  /* return all values */    }    else {      if (nret == 1)  /* only one single value? */        first = luaK_exp2anyreg(fs, &e);      else {        luaK_exp2nextreg(fs, &e);  /* values must go to the `stack' */        first = fs->nactvar;  /* return all `active' values */        lua_assert(nret == fs->freereg - first);      }    }  }  luaK_codeABC(fs, OP_RETURN, first, nret+1, 0);}static void breakstat (LexState *ls) {  /* stat -> BREAK [NAME] */  FuncState *fs = ls->fs;  BlockCnt *bl = fs->bl;  int upval = 0;  next(ls);  /* skip BREAK */  while (bl && !bl->isbreakable) {    upval |= bl->upval;    bl = bl->previous;  }  if (!bl)    luaX_syntaxerror(ls, "no loop to break");  if (upval)    luaK_codeABC(fs, OP_CLOSE, bl->nactvar, 0, 0);  luaK_concat(fs, &bl->breaklist, luaK_jump(fs));}static int statement (LexState *ls) {  int line = ls->linenumber;  /* may be needed for error messages */  switch (ls->t.token) {    case TK_IF: {  /* stat -> ifstat */      ifstat(ls, line);      return 0;    }    case TK_WHILE: {  /* stat -> whilestat */      whilestat(ls, line);      return 0;    }    case TK_DO: {  /* stat -> DO block END */      next(ls);  /* skip DO */      block(ls);      check_match(ls, TK_END, TK_DO, line);      return 0;    }    case TK_FOR: {  /* stat -> forstat */      forstat(ls, line);      return 0;    }    case TK_REPEAT: {  /* stat -> repeatstat */      repeatstat(ls, line);      return 0;    }    case TK_FUNCTION: {      funcstat(ls, line);  /* stat -> funcstat */      return 0;    }    case TK_LOCAL: {  /* stat -> localstat */      next(ls);  /* skip LOCAL */      if (testnext(ls, TK_FUNCTION))  /* local function? */        localfunc(ls);      else        localstat(ls);      return 0;    }    case TK_RETURN: {  /* stat -> retstat */      retstat(ls);      return 1;  /* must be last statement */    }    case TK_BREAK: {  /* stat -> breakstat */      breakstat(ls);      return 1;  /* must be last statement */    }    default: {      exprstat(ls);      return 0;  /* to avoid warnings */    }  }}static void chunk (LexState *ls) {  /* chunk -> { stat [`;'] } */  int islast = 0;  enterlevel(ls);  while (!islast && !block_follow(ls->t.token)) {    islast = statement(ls);    testnext(ls, ';');    lua_assert(ls->fs->freereg >= ls->fs->nactvar);    ls->fs->freereg = ls->fs->nactvar;  /* free registers */  }  leavelevel(ls);}/* }====================================================================== */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -