Branch data Line data Source code
1 : : /*
2 : : * This file is part of the MicroPython project, http://micropython.org/
3 : : *
4 : : * The MIT License (MIT)
5 : : *
6 : : * Copyright (c) 2013, 2014 Damien P. George
7 : : *
8 : : * Permission is hereby granted, free of charge, to any person obtaining a copy
9 : : * of this software and associated documentation files (the "Software"), to deal
10 : : * in the Software without restriction, including without limitation the rights
11 : : * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 : : * copies of the Software, and to permit persons to whom the Software is
13 : : * furnished to do so, subject to the following conditions:
14 : : *
15 : : * The above copyright notice and this permission notice shall be included in
16 : : * all copies or substantial portions of the Software.
17 : : *
18 : : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 : : * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 : : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 : : * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 : : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 : : * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 : : * THE SOFTWARE.
25 : : */
26 : :
27 : : #include <stdio.h>
28 : : #include <string.h>
29 : : #include <assert.h>
30 : :
31 : : #include "py/reader.h"
32 : : #include "py/lexer.h"
33 : : #include "py/runtime.h"
34 : :
35 : : #if MICROPY_ENABLE_COMPILER
36 : :
37 : : #define TAB_SIZE (8)
38 : :
39 : : // TODO seems that CPython allows NULL byte in the input stream
40 : : // don't know if that's intentional or not, but we don't allow it
41 : :
42 : : #define MP_LEXER_EOF ((unichar)MP_READER_EOF)
43 : : #define CUR_CHAR(lex) ((lex)->chr0)
44 : :
45 : 2832628 : STATIC bool is_end(mp_lexer_t *lex) {
46 : 2832628 : return lex->chr0 == MP_LEXER_EOF;
47 : : }
48 : :
49 : 1458092 : STATIC bool is_physical_newline(mp_lexer_t *lex) {
50 : 1458092 : return lex->chr0 == '\n';
51 : : }
52 : :
53 : 3533560 : STATIC bool is_char(mp_lexer_t *lex, byte c) {
54 : 3533560 : return lex->chr0 == c;
55 : : }
56 : :
57 : 495685 : STATIC bool is_char_or(mp_lexer_t *lex, byte c1, byte c2) {
58 [ + + + + ]: 495685 : return lex->chr0 == c1 || lex->chr0 == c2;
59 : : }
60 : :
61 : 46382 : STATIC bool is_char_or3(mp_lexer_t *lex, byte c1, byte c2, byte c3) {
62 [ + + + + : 46382 : return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3;
+ - ]
63 : : }
64 : :
65 : : #if MICROPY_PY_FSTRINGS
66 : 413883 : STATIC bool is_char_or4(mp_lexer_t *lex, byte c1, byte c2, byte c3, byte c4) {
67 [ + + + + : 413883 : return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3 || lex->chr0 == c4;
+ + + + ]
68 : : }
69 : : #endif
70 : :
71 : 2273 : STATIC bool is_char_following(mp_lexer_t *lex, byte c) {
72 : 2273 : return lex->chr1 == c;
73 : : }
74 : :
75 : 26550 : STATIC bool is_char_following_or(mp_lexer_t *lex, byte c1, byte c2) {
76 [ + + + + ]: 26550 : return lex->chr1 == c1 || lex->chr1 == c2;
77 : : }
78 : :
79 : 1106 : STATIC bool is_char_following_following_or(mp_lexer_t *lex, byte c1, byte c2) {
80 [ + + + + ]: 1106 : return lex->chr2 == c1 || lex->chr2 == c2;
81 : : }
82 : :
83 : 2214826 : STATIC bool is_char_and(mp_lexer_t *lex, byte c1, byte c2) {
84 [ + + + + ]: 2214826 : return lex->chr0 == c1 && lex->chr1 == c2;
85 : : }
86 : :
87 : 915273 : STATIC bool is_whitespace(mp_lexer_t *lex) {
88 : 915273 : return unichar_isspace(lex->chr0);
89 : : }
90 : :
91 : 1194595 : STATIC bool is_letter(mp_lexer_t *lex) {
92 : 1194595 : return unichar_isalpha(lex->chr0);
93 : : }
94 : :
95 : 469899 : STATIC bool is_digit(mp_lexer_t *lex) {
96 : 469899 : return unichar_isdigit(lex->chr0);
97 : : }
98 : :
99 : 16671 : STATIC bool is_following_digit(mp_lexer_t *lex) {
100 : 16671 : return unichar_isdigit(lex->chr1);
101 : : }
102 : :
103 : 5097 : STATIC bool is_following_base_char(mp_lexer_t *lex) {
104 : 5097 : const unichar chr1 = lex->chr1 | 0x20;
105 [ + + + + ]: 5097 : return chr1 == 'b' || chr1 == 'o' || chr1 == 'x';
106 : : }
107 : :
108 : 112 : STATIC bool is_following_odigit(mp_lexer_t *lex) {
109 : 112 : return lex->chr1 >= '0' && lex->chr1 <= '7';
110 : : }
111 : :
112 : 428917 : STATIC bool is_string_or_bytes(mp_lexer_t *lex) {
113 : 428917 : return is_char_or(lex, '\'', '\"')
114 : : #if MICROPY_PY_FSTRINGS
115 [ + + + + ]: 413883 : || (is_char_or4(lex, 'r', 'u', 'b', 'f') && is_char_following_or(lex, '\'', '\"'))
116 [ + + + + ]: 411722 : || (((is_char_and(lex, 'r', 'f') || is_char_and(lex, 'f', 'r'))
117 [ + - ]: 897 : && is_char_following_following_or(lex, '\'', '\"')))
118 : : #else
119 : : || (is_char_or3(lex, 'r', 'u', 'b') && is_char_following_or(lex, '\'', '\"'))
120 : : #endif
121 [ + + + + : 840639 : || ((is_char_and(lex, 'r', 'b') || is_char_and(lex, 'b', 'r'))
+ + ]
122 [ + + ]: 209 : && is_char_following_following_or(lex, '\'', '\"'));
123 : : }
124 : :
125 : : // to easily parse utf-8 identifiers we allow any raw byte with high bit set
126 : 1120932 : STATIC bool is_head_of_identifier(mp_lexer_t *lex) {
127 [ + + + + : 1120932 : return is_letter(lex) || lex->chr0 == '_' || lex->chr0 >= 0x80;
+ + ]
128 : : }
129 : :
130 : 726222 : STATIC bool is_tail_of_identifier(mp_lexer_t *lex) {
131 [ + + + + ]: 726222 : return is_head_of_identifier(lex) || is_digit(lex);
132 : : }
133 : :
134 : 2099252 : STATIC void next_char(mp_lexer_t *lex) {
135 [ + + ]: 2099252 : if (lex->chr0 == '\n') {
136 : : // a new line
137 : 93744 : ++lex->line;
138 : 93744 : lex->column = 1;
139 [ + + ]: 2005508 : } else if (lex->chr0 == '\t') {
140 : : // a tab
141 : 4 : lex->column = (((lex->column - 1 + TAB_SIZE) / TAB_SIZE) * TAB_SIZE) + 1;
142 : : } else {
143 : : // a character worth one column
144 : 2005504 : ++lex->column;
145 : : }
146 : :
147 : : // shift the input queue forward
148 : 2099252 : lex->chr0 = lex->chr1;
149 : 2099252 : lex->chr1 = lex->chr2;
150 : :
151 : : // and add the next byte from either the fstring args or the reader
152 : : #if MICROPY_PY_FSTRINGS
153 [ + + ]: 2099252 : if (lex->fstring_args_idx) {
154 : : // if there are saved chars, then we're currently injecting fstring args
155 [ + + ]: 1205 : if (lex->fstring_args_idx < lex->fstring_args.len) {
156 : 986 : lex->chr2 = lex->fstring_args.buf[lex->fstring_args_idx++];
157 : : } else {
158 : : // no more fstring arg bytes
159 : 219 : lex->chr2 = '\0';
160 : : }
161 : :
162 [ + + ]: 1205 : if (lex->chr0 == '\0') {
163 : : // consumed all fstring data, restore saved input queue
164 : 73 : lex->chr0 = lex->chr0_saved;
165 : 73 : lex->chr1 = lex->chr1_saved;
166 : 73 : lex->chr2 = lex->chr2_saved;
167 : : // stop consuming fstring arg data
168 : 73 : vstr_reset(&lex->fstring_args);
169 : 73 : lex->fstring_args_idx = 0;
170 : : }
171 : : } else
172 : : #endif
173 : : {
174 : 2098047 : lex->chr2 = lex->reader.readbyte(lex->reader.data);
175 : : }
176 : :
177 [ + + ]: 2099259 : if (lex->chr1 == '\r') {
178 : : // CR is a new line, converted to LF
179 : 76 : lex->chr1 = '\n';
180 [ + + ]: 76 : if (lex->chr2 == '\n') {
181 : : // CR LF is a single new line, throw out the extra LF
182 : 28 : lex->chr2 = lex->reader.readbyte(lex->reader.data);
183 : : }
184 : : }
185 : :
186 : : // check if we need to insert a newline at end of file
187 [ + + + + : 2099259 : if (lex->chr2 == MP_LEXER_EOF && lex->chr1 != MP_LEXER_EOF && lex->chr1 != '\n') {
+ + ]
188 : 1505 : lex->chr2 = '\n';
189 : : }
190 : 2099259 : }
191 : :
192 : 21804 : STATIC void indent_push(mp_lexer_t *lex, size_t indent) {
193 [ + + ]: 21804 : if (lex->num_indent_level >= lex->alloc_indent_level) {
194 : 8 : lex->indent_level = m_renew(uint16_t, lex->indent_level, lex->alloc_indent_level, lex->alloc_indent_level + MICROPY_ALLOC_LEXEL_INDENT_INC);
195 : 8 : lex->alloc_indent_level += MICROPY_ALLOC_LEXEL_INDENT_INC;
196 : : }
197 : 21804 : lex->indent_level[lex->num_indent_level++] = indent;
198 : 21804 : }
199 : :
200 : 105700 : STATIC size_t indent_top(mp_lexer_t *lex) {
201 : 105700 : return lex->indent_level[lex->num_indent_level - 1];
202 : : }
203 : :
204 : 21804 : STATIC void indent_pop(mp_lexer_t *lex) {
205 : 21804 : lex->num_indent_level -= 1;
206 : 21804 : }
207 : :
208 : : // some tricky operator encoding:
209 : : // <op> = begin with <op>, if this opchar matches then begin here
210 : : // e<op> = end with <op>, if this opchar matches then end
211 : : // c<op> = continue with <op>, if this opchar matches then continue matching
212 : : // this means if the start of two ops are the same then they are equal til the last char
213 : :
214 : : STATIC const char *const tok_enc =
215 : : "()[]{},;~" // singles
216 : : ":e=" // : :=
217 : : "<e=c<e=" // < <= << <<=
218 : : ">e=c>e=" // > >= >> >>=
219 : : "*e=c*e=" // * *= ** **=
220 : : "+e=" // + +=
221 : : "-e=e>" // - -= ->
222 : : "&e=" // & &=
223 : : "|e=" // | |=
224 : : "/e=c/e=" // / /= // //=
225 : : "%e=" // % %=
226 : : "^e=" // ^ ^=
227 : : "@e=" // @ @=
228 : : "=e=" // = ==
229 : : "!."; // start of special cases: != . ...
230 : :
231 : : // TODO static assert that number of tokens is less than 256 so we can safely make this table with byte sized entries
232 : : STATIC const uint8_t tok_enc_kind[] = {
233 : : MP_TOKEN_DEL_PAREN_OPEN, MP_TOKEN_DEL_PAREN_CLOSE,
234 : : MP_TOKEN_DEL_BRACKET_OPEN, MP_TOKEN_DEL_BRACKET_CLOSE,
235 : : MP_TOKEN_DEL_BRACE_OPEN, MP_TOKEN_DEL_BRACE_CLOSE,
236 : : MP_TOKEN_DEL_COMMA, MP_TOKEN_DEL_SEMICOLON, MP_TOKEN_OP_TILDE,
237 : :
238 : : MP_TOKEN_DEL_COLON, MP_TOKEN_OP_ASSIGN,
239 : : MP_TOKEN_OP_LESS, MP_TOKEN_OP_LESS_EQUAL, MP_TOKEN_OP_DBL_LESS, MP_TOKEN_DEL_DBL_LESS_EQUAL,
240 : : MP_TOKEN_OP_MORE, MP_TOKEN_OP_MORE_EQUAL, MP_TOKEN_OP_DBL_MORE, MP_TOKEN_DEL_DBL_MORE_EQUAL,
241 : : MP_TOKEN_OP_STAR, MP_TOKEN_DEL_STAR_EQUAL, MP_TOKEN_OP_DBL_STAR, MP_TOKEN_DEL_DBL_STAR_EQUAL,
242 : : MP_TOKEN_OP_PLUS, MP_TOKEN_DEL_PLUS_EQUAL,
243 : : MP_TOKEN_OP_MINUS, MP_TOKEN_DEL_MINUS_EQUAL, MP_TOKEN_DEL_MINUS_MORE,
244 : : MP_TOKEN_OP_AMPERSAND, MP_TOKEN_DEL_AMPERSAND_EQUAL,
245 : : MP_TOKEN_OP_PIPE, MP_TOKEN_DEL_PIPE_EQUAL,
246 : : MP_TOKEN_OP_SLASH, MP_TOKEN_DEL_SLASH_EQUAL, MP_TOKEN_OP_DBL_SLASH, MP_TOKEN_DEL_DBL_SLASH_EQUAL,
247 : : MP_TOKEN_OP_PERCENT, MP_TOKEN_DEL_PERCENT_EQUAL,
248 : : MP_TOKEN_OP_CARET, MP_TOKEN_DEL_CARET_EQUAL,
249 : : MP_TOKEN_OP_AT, MP_TOKEN_DEL_AT_EQUAL,
250 : : MP_TOKEN_DEL_EQUAL, MP_TOKEN_OP_DBL_EQUAL,
251 : : };
252 : :
253 : : // must have the same order as enum in lexer.h
254 : : // must be sorted according to strcmp
255 : : STATIC const char *const tok_kw[] = {
256 : : "False",
257 : : "None",
258 : : "True",
259 : : "__debug__",
260 : : "and",
261 : : "as",
262 : : "assert",
263 : : #if MICROPY_PY_ASYNC_AWAIT
264 : : "async",
265 : : "await",
266 : : #endif
267 : : "break",
268 : : "class",
269 : : "continue",
270 : : "def",
271 : : "del",
272 : : "elif",
273 : : "else",
274 : : "except",
275 : : "finally",
276 : : "for",
277 : : "from",
278 : : "global",
279 : : "if",
280 : : "import",
281 : : "in",
282 : : "is",
283 : : "lambda",
284 : : "nonlocal",
285 : : "not",
286 : : "or",
287 : : "pass",
288 : : "raise",
289 : : "return",
290 : : "try",
291 : : "while",
292 : : "with",
293 : : "yield",
294 : : };
295 : :
296 : : // This is called with CUR_CHAR() before first hex digit, and should return with
297 : : // it pointing to last hex digit
298 : : // num_digits must be greater than zero
299 : 2578 : STATIC bool get_hex(mp_lexer_t *lex, size_t num_digits, mp_uint_t *result) {
300 : 2578 : mp_uint_t num = 0;
301 [ + + ]: 7810 : while (num_digits-- != 0) {
302 : 5248 : next_char(lex);
303 : 5248 : unichar c = CUR_CHAR(lex);
304 [ + + ]: 5248 : if (!unichar_isxdigit(c)) {
305 : : return false;
306 : : }
307 : 5232 : num = (num << 4) + unichar_xdigit_value(c);
308 : : }
309 : 2562 : *result = num;
310 : 2562 : return true;
311 : : }
312 : :
313 : 17199 : STATIC void parse_string_literal(mp_lexer_t *lex, bool is_raw, bool is_fstring) {
314 : : // get first quoting character
315 : 17199 : char quote_char = '\'';
316 [ + + ]: 17199 : if (is_char(lex, '\"')) {
317 : 13571 : quote_char = '\"';
318 : : }
319 : 17199 : next_char(lex);
320 : :
321 : : // work out if it's a single or triple quoted literal
322 : 17199 : size_t num_quotes;
323 [ + + ]: 17199 : if (is_char_and(lex, quote_char, quote_char)) {
324 : : // triple quotes
325 : 24 : next_char(lex);
326 : 24 : next_char(lex);
327 : 24 : num_quotes = 3;
328 : : } else {
329 : : // single quotes
330 : : num_quotes = 1;
331 : : }
332 : :
333 : 17199 : size_t n_closing = 0;
334 : : #if MICROPY_PY_FSTRINGS
335 [ + + ]: 17199 : if (is_fstring) {
336 : : // assume there's going to be interpolation, so prep the injection data
337 : : // fstring_args_idx==0 && len(fstring_args)>0 means we're extracting the args.
338 : : // only when fstring_args_idx>0 will we consume the arg data
339 : : // note: lex->fstring_args will be empty already (it's reset when finished)
340 : 77 : vstr_add_str(&lex->fstring_args, ".format(");
341 : : }
342 : : #endif
343 : :
344 [ + - + + : 150676 : while (!is_end(lex) && (num_quotes > 1 || !is_char(lex, '\n')) && n_closing < num_quotes) {
+ + + + ]
345 [ + + ]: 133479 : if (is_char(lex, quote_char)) {
346 : 17225 : n_closing += 1;
347 : 17225 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
348 : : } else {
349 : 116337 : n_closing = 0;
350 : :
351 : : #if MICROPY_PY_FSTRINGS
352 [ + + + + ]: 116337 : while (is_fstring && is_char(lex, '{')) {
353 : 83 : next_char(lex);
354 [ + + ]: 83 : if (is_char(lex, '{')) {
355 : : // "{{" is passed through unchanged to be handled by str.format
356 : 8 : vstr_add_byte(&lex->vstr, '{');
357 : 8 : next_char(lex);
358 : : } else {
359 : : // wrap each argument in (), e.g.
360 : : // f"{a,b,}, {c}" --> "{}".format((a,b), (c),)
361 : 75 : vstr_add_byte(&lex->fstring_args, '(');
362 : : // remember the start of this argument (if we need it for f'{a=}').
363 : 75 : size_t i = lex->fstring_args.len;
364 : : // extract characters inside the { until we reach the
365 : : // format specifier or closing }.
366 : : // (MicroPython limitation) note: this is completely unaware of
367 : : // Python syntax and will not handle any expression containing '}' or ':'.
368 : : // e.g. f'{"}"}' or f'{foo({})}'.
369 : 75 : unsigned int nested_bracket_level = 0;
370 [ + - + + : 392 : while (!is_end(lex) && (nested_bracket_level != 0 || !is_char_or(lex, ':', '}'))) {
+ + ]
371 : 317 : unichar c = CUR_CHAR(lex);
372 [ + + ]: 317 : if (c == '[' || c == '{') {
373 : 12 : nested_bracket_level += 1;
374 [ + + ]: 305 : } else if (c == ']' || c == '}') {
375 : 12 : nested_bracket_level -= 1;
376 : : }
377 : : // like the default case at the end of this function, stay 8-bit clean
378 : 317 : vstr_add_byte(&lex->fstring_args, c);
379 : 317 : next_char(lex);
380 : : }
381 [ + + ]: 75 : if (lex->fstring_args.buf[lex->fstring_args.len - 1] == '=') {
382 : : // if the last character of the arg was '=', then inject "arg=" before the '{'.
383 : : // f'{a=}' --> 'a={}'.format(a)
384 : 18 : vstr_add_strn(&lex->vstr, lex->fstring_args.buf + i, lex->fstring_args.len - i);
385 : : // remove the trailing '='
386 : 18 : lex->fstring_args.len--;
387 : : }
388 : : // close the paren-wrapped arg to .format().
389 : 75 : vstr_add_byte(&lex->fstring_args, ')');
390 : : // comma-separate args to .format().
391 : 75 : vstr_add_byte(&lex->fstring_args, ',');
392 : : }
393 : 83 : vstr_add_byte(&lex->vstr, '{');
394 : : }
395 : : #endif
396 : :
397 [ + + ]: 116254 : if (is_char(lex, '\\')) {
398 : 3416 : next_char(lex);
399 : 3416 : unichar c = CUR_CHAR(lex);
400 [ + + ]: 3416 : if (is_raw) {
401 : : // raw strings allow escaping of quotes, but the backslash is also emitted
402 : 80 : vstr_add_char(&lex->vstr, '\\');
403 : : } else {
404 [ + + + + : 3336 : switch (c) {
+ + + + +
+ + + + ]
405 : : // note: "c" can never be MP_LEXER_EOF because next_char
406 : : // always inserts a newline at the end of the input stream
407 : : case '\n':
408 : : c = MP_LEXER_EOF;
409 : : break; // backslash escape the newline, just ignore it
410 : : case '\\':
411 : : break;
412 : : case '\'':
413 : : break;
414 : : case '"':
415 : : break;
416 : : case 'a':
417 : : c = 0x07;
418 : : break;
419 : : case 'b':
420 : : c = 0x08;
421 : : break;
422 : : case 't':
423 : : c = 0x09;
424 : : break;
425 : : case 'n':
426 : : c = 0x0a;
427 : : break;
428 : : case 'v':
429 : : c = 0x0b;
430 : : break;
431 : : case 'f':
432 : : c = 0x0c;
433 : : break;
434 : : case 'r':
435 : : c = 0x0d;
436 : : break;
437 : 28 : case 'u':
438 : : case 'U':
439 [ + + ]: 28 : if (lex->tok_kind == MP_TOKEN_BYTES) {
440 : : // b'\u1234' == b'\\u1234'
441 : 2 : vstr_add_char(&lex->vstr, '\\');
442 : 2 : break;
443 : : }
444 : : // Otherwise fall through.
445 : 2578 : MP_FALLTHROUGH
446 : : case 'x': {
447 : 2578 : mp_uint_t num = 0;
448 [ + - + + : 2588 : if (!get_hex(lex, (c == 'x' ? 2 : c == 'u' ? 4 : 8), &num)) {
+ + ]
449 : : // not enough hex chars for escape sequence
450 : 16 : lex->tok_kind = MP_TOKEN_INVALID;
451 : : }
452 : 2578 : c = num;
453 : 2578 : break;
454 : : }
455 : : case 'N':
456 : : // Supporting '\N{LATIN SMALL LETTER A}' == 'a' would require keeping the
457 : : // entire Unicode name table in the core. As of Unicode 6.3.0, that's nearly
458 : : // 3MB of text; even gzip-compressed and with minimal structure, it'll take
459 : : // roughly half a meg of storage. This form of Unicode escape may be added
460 : : // later on, but it's definitely not a priority right now. -- CJA 20140607
461 : 2 : mp_raise_NotImplementedError(MP_ERROR_TEXT("unicode name escapes"));
462 : 134 : break;
463 : 134 : default:
464 [ + + ]: 134 : if (c >= '0' && c <= '7') {
465 : : // Octal sequence, 1-3 chars
466 : 104 : size_t digits = 3;
467 : 104 : mp_uint_t num = c - '0';
468 [ + + + + ]: 112 : while (is_following_odigit(lex) && --digits != 0) {
469 : 8 : next_char(lex);
470 : 8 : num = num * 8 + (CUR_CHAR(lex) - '0');
471 : : }
472 : 104 : c = num;
473 : : } else {
474 : : // unrecognised escape character; CPython lets this through verbatim as '\' and then the character
475 : 30 : vstr_add_char(&lex->vstr, '\\');
476 : : }
477 : : break;
478 : : }
479 : : }
480 [ + - ]: 2794 : if (c != MP_LEXER_EOF) {
481 : : #if MICROPY_PY_BUILTINS_STR_UNICODE
482 [ + + + + ]: 3412 : if (c < 0x110000 && lex->tok_kind == MP_TOKEN_STRING) {
483 : : // Valid unicode character in a str object.
484 : 718 : vstr_add_char(&lex->vstr, c);
485 [ + - + + ]: 2692 : } else if (c < 0x100 && lex->tok_kind == MP_TOKEN_BYTES) {
486 : : // Valid byte in a bytes object.
487 : 2676 : vstr_add_byte(&lex->vstr, c);
488 : : }
489 : : #else
490 : : if (c < 0x100) {
491 : : // Without unicode everything is just added as an 8-bit byte.
492 : : vstr_add_byte(&lex->vstr, c);
493 : : }
494 : : #endif
495 : : else {
496 : : // Character out of range; this raises a generic SyntaxError.
497 : 18 : lex->tok_kind = MP_TOKEN_INVALID;
498 : : }
499 : : }
500 : : } else {
501 : : // Add the "character" as a byte so that we remain 8-bit clean.
502 : : // This way, strings are parsed correctly whether or not they contain utf-8 chars.
503 : 112838 : vstr_add_byte(&lex->vstr, CUR_CHAR(lex));
504 : : }
505 : : }
506 : 133477 : next_char(lex);
507 : : }
508 : :
509 : : // check we got the required end quotes
510 [ + + ]: 17197 : if (n_closing < num_quotes) {
511 : 20 : lex->tok_kind = MP_TOKEN_LONELY_STRING_OPEN;
512 : : }
513 : :
514 : : // cut off the end quotes from the token text
515 : 17197 : vstr_cut_tail_bytes(&lex->vstr, n_closing);
516 : 17197 : }
517 : :
518 : 542726 : STATIC bool skip_whitespace(mp_lexer_t *lex, bool stop_at_newline) {
519 : 542726 : bool had_physical_newline = false;
520 [ + + ]: 1017538 : while (!is_end(lex)) {
521 [ + + ]: 1009388 : if (is_physical_newline(lex)) {
522 [ + + + + ]: 94116 : if (stop_at_newline && lex->nested_bracket_level == 0) {
523 : : break;
524 : : }
525 : 93636 : had_physical_newline = true;
526 : 93636 : next_char(lex);
527 [ + + ]: 915272 : } else if (is_whitespace(lex)) {
528 : 370551 : next_char(lex);
529 [ + + ]: 544722 : } else if (is_char(lex, '#')) {
530 : 10585 : next_char(lex);
531 [ + - + + ]: 448704 : while (!is_end(lex) && !is_physical_newline(lex)) {
532 : 438119 : next_char(lex);
533 : : }
534 : : // had_physical_newline will be set on next loop
535 [ + + ]: 534137 : } else if (is_char_and(lex, '\\', '\n')) {
536 : : // line-continuation, so don't set had_physical_newline
537 : 40 : next_char(lex);
538 : 40 : next_char(lex);
539 : : } else {
540 : : break;
541 : : }
542 : : }
543 : 542727 : return had_physical_newline;
544 : : }
545 : :
546 : 525527 : void mp_lexer_to_next(mp_lexer_t *lex) {
547 : : #if MICROPY_PY_FSTRINGS
548 [ + + + + ]: 525527 : if (lex->fstring_args.len && lex->fstring_args_idx == 0) {
549 : : // moving onto the next token means the literal string is complete.
550 : : // switch into injecting the format args.
551 : 77 : vstr_add_byte(&lex->fstring_args, ')');
552 : 77 : lex->chr0_saved = lex->chr0;
553 : 77 : lex->chr1_saved = lex->chr1;
554 : 77 : lex->chr2_saved = lex->chr2;
555 : 77 : lex->chr0 = lex->fstring_args.buf[0];
556 : 77 : lex->chr1 = lex->fstring_args.buf[1];
557 : 77 : lex->chr2 = lex->fstring_args.buf[2];
558 : : // we've already extracted 3 chars, but setting this non-zero also
559 : : // means we'll start consuming the fstring data
560 : 77 : lex->fstring_args_idx = 3;
561 : : }
562 : : #endif
563 : :
564 : : // start new token text
565 : 525527 : vstr_reset(&lex->vstr);
566 : :
567 : : // skip white space and comments
568 : 525527 : bool had_physical_newline = skip_whitespace(lex, false);
569 : :
570 : : // set token source information
571 : 525531 : lex->tok_line = lex->line;
572 : 525531 : lex->tok_column = lex->column;
573 : :
574 [ + + ]: 525531 : if (lex->emit_dent < 0) {
575 : 21800 : lex->tok_kind = MP_TOKEN_DEDENT;
576 : 21800 : lex->emit_dent += 1;
577 : :
578 [ + + ]: 503731 : } else if (lex->emit_dent > 0) {
579 : 21804 : lex->tok_kind = MP_TOKEN_INDENT;
580 : 21804 : lex->emit_dent -= 1;
581 : :
582 [ + + + + ]: 481927 : } else if (had_physical_newline && lex->nested_bracket_level == 0) {
583 : 66615 : lex->tok_kind = MP_TOKEN_NEWLINE;
584 : :
585 : 66615 : size_t num_spaces = lex->column - 1;
586 [ + + ]: 66615 : if (num_spaces == indent_top(lex)) {
587 [ + + ]: 39085 : } else if (num_spaces > indent_top(lex)) {
588 : 21804 : indent_push(lex, num_spaces);
589 : 21804 : lex->emit_dent += 1;
590 : : } else {
591 [ + + ]: 39085 : while (num_spaces < indent_top(lex)) {
592 : 21804 : indent_pop(lex);
593 : 21804 : lex->emit_dent -= 1;
594 : : }
595 [ + + ]: 17281 : if (num_spaces != indent_top(lex)) {
596 : 4 : lex->tok_kind = MP_TOKEN_DEDENT_MISMATCH;
597 : : }
598 : : }
599 : :
600 [ + + ]: 415312 : } else if (is_end(lex)) {
601 : 3590 : lex->tok_kind = MP_TOKEN_END;
602 : :
603 [ + + ]: 411722 : } else if (is_string_or_bytes(lex)) {
604 : : // a string or bytes literal
605 : :
606 : : // Python requires adjacent string/bytes literals to be automatically
607 : : // concatenated. We do it here in the tokeniser to make efficient use of RAM,
608 : : // because then the lexer's vstr can be used to accumulate the string literal,
609 : : // in contrast to creating a parse tree of strings and then joining them later
610 : : // in the compiler. It's also more compact in code size to do it here.
611 : :
612 : : // MP_TOKEN_END is used to indicate that this is the first string token
613 : 17005 : lex->tok_kind = MP_TOKEN_END;
614 : :
615 : : // Loop to accumulate string/bytes literals
616 : 17203 : do {
617 : : // parse type codes
618 : 17203 : bool is_raw = false;
619 : 17203 : bool is_fstring = false;
620 : 17203 : mp_token_kind_t kind = MP_TOKEN_STRING;
621 : 17203 : int n_char = 0;
622 [ + + ]: 17203 : if (is_char(lex, 'u')) {
623 : : n_char = 1;
624 [ + + ]: 17201 : } else if (is_char(lex, 'b')) {
625 : 1980 : kind = MP_TOKEN_BYTES;
626 : 1980 : n_char = 1;
627 [ + + ]: 1980 : if (is_char_following(lex, 'r')) {
628 : 2 : is_raw = true;
629 : 2 : n_char = 2;
630 : : }
631 [ + + ]: 15221 : } else if (is_char(lex, 'r')) {
632 : 108 : is_raw = true;
633 : 108 : n_char = 1;
634 [ + + ]: 108 : if (is_char_following(lex, 'b')) {
635 : 4 : kind = MP_TOKEN_BYTES;
636 : 4 : n_char = 2;
637 : : }
638 : : #if MICROPY_PY_FSTRINGS
639 [ - + ]: 108 : if (is_char_following(lex, 'f')) {
640 : : // raw-f-strings unsupported, immediately return (invalid) token.
641 : 0 : lex->tok_kind = MP_TOKEN_FSTRING_RAW;
642 : 0 : break;
643 : : }
644 : : #endif
645 : : }
646 : : #if MICROPY_PY_FSTRINGS
647 [ + + ]: 15113 : else if (is_char(lex, 'f')) {
648 [ - + ]: 77 : if (is_char_following(lex, 'r')) {
649 : : // raw-f-strings unsupported, immediately return (invalid) token.
650 : 0 : lex->tok_kind = MP_TOKEN_FSTRING_RAW;
651 : 0 : break;
652 : : }
653 : : n_char = 1;
654 : : is_fstring = true;
655 : : }
656 : : #endif
657 : :
658 : : // Set or check token kind
659 [ + + ]: 17203 : if (lex->tok_kind == MP_TOKEN_END) {
660 : 17005 : lex->tok_kind = kind;
661 [ + + ]: 198 : } else if (lex->tok_kind != kind) {
662 : : // Can't concatenate string with bytes
663 : : break;
664 : : }
665 : :
666 : : // Skip any type code characters
667 [ + + ]: 17199 : if (n_char != 0) {
668 : 2163 : next_char(lex);
669 [ + + ]: 2163 : if (n_char == 2) {
670 : 6 : next_char(lex);
671 : : }
672 : : }
673 : :
674 : : // Parse the literal
675 : 17199 : parse_string_literal(lex, is_raw, is_fstring);
676 : :
677 : : // Skip whitespace so we can check if there's another string following
678 : 17197 : skip_whitespace(lex, true);
679 : :
680 [ + + ]: 17197 : } while (is_string_or_bytes(lex));
681 : :
682 [ + + ]: 394717 : } else if (is_head_of_identifier(lex)) {
683 : 158019 : lex->tok_kind = MP_TOKEN_NAME;
684 : :
685 : : // get first char (add as byte to remain 8-bit clean and support utf-8)
686 : 158019 : vstr_add_byte(&lex->vstr, CUR_CHAR(lex));
687 : 158019 : next_char(lex);
688 : :
689 : : // get tail chars
690 [ + - + + ]: 726222 : while (!is_end(lex) && is_tail_of_identifier(lex)) {
691 : 568205 : vstr_add_byte(&lex->vstr, CUR_CHAR(lex));
692 : 568203 : next_char(lex);
693 : : }
694 : :
695 : : // Check if the name is a keyword.
696 : : // We also check for __debug__ here and convert it to its value. This is
697 : : // so the parser gives a syntax error on, eg, x.__debug__. Otherwise, we
698 : : // need to check for this special token in many places in the compiler.
699 : 158019 : const char *s = vstr_null_terminated_str(&lex->vstr);
700 [ + + ]: 3381619 : for (size_t i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) {
701 : 3381436 : int cmp = strcmp(s, tok_kw[i]);
702 [ + + ]: 3381436 : if (cmp == 0) {
703 : 43433 : lex->tok_kind = MP_TOKEN_KW_FALSE + i;
704 [ + + ]: 43433 : if (lex->tok_kind == MP_TOKEN_KW___DEBUG__) {
705 [ + + ]: 18 : lex->tok_kind = (MP_STATE_VM(mp_optimise_value) == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE);
706 : : }
707 : : break;
708 [ + + ]: 3338003 : } else if (cmp < 0) {
709 : : // Table is sorted and comparison was less-than, so stop searching
710 : : break;
711 : : }
712 : : }
713 : :
714 [ + + + + : 236697 : } else if (is_digit(lex) || (is_char(lex, '.') && is_following_digit(lex))) {
+ + ]
715 : 27235 : bool forced_integer = false;
716 [ + + ]: 27235 : if (is_char(lex, '.')) {
717 : 2 : lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
718 : : } else {
719 : 27233 : lex->tok_kind = MP_TOKEN_INTEGER;
720 [ + + + + ]: 27233 : if (is_char(lex, '0') && is_following_base_char(lex)) {
721 : 907 : forced_integer = true;
722 : : }
723 : : }
724 : :
725 : : // get first char
726 : 27235 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
727 : 27235 : next_char(lex);
728 : :
729 : : // get tail chars
730 [ + - ]: 73837 : while (!is_end(lex)) {
731 [ + + + + ]: 73837 : if (!forced_integer && is_char_or(lex, 'e', 'E')) {
732 : 170 : lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
733 : 170 : vstr_add_char(&lex->vstr, 'e');
734 : 170 : next_char(lex);
735 [ + - + + ]: 170 : if (is_char(lex, '+') || is_char(lex, '-')) {
736 : 96 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
737 : 96 : next_char(lex);
738 : : }
739 [ + + + + : 73667 : } else if (is_letter(lex) || is_digit(lex) || is_char(lex, '.')) {
+ + ]
740 [ + + ]: 46382 : if (is_char_or3(lex, '.', 'j', 'J')) {
741 : 1543 : lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
742 : : }
743 : 46382 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
744 : 46382 : next_char(lex);
745 [ + + ]: 27285 : } else if (is_char(lex, '_')) {
746 : 50 : next_char(lex);
747 : : } else {
748 : : break;
749 : : }
750 : : }
751 : :
752 : : } else {
753 : : // search for encoded delimiter or operator
754 : :
755 : : const char *t = tok_enc;
756 : : size_t tok_enc_index = 0;
757 [ + + + + ]: 2134380 : for (; *t != 0 && !is_char(lex, *t); t += 1) {
758 [ + + ]: 1924917 : if (*t == 'e' || *t == 'c') {
759 : 705681 : t += 1;
760 : : }
761 : 1924917 : tok_enc_index += 1;
762 : : }
763 : :
764 : 209463 : next_char(lex);
765 : :
766 [ + + ]: 209463 : if (*t == 0) {
767 : : // didn't match any delimiter or operator characters
768 : 16 : lex->tok_kind = MP_TOKEN_INVALID;
769 : :
770 [ + + ]: 209447 : } else if (*t == '!') {
771 : : // "!=" is a special case because "!" is not a valid operator
772 [ + + ]: 355 : if (is_char(lex, '=')) {
773 : 351 : next_char(lex);
774 : 351 : lex->tok_kind = MP_TOKEN_OP_NOT_EQUAL;
775 : : } else {
776 : 4 : lex->tok_kind = MP_TOKEN_INVALID;
777 : : }
778 : :
779 [ + + ]: 209092 : } else if (*t == '.') {
780 : : // "." and "..." are special cases because ".." is not a valid operator
781 [ + + ]: 16669 : if (is_char_and(lex, '.', '.')) {
782 : 14 : next_char(lex);
783 : 14 : next_char(lex);
784 : 14 : lex->tok_kind = MP_TOKEN_ELLIPSIS;
785 : : } else {
786 : 16655 : lex->tok_kind = MP_TOKEN_DEL_PERIOD;
787 : : }
788 : :
789 : : } else {
790 : : // matched a delimiter or operator character
791 : :
792 : : // get the maximum characters for a valid token
793 : 192423 : t += 1;
794 : 192423 : size_t t_index = tok_enc_index;
795 [ + + ]: 240057 : while (*t == 'c' || *t == 'e') {
796 : 51659 : t_index += 1;
797 [ + + ]: 51659 : if (is_char(lex, t[1])) {
798 : 3167 : next_char(lex);
799 : 3167 : tok_enc_index = t_index;
800 [ + + ]: 3167 : if (*t == 'e') {
801 : : break;
802 : : }
803 [ + + ]: 48492 : } else if (*t == 'c') {
804 : : break;
805 : : }
806 : 47634 : t += 2;
807 : : }
808 : :
809 : : // set token kind
810 : 192423 : lex->tok_kind = tok_enc_kind[tok_enc_index];
811 : :
812 : : // compute bracket level for implicit line joining
813 [ + + + + ]: 192423 : if (lex->tok_kind == MP_TOKEN_DEL_PAREN_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACKET_OPEN || lex->tok_kind == MP_TOKEN_DEL_BRACE_OPEN) {
814 : 60803 : lex->nested_bracket_level += 1;
815 [ + + + + ]: 131620 : } else if (lex->tok_kind == MP_TOKEN_DEL_PAREN_CLOSE || lex->tok_kind == MP_TOKEN_DEL_BRACKET_CLOSE || lex->tok_kind == MP_TOKEN_DEL_BRACE_CLOSE) {
816 : 60773 : lex->nested_bracket_level -= 1;
817 : : }
818 : : }
819 : : }
820 : 525529 : }
821 : :
822 : 3722 : mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) {
823 : 3722 : mp_lexer_t *lex = m_new_obj(mp_lexer_t);
824 : :
825 : 3722 : lex->source_name = src_name;
826 : 3722 : lex->reader = reader;
827 : 3722 : lex->line = 1;
828 : 3722 : lex->column = (size_t)-2; // account for 3 dummy bytes
829 : 3722 : lex->emit_dent = 0;
830 : 3722 : lex->nested_bracket_level = 0;
831 : 3722 : lex->alloc_indent_level = MICROPY_ALLOC_LEXER_INDENT_INIT;
832 : 3722 : lex->num_indent_level = 1;
833 : 3722 : lex->indent_level = m_new(uint16_t, lex->alloc_indent_level);
834 : 3722 : vstr_init(&lex->vstr, 32);
835 : : #if MICROPY_PY_FSTRINGS
836 : 3722 : vstr_init(&lex->fstring_args, 0);
837 : : #endif
838 : :
839 : : // store sentinel for first indentation level
840 : 3722 : lex->indent_level[0] = 0;
841 : :
842 : : // load lexer with start of file, advancing lex->column to 1
843 : : // start with dummy bytes and use next_char() for proper EOL/EOF handling
844 : 3722 : lex->chr0 = lex->chr1 = lex->chr2 = 0;
845 : 3722 : next_char(lex);
846 : 3722 : next_char(lex);
847 : 3722 : next_char(lex);
848 : :
849 : : // preload first token
850 : 3722 : mp_lexer_to_next(lex);
851 : :
852 : : // Check that the first token is in the first column. If it's not then we
853 : : // convert the token kind to INDENT so that the parser gives a syntax error.
854 [ + + ]: 3720 : if (lex->tok_column != 1) {
855 : 4 : lex->tok_kind = MP_TOKEN_INDENT;
856 : : }
857 : :
858 : 3720 : return lex;
859 : : }
860 : :
861 : 1616 : mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len, size_t free_len) {
862 : 1616 : mp_reader_t reader;
863 : 1616 : mp_reader_new_mem(&reader, (const byte *)str, len, free_len);
864 : 1616 : return mp_lexer_new(src_name, reader);
865 : : }
866 : :
867 : : #if MICROPY_READER_POSIX || MICROPY_READER_VFS
868 : :
869 : 2109 : mp_lexer_t *mp_lexer_new_from_file(const char *filename) {
870 : 2109 : mp_reader_t reader;
871 : 2109 : mp_reader_new_file(&reader, filename);
872 : 2105 : return mp_lexer_new(qstr_from_str(filename), reader);
873 : : }
874 : :
875 : : #if MICROPY_HELPER_LEXER_UNIX
876 : :
877 : 1 : mp_lexer_t *mp_lexer_new_from_fd(qstr filename, int fd, bool close_fd) {
878 : 1 : mp_reader_t reader;
879 : 1 : mp_reader_new_file_from_fd(&reader, fd, close_fd);
880 : 1 : return mp_lexer_new(filename, reader);
881 : : }
882 : :
883 : : #endif
884 : :
885 : : #endif
886 : :
887 : 3574 : void mp_lexer_free(mp_lexer_t *lex) {
888 [ + - ]: 3574 : if (lex) {
889 : 3574 : lex->reader.close(lex->reader.data);
890 : 3574 : vstr_clear(&lex->vstr);
891 : : #if MICROPY_PY_FSTRINGS
892 : 3574 : vstr_clear(&lex->fstring_args);
893 : : #endif
894 : 3574 : m_del(uint16_t, lex->indent_level, lex->alloc_indent_level);
895 : 3574 : m_del_obj(mp_lexer_t, lex);
896 : : }
897 : 3574 : }
898 : :
899 : : #if 0
900 : : // This function is used to print the current token and should only be
901 : : // needed to debug the lexer, so it's not available via a config option.
902 : : void mp_lexer_show_token(const mp_lexer_t *lex) {
903 : : printf("(" UINT_FMT ":" UINT_FMT ") kind:%u str:%p len:%zu", lex->tok_line, lex->tok_column, lex->tok_kind, lex->vstr.buf, lex->vstr.len);
904 : : if (lex->vstr.len > 0) {
905 : : const byte *i = (const byte *)lex->vstr.buf;
906 : : const byte *j = (const byte *)i + lex->vstr.len;
907 : : printf(" ");
908 : : while (i < j) {
909 : : unichar c = utf8_get_char(i);
910 : : i = utf8_next_char(i);
911 : : if (unichar_isprint(c)) {
912 : : printf("%c", (int)c);
913 : : } else {
914 : : printf("?");
915 : : }
916 : : }
917 : : }
918 : : printf("\n");
919 : : }
920 : : #endif
921 : :
922 : : #endif // MICROPY_ENABLE_COMPILER
|