diff options
author | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-11-22 13:56:04 -0200 |
---|---|---|
committer | Roberto Ierusalimschy <roberto@inf.puc-rio.br> | 2018-11-22 13:56:04 -0200 |
commit | 35296e1fde705b3ac8356a4f4ce426497cf7b64c (patch) | |
tree | 59b369957490dd472f04576afe4a225e399c2995 /lparser.c | |
parent | bb0185b196773b878f0bf6b6c6a4a01dbf8c2b83 (diff) | |
download | lua-35296e1fde705b3ac8356a4f4ce426497cf7b64c.tar.gz lua-35296e1fde705b3ac8356a4f4ce426497cf7b64c.tar.bz2 lua-35296e1fde705b3ac8356a4f4ce426497cf7b64c.zip |
Details
comments and other janitorial work.
Diffstat (limited to 'lparser.c')
-rw-r--r-- | lparser.c | 118 |
1 files changed, 85 insertions, 33 deletions
@@ -10,6 +10,7 @@ | |||
10 | #include "lprefix.h" | 10 | #include "lprefix.h" |
11 | 11 | ||
12 | 12 | ||
13 | #include <limits.h> | ||
13 | #include <string.h> | 14 | #include <string.h> |
14 | 15 | ||
15 | #include "lua.h" | 16 | #include "lua.h" |
@@ -87,6 +88,9 @@ static void checklimit (FuncState *fs, int v, int l, const char *what) { | |||
87 | } | 88 | } |
88 | 89 | ||
89 | 90 | ||
91 | /* | ||
92 | ** Test whether next token is 'c'; if so, skip it. | ||
93 | */ | ||
90 | static int testnext (LexState *ls, int c) { | 94 | static int testnext (LexState *ls, int c) { |
91 | if (ls->t.token == c) { | 95 | if (ls->t.token == c) { |
92 | luaX_next(ls); | 96 | luaX_next(ls); |
@@ -96,12 +100,18 @@ static int testnext (LexState *ls, int c) { | |||
96 | } | 100 | } |
97 | 101 | ||
98 | 102 | ||
103 | /* | ||
104 | ** Check that next token is 'c'. | ||
105 | */ | ||
99 | static void check (LexState *ls, int c) { | 106 | static void check (LexState *ls, int c) { |
100 | if (ls->t.token != c) | 107 | if (ls->t.token != c) |
101 | error_expected(ls, c); | 108 | error_expected(ls, c); |
102 | } | 109 | } |
103 | 110 | ||
104 | 111 | ||
112 | /* | ||
113 | ** Check that next token is 'c' and skip it. | ||
114 | */ | ||
105 | static void checknext (LexState *ls, int c) { | 115 | static void checknext (LexState *ls, int c) { |
106 | check(ls, c); | 116 | check(ls, c); |
107 | luaX_next(ls); | 117 | luaX_next(ls); |
@@ -111,11 +121,15 @@ static void checknext (LexState *ls, int c) { | |||
111 | #define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } | 121 | #define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } |
112 | 122 | ||
113 | 123 | ||
114 | 124 | /* | |
125 | ** Check that next token is 'what' and skip it. In case of error, | ||
126 | ** raise an error that the expected 'what' should match a 'who' | ||
127 | ** in line 'where' (if that is not the current line). | ||
128 | */ | ||
115 | static void check_match (LexState *ls, int what, int who, int where) { | 129 | static void check_match (LexState *ls, int what, int who, int where) { |
116 | if (unlikely(!testnext(ls, what))) { | 130 | if (unlikely(!testnext(ls, what))) { |
117 | if (where == ls->linenumber) | 131 | if (where == ls->linenumber) /* all in the same line? */ |
118 | error_expected(ls, what); | 132 | error_expected(ls, what); /* do not need a complex message */ |
119 | else { | 133 | else { |
120 | luaX_syntaxerror(ls, luaO_pushfstring(ls->L, | 134 | luaX_syntaxerror(ls, luaO_pushfstring(ls->L, |
121 | "%s expected (to close %s at line %d)", | 135 | "%s expected (to close %s at line %d)", |
@@ -146,11 +160,15 @@ static void codestring (LexState *ls, expdesc *e, TString *s) { | |||
146 | } | 160 | } |
147 | 161 | ||
148 | 162 | ||
149 | static void checkname (LexState *ls, expdesc *e) { | 163 | static void codename (LexState *ls, expdesc *e) { |
150 | codestring(ls, e, str_checkname(ls)); | 164 | codestring(ls, e, str_checkname(ls)); |
151 | } | 165 | } |
152 | 166 | ||
153 | 167 | ||
168 | /* | ||
169 | ** Register a new local variable in the active 'Proto' (for debug | ||
170 | ** information). | ||
171 | */ | ||
154 | static int registerlocalvar (LexState *ls, TString *varname) { | 172 | static int registerlocalvar (LexState *ls, TString *varname) { |
155 | FuncState *fs = ls->fs; | 173 | FuncState *fs = ls->fs; |
156 | Proto *f = fs->f; | 174 | Proto *f = fs->f; |
@@ -183,6 +201,9 @@ static void new_localvar (LexState *ls, TString *name) { | |||
183 | new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1)); | 201 | new_localvar(ls, luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1)); |
184 | 202 | ||
185 | 203 | ||
204 | /* | ||
205 | ** Get the debug-information entry for current variable 'i'. | ||
206 | */ | ||
186 | static LocVar *getlocvar (FuncState *fs, int i) { | 207 | static LocVar *getlocvar (FuncState *fs, int i) { |
187 | int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; | 208 | int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; |
188 | lua_assert(idx < fs->nlocvars); | 209 | lua_assert(idx < fs->nlocvars); |
@@ -192,6 +213,7 @@ static LocVar *getlocvar (FuncState *fs, int i) { | |||
192 | 213 | ||
193 | /* | 214 | /* |
194 | ** Start the scope for the last 'nvars' created variables. | 215 | ** Start the scope for the last 'nvars' created variables. |
216 | ** (debug info.) | ||
195 | */ | 217 | */ |
196 | static void adjustlocalvars (LexState *ls, int nvars) { | 218 | static void adjustlocalvars (LexState *ls, int nvars) { |
197 | FuncState *fs = ls->fs; | 219 | FuncState *fs = ls->fs; |
@@ -202,6 +224,10 @@ static void adjustlocalvars (LexState *ls, int nvars) { | |||
202 | } | 224 | } |
203 | 225 | ||
204 | 226 | ||
227 | /* | ||
228 | ** Close the scope for all variables up to level 'tolevel'. | ||
229 | ** (debug info.) | ||
230 | */ | ||
205 | static void removevars (FuncState *fs, int tolevel) { | 231 | static void removevars (FuncState *fs, int tolevel) { |
206 | fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); | 232 | fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); |
207 | while (fs->nactvar > tolevel) | 233 | while (fs->nactvar > tolevel) |
@@ -209,6 +235,10 @@ static void removevars (FuncState *fs, int tolevel) { | |||
209 | } | 235 | } |
210 | 236 | ||
211 | 237 | ||
238 | /* | ||
239 | ** Search the upvalues of the function 'fs' for one | ||
240 | ** with the given 'name'. | ||
241 | */ | ||
212 | static int searchupvalue (FuncState *fs, TString *name) { | 242 | static int searchupvalue (FuncState *fs, TString *name) { |
213 | int i; | 243 | int i; |
214 | Upvaldesc *up = fs->f->upvalues; | 244 | Upvaldesc *up = fs->f->upvalues; |
@@ -235,6 +265,10 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { | |||
235 | } | 265 | } |
236 | 266 | ||
237 | 267 | ||
268 | /* | ||
269 | ** Look for an active local variable with the name 'n' in the | ||
270 | ** function 'fs'. | ||
271 | */ | ||
238 | static int searchvar (FuncState *fs, TString *n) { | 272 | static int searchvar (FuncState *fs, TString *n) { |
239 | int i; | 273 | int i; |
240 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { | 274 | for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { |
@@ -246,8 +280,8 @@ static int searchvar (FuncState *fs, TString *n) { | |||
246 | 280 | ||
247 | 281 | ||
248 | /* | 282 | /* |
249 | Mark block where variable at given level was defined | 283 | ** Mark block where variable at given level was defined |
250 | (to emit close instructions later). | 284 | ** (to emit close instructions later). |
251 | */ | 285 | */ |
252 | static void markupval (FuncState *fs, int level) { | 286 | static void markupval (FuncState *fs, int level) { |
253 | BlockCnt *bl = fs->bl; | 287 | BlockCnt *bl = fs->bl; |
@@ -259,8 +293,9 @@ static void markupval (FuncState *fs, int level) { | |||
259 | 293 | ||
260 | 294 | ||
261 | /* | 295 | /* |
262 | Find variable with given name 'n'. If it is an upvalue, add this | 296 | ** Find a variable with the given name 'n'. If it is an upvalue, add |
263 | upvalue into all intermediate functions. | 297 | ** this upvalue into all intermediate functions. If it is a global, set |
298 | ** 'var' as 'void' as a flag. | ||
264 | */ | 299 | */ |
265 | static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | 300 | static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { |
266 | if (fs == NULL) /* no more levels? */ | 301 | if (fs == NULL) /* no more levels? */ |
@@ -287,6 +322,10 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { | |||
287 | } | 322 | } |
288 | 323 | ||
289 | 324 | ||
325 | /* | ||
326 | ** Find a variable with the given name 'n', handling global variables | ||
327 | ** too. | ||
328 | */ | ||
290 | static void singlevar (LexState *ls, expdesc *var) { | 329 | static void singlevar (LexState *ls, expdesc *var) { |
291 | TString *varname = str_checkname(ls); | 330 | TString *varname = str_checkname(ls); |
292 | FuncState *fs = ls->fs; | 331 | FuncState *fs = ls->fs; |
@@ -301,25 +340,29 @@ static void singlevar (LexState *ls, expdesc *var) { | |||
301 | } | 340 | } |
302 | 341 | ||
303 | 342 | ||
343 | /* | ||
344 | ** Adjust the number of results from an expression list 'e' with 'nexps' | ||
345 | ** expressions to 'nvars' values. | ||
346 | */ | ||
304 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { | 347 | static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { |
305 | FuncState *fs = ls->fs; | 348 | FuncState *fs = ls->fs; |
306 | int extra = nvars - nexps; | 349 | int needed = nvars - nexps; /* extra values needed */ |
307 | if (hasmultret(e->k)) { | 350 | if (hasmultret(e->k)) { /* last expression has multiple returns? */ |
308 | extra++; /* includes call itself */ | 351 | int extra = needed + 1; /* discount last expression itself */ |
309 | if (extra < 0) extra = 0; | 352 | if (extra < 0) |
353 | extra = 0; | ||
310 | luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ | 354 | luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ |
311 | if (extra > 1) luaK_reserveregs(fs, extra-1); | ||
312 | } | 355 | } |
313 | else { | 356 | else { |
314 | if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ | 357 | if (e->k != VVOID) /* at least one expression? */ |
315 | if (extra > 0) { | 358 | luaK_exp2nextreg(fs, e); /* close last expression */ |
316 | int reg = fs->freereg; | 359 | if (needed > 0) /* missing values? */ |
317 | luaK_reserveregs(fs, extra); | 360 | luaK_nil(fs, fs->freereg, needed); /* complete with nils */ |
318 | luaK_nil(fs, reg, extra); | ||
319 | } | ||
320 | } | 361 | } |
321 | if (nexps > nvars) | 362 | if (needed > 0) |
322 | ls->fs->freereg -= nexps - nvars; /* remove extra values */ | 363 | luaK_reserveregs(fs, needed); /* registers for extra values */ |
364 | else /* adding 'needed' is actually a subtraction */ | ||
365 | fs->freereg += needed; /* remove extra values */ | ||
323 | } | 366 | } |
324 | 367 | ||
325 | 368 | ||
@@ -632,7 +675,7 @@ static void fieldsel (LexState *ls, expdesc *v) { | |||
632 | expdesc key; | 675 | expdesc key; |
633 | luaK_exp2anyregup(fs, v); | 676 | luaK_exp2anyregup(fs, v); |
634 | luaX_next(ls); /* skip the dot or colon */ | 677 | luaX_next(ls); /* skip the dot or colon */ |
635 | checkname(ls, &key); | 678 | codename(ls, &key); |
636 | luaK_indexed(fs, v, &key); | 679 | luaK_indexed(fs, v, &key); |
637 | } | 680 | } |
638 | 681 | ||
@@ -669,7 +712,7 @@ static void recfield (LexState *ls, struct ConsControl *cc) { | |||
669 | expdesc tab, key, val; | 712 | expdesc tab, key, val; |
670 | if (ls->t.token == TK_NAME) { | 713 | if (ls->t.token == TK_NAME) { |
671 | checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); | 714 | checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); |
672 | checkname(ls, &key); | 715 | codename(ls, &key); |
673 | } | 716 | } |
674 | else /* ls->t.token == '[' */ | 717 | else /* ls->t.token == '[' */ |
675 | yindex(ls, &key); | 718 | yindex(ls, &key); |
@@ -938,7 +981,7 @@ static void suffixedexp (LexState *ls, expdesc *v) { | |||
938 | case ':': { /* ':' NAME funcargs */ | 981 | case ':': { /* ':' NAME funcargs */ |
939 | expdesc key; | 982 | expdesc key; |
940 | luaX_next(ls); | 983 | luaX_next(ls); |
941 | checkname(ls, &key); | 984 | codename(ls, &key); |
942 | luaK_self(fs, v, &key); | 985 | luaK_self(fs, v, &key); |
943 | funcargs(ls, v, line); | 986 | funcargs(ls, v, line); |
944 | break; | 987 | break; |
@@ -1048,6 +1091,9 @@ static BinOpr getbinopr (int op) { | |||
1048 | } | 1091 | } |
1049 | 1092 | ||
1050 | 1093 | ||
1094 | /* | ||
1095 | ** Priority table for binary operators. | ||
1096 | */ | ||
1051 | static const struct { | 1097 | static const struct { |
1052 | lu_byte left; /* left priority for each binary operator */ | 1098 | lu_byte left; /* left priority for each binary operator */ |
1053 | lu_byte right; /* right priority */ | 1099 | lu_byte right; /* right priority */ |
@@ -1076,9 +1122,9 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { | |||
1076 | UnOpr uop; | 1122 | UnOpr uop; |
1077 | enterlevel(ls); | 1123 | enterlevel(ls); |
1078 | uop = getunopr(ls->t.token); | 1124 | uop = getunopr(ls->t.token); |
1079 | if (uop != OPR_NOUNOPR) { | 1125 | if (uop != OPR_NOUNOPR) { /* prefix (unary) operator? */ |
1080 | int line = ls->linenumber; | 1126 | int line = ls->linenumber; |
1081 | luaX_next(ls); | 1127 | luaX_next(ls); /* skip operator */ |
1082 | subexpr(ls, v, UNARY_PRIORITY); | 1128 | subexpr(ls, v, UNARY_PRIORITY); |
1083 | luaK_prefix(ls->fs, uop, v, line); | 1129 | luaK_prefix(ls->fs, uop, v, line); |
1084 | } | 1130 | } |
@@ -1089,7 +1135,7 @@ static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { | |||
1089 | expdesc v2; | 1135 | expdesc v2; |
1090 | BinOpr nextop; | 1136 | BinOpr nextop; |
1091 | int line = ls->linenumber; | 1137 | int line = ls->linenumber; |
1092 | luaX_next(ls); | 1138 | luaX_next(ls); /* skip operator */ |
1093 | luaK_infix(ls->fs, op, v); | 1139 | luaK_infix(ls->fs, op, v); |
1094 | /* read sub-expression with higher priority */ | 1140 | /* read sub-expression with higher priority */ |
1095 | nextop = subexpr(ls, &v2, priority[op].right); | 1141 | nextop = subexpr(ls, &v2, priority[op].right); |
@@ -1177,21 +1223,27 @@ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { | |||
1177 | } | 1223 | } |
1178 | } | 1224 | } |
1179 | 1225 | ||
1180 | 1226 | /* | |
1181 | static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { | 1227 | ** Parse and compile a mulitple assignment. The first "variable" |
1228 | ** (a 'suffixedexp') was already read by the caller. | ||
1229 | ** | ||
1230 | ** assignment -> suffixedexp restassign | ||
1231 | ** restassign -> ',' suffixedexp restassign | '=' explist | ||
1232 | */ | ||
1233 | static void restassign (LexState *ls, struct LHS_assign *lh, int nvars) { | ||
1182 | expdesc e; | 1234 | expdesc e; |
1183 | check_condition(ls, vkisvar(lh->v.k), "syntax error"); | 1235 | check_condition(ls, vkisvar(lh->v.k), "syntax error"); |
1184 | if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ | 1236 | if (testnext(ls, ',')) { /* restassign -> ',' suffixedexp restassign */ |
1185 | struct LHS_assign nv; | 1237 | struct LHS_assign nv; |
1186 | nv.prev = lh; | 1238 | nv.prev = lh; |
1187 | suffixedexp(ls, &nv.v); | 1239 | suffixedexp(ls, &nv.v); |
1188 | if (!vkisindexed(nv.v.k)) | 1240 | if (!vkisindexed(nv.v.k)) |
1189 | check_conflict(ls, lh, &nv.v); | 1241 | check_conflict(ls, lh, &nv.v); |
1190 | enterlevel(ls); /* control recursion depth */ | 1242 | enterlevel(ls); /* control recursion depth */ |
1191 | assignment(ls, &nv, nvars+1); | 1243 | restassign(ls, &nv, nvars+1); |
1192 | leavelevel(ls); | 1244 | leavelevel(ls); |
1193 | } | 1245 | } |
1194 | else { /* assignment -> '=' explist */ | 1246 | else { /* restassign -> '=' explist */ |
1195 | int nexps; | 1247 | int nexps; |
1196 | checknext(ls, '='); | 1248 | checknext(ls, '='); |
1197 | nexps = explist(ls, &e); | 1249 | nexps = explist(ls, &e); |
@@ -1627,7 +1679,7 @@ static void exprstat (LexState *ls) { | |||
1627 | suffixedexp(ls, &v.v); | 1679 | suffixedexp(ls, &v.v); |
1628 | if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ | 1680 | if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ |
1629 | v.prev = NULL; | 1681 | v.prev = NULL; |
1630 | assignment(ls, &v, 1); | 1682 | restassign(ls, &v, 1); |
1631 | } | 1683 | } |
1632 | else { /* stat -> func */ | 1684 | else { /* stat -> func */ |
1633 | Instruction *inst = &getinstruction(fs, &v.v); | 1685 | Instruction *inst = &getinstruction(fs, &v.v); |