| 2203 | } |
| 2204 | |
| 2205 | static size_t preprocessclass (LexState *ls) { |
| 2206 | int allowed_ends = 0; |
| 2207 | bool expect_block_opener = false; |
| 2208 | const auto start = luaX_getpos(ls); |
| 2209 | |
| 2210 | while (ls->t.token != TK_EOS) { |
| 2211 | if (ls->t.token == TK_END && allowed_ends-- <= 0) { |
| 2212 | // printf("Preprocessed class body ending at line %d.\n", ls->getLineNumber()); |
| 2213 | break; |
| 2214 | } |
| 2215 | |
| 2216 | // This is only checking *inside* our current class body, the parser has already skipped the class declaration. |
| 2217 | switch (ls->t.normalizedToken()) { |
| 2218 | case TK_IF: |
| 2219 | case TK_ENUM: |
| 2220 | case TK_CLASS: /* class or enum class */ |
| 2221 | case TK_FUNCTION: |
| 2222 | /* ensure this keyword isn't being used in a goto label, call, type hint, or table key assignment (issue #1410) */ |
| 2223 | if (luaX_lookahead(ls) != '=' |
| 2224 | && luaX_lookbehind(ls).token != ':' |
| 2225 | && luaX_lookbehind(ls).token != '.' |
| 2226 | && luaX_lookbehind(ls).token != TK_GOTO |
| 2227 | && (luaX_lookbehind(ls).token != TK_DBCOLON || luaX_lookahead(ls) != TK_DBCOLON) /* allow keyword immediately after goto label */ |
| 2228 | ) { |
| 2229 | expect_block_opener = ls->t.token != TK_FUNCTION; |
| 2230 | if (ls->t.token != TK_ENUM || luaX_lookahead(ls) != TK_CLASS) { /* 'enum class' would already be counted */ |
| 2231 | ++allowed_ends; |
| 2232 | } |
| 2233 | } |
| 2234 | break; |
| 2235 | |
| 2236 | case TK_THEN: |
| 2237 | case TK_BEGIN: |
| 2238 | expect_block_opener = false; |
| 2239 | break; |
| 2240 | |
| 2241 | case TK_DO: |
| 2242 | if (expect_block_opener) |
| 2243 | expect_block_opener = false; |
| 2244 | else |
| 2245 | ++allowed_ends; /* forstat, whilestat, switchstat, dostat, '-> do' */ |
| 2246 | break; |
| 2247 | } |
| 2248 | |
| 2249 | if (ls->t.token == TK_NAME && strcmp(getstr(ls->t.seminfo.ts), "protected") == 0) { |
| 2250 | if (luaX_lookahead(ls) == TK_FUNCTION) { |
| 2251 | checknext(ls, TK_NAME); |
| 2252 | checknext(ls, TK_FUNCTION); |
| 2253 | ls->classes.top().addProtectedField(getstr(ls->t.seminfo.ts)); |
| 2254 | ++allowed_ends; // For TK_FUNCTION |
| 2255 | } |
| 2256 | else if (luaX_lookahead(ls) == TK_NAME) { |
| 2257 | checknext(ls, TK_NAME); |
| 2258 | ls->classes.top().addProtectedField(getstr(ls->t.seminfo.ts)); |
| 2259 | } |
| 2260 | } |
| 2261 | else if (ls->t.token == TK_NAME && strcmp(getstr(ls->t.seminfo.ts), "private") == 0) { |
| 2262 | if (luaX_lookahead(ls) == TK_FUNCTION) { |
no test coverage detected