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 : 3366711 : static bool is_end(mp_lexer_t *lex) {
46 : 3366711 : return lex->chr0 == MP_LEXER_EOF;
47 : : }
48 : :
49 : 1793890 : static bool is_physical_newline(mp_lexer_t *lex) {
50 : 1793890 : return lex->chr0 == '\n';
51 : : }
52 : :
53 : 4072842 : static bool is_char(mp_lexer_t *lex, byte c) {
54 : 4072842 : return lex->chr0 == c;
55 : : }
56 : :
57 : 553962 : static bool is_char_or(mp_lexer_t *lex, byte c1, byte c2) {
58 [ + + + + ]: 553962 : return lex->chr0 == c1 || lex->chr0 == c2;
59 : : }
60 : :
61 : 48767 : static bool is_char_or3(mp_lexer_t *lex, byte c1, byte c2, byte c3) {
62 [ + + + + : 48767 : return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3;
+ - ]
63 : : }
64 : :
65 : : #if MICROPY_PY_FSTRINGS
66 : 466415 : static bool is_char_or4(mp_lexer_t *lex, byte c1, byte c2, byte c3, byte c4) {
67 [ + + + + : 466415 : return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3 || lex->chr0 == c4;
+ + + + ]
68 : : }
69 : : #endif
70 : :
71 : 2433 : static bool is_char_following(mp_lexer_t *lex, byte c) {
72 : 2433 : return lex->chr1 == c;
73 : : }
74 : :
75 : 28838 : static bool is_char_following_or(mp_lexer_t *lex, byte c1, byte c2) {
76 [ + + + + ]: 28838 : return lex->chr1 == c1 || lex->chr1 == c2;
77 : : }
78 : :
79 : 1414 : static bool is_char_following_following_or(mp_lexer_t *lex, byte c1, byte c2) {
80 [ + + + + ]: 1414 : return lex->chr2 == c1 || lex->chr2 == c2;
81 : : }
82 : :
83 : 2495530 : static bool is_char_and(mp_lexer_t *lex, byte c1, byte c2) {
84 [ + + + + ]: 2495530 : return lex->chr0 == c1 && lex->chr1 == c2;
85 : : }
86 : :
87 : 1049168 : static bool is_whitespace(mp_lexer_t *lex) {
88 : 1049168 : return unichar_isspace(lex->chr0);
89 : : }
90 : :
91 : 1366120 : static bool is_letter(mp_lexer_t *lex) {
92 : 1366120 : return unichar_isalpha(lex->chr0);
93 : : }
94 : :
95 : 525128 : static bool is_digit(mp_lexer_t *lex) {
96 : 525128 : return unichar_isdigit(lex->chr0);
97 : : }
98 : :
99 : 20523 : static bool is_following_digit(mp_lexer_t *lex) {
100 : 20523 : return unichar_isdigit(lex->chr1);
101 : : }
102 : :
103 : 5701 : static bool is_following_base_char(mp_lexer_t *lex) {
104 : 5701 : const unichar chr1 = lex->chr1 | 0x20;
105 [ + + + ]: 5701 : return chr1 == 'b' || chr1 == 'o' || chr1 == 'x';
106 : : }
107 : :
108 : 148 : static bool is_following_odigit(mp_lexer_t *lex) {
109 : 148 : return lex->chr1 >= '0' && lex->chr1 <= '7';
110 : : }
111 : :
112 : 483349 : static bool is_string_or_bytes(mp_lexer_t *lex) {
113 : 483349 : return is_char_or(lex, '\'', '\"')
114 : : #if MICROPY_PY_FSTRINGS
115 [ + + + + ]: 466413 : || (is_char_or4(lex, 'r', 'u', 'b', 'f') && is_char_following_or(lex, '\'', '\"'))
116 [ + + + + ]: 464108 : || (((is_char_and(lex, 'r', 'f') || is_char_and(lex, 'f', 'r'))
117 [ + + ]: 1105 : && is_char_following_following_or(lex, '\'', '\"')))
118 : : #else
119 : : || (is_char_or3(lex, 'r', 'u', 'b') && is_char_following_or(lex, '\'', '\"'))
120 : : #endif
121 [ + + + + : 947453 : || ((is_char_and(lex, 'r', 'b') || is_char_and(lex, 'b', 'r'))
+ + ]
122 [ + + ]: 298 : && 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 : 1287619 : static bool is_head_of_identifier(mp_lexer_t *lex) {
127 [ + + + + : 1287619 : return is_letter(lex) || lex->chr0 == '_' || lex->chr0 >= 0x80;
+ + ]
128 : : }
129 : :
130 : 842542 : static bool is_tail_of_identifier(mp_lexer_t *lex) {
131 [ + + + + ]: 842542 : return is_head_of_identifier(lex) || is_digit(lex);
132 : : }
133 : :
134 : 2470145 : static void next_char(mp_lexer_t *lex) {
135 [ + + ]: 2470145 : if (lex->chr0 == '\n') {
136 : : // a new line
137 : 106355 : ++lex->line;
138 : 106355 : lex->column = 1;
139 [ + + ]: 2363790 : } 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 : 2363786 : ++lex->column;
145 : : }
146 : :
147 : : // shift the input queue forward
148 : 2470145 : lex->chr0 = lex->chr1;
149 : 2470145 : 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 [ + + ]: 2470145 : if (lex->fstring_args_idx) {
154 : : // if there are saved chars, then we're currently injecting fstring args
155 [ + + ]: 1665 : if (lex->fstring_args_idx < lex->fstring_args.len) {
156 : 1374 : lex->chr2 = lex->fstring_args.buf[lex->fstring_args_idx++];
157 : : } else {
158 : : // no more fstring arg bytes
159 : 291 : lex->chr2 = '\0';
160 : : }
161 : :
162 [ + + ]: 1665 : if (lex->chr0 == '\0') {
163 : : // consumed all fstring data, restore saved input queue
164 : 97 : lex->chr0 = lex->chr0_saved;
165 : 97 : lex->chr1 = lex->chr1_saved;
166 : 97 : lex->chr2 = lex->chr2_saved;
167 : : // stop consuming fstring arg data
168 : 97 : vstr_reset(&lex->fstring_args);
169 : 97 : lex->fstring_args_idx = 0;
170 : : }
171 : : } else
172 : : #endif
173 : : {
174 : 2468480 : lex->chr2 = lex->reader.readbyte(lex->reader.data);
175 : : }
176 : :
177 [ + + ]: 2470178 : 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 [ + + + + : 2470178 : if (lex->chr2 == MP_LEXER_EOF && lex->chr1 != MP_LEXER_EOF && lex->chr1 != '\n') {
+ + ]
188 : 1625 : lex->chr2 = '\n';
189 : : }
190 : 2470178 : }
191 : :
192 : 23793 : static void indent_push(mp_lexer_t *lex, size_t indent) {
193 [ + + ]: 23793 : 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 : 23793 : lex->indent_level[lex->num_indent_level++] = indent;
198 : 23793 : }
199 : :
200 : 116800 : static size_t indent_top(mp_lexer_t *lex) {
201 : 116800 : return lex->indent_level[lex->num_indent_level - 1];
202 : : }
203 : :
204 : 23793 : static void indent_pop(mp_lexer_t *lex) {
205 : 23793 : lex->num_indent_level -= 1;
206 : 23793 : }
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 : : static const uint8_t tok_enc_kind[] = {
232 : : MP_TOKEN_DEL_PAREN_OPEN, MP_TOKEN_DEL_PAREN_CLOSE,
233 : : MP_TOKEN_DEL_BRACKET_OPEN, MP_TOKEN_DEL_BRACKET_CLOSE,
234 : : MP_TOKEN_DEL_BRACE_OPEN, MP_TOKEN_DEL_BRACE_CLOSE,
235 : : MP_TOKEN_DEL_COMMA, MP_TOKEN_DEL_SEMICOLON, MP_TOKEN_OP_TILDE,
236 : :
237 : : MP_TOKEN_DEL_COLON, MP_TOKEN_OP_ASSIGN,
238 : : MP_TOKEN_OP_LESS, MP_TOKEN_OP_LESS_EQUAL, MP_TOKEN_OP_DBL_LESS, MP_TOKEN_DEL_DBL_LESS_EQUAL,
239 : : MP_TOKEN_OP_MORE, MP_TOKEN_OP_MORE_EQUAL, MP_TOKEN_OP_DBL_MORE, MP_TOKEN_DEL_DBL_MORE_EQUAL,
240 : : MP_TOKEN_OP_STAR, MP_TOKEN_DEL_STAR_EQUAL, MP_TOKEN_OP_DBL_STAR, MP_TOKEN_DEL_DBL_STAR_EQUAL,
241 : : MP_TOKEN_OP_PLUS, MP_TOKEN_DEL_PLUS_EQUAL,
242 : : MP_TOKEN_OP_MINUS, MP_TOKEN_DEL_MINUS_EQUAL, MP_TOKEN_DEL_MINUS_MORE,
243 : : MP_TOKEN_OP_AMPERSAND, MP_TOKEN_DEL_AMPERSAND_EQUAL,
244 : : MP_TOKEN_OP_PIPE, MP_TOKEN_DEL_PIPE_EQUAL,
245 : : MP_TOKEN_OP_SLASH, MP_TOKEN_DEL_SLASH_EQUAL, MP_TOKEN_OP_DBL_SLASH, MP_TOKEN_DEL_DBL_SLASH_EQUAL,
246 : : MP_TOKEN_OP_PERCENT, MP_TOKEN_DEL_PERCENT_EQUAL,
247 : : MP_TOKEN_OP_CARET, MP_TOKEN_DEL_CARET_EQUAL,
248 : : MP_TOKEN_OP_AT, MP_TOKEN_DEL_AT_EQUAL,
249 : : MP_TOKEN_DEL_EQUAL, MP_TOKEN_OP_DBL_EQUAL,
250 : : };
251 : :
252 : : // must have the same order as enum in lexer.h
253 : : // must be sorted according to strcmp
254 : : static const char *const tok_kw[] = {
255 : : "False",
256 : : "None",
257 : : "True",
258 : : "__debug__",
259 : : "and",
260 : : "as",
261 : : "assert",
262 : : #if MICROPY_PY_ASYNC_AWAIT
263 : : "async",
264 : : "await",
265 : : #endif
266 : : "break",
267 : : "class",
268 : : "continue",
269 : : "def",
270 : : "del",
271 : : "elif",
272 : : "else",
273 : : "except",
274 : : "finally",
275 : : "for",
276 : : "from",
277 : : "global",
278 : : "if",
279 : : "import",
280 : : "in",
281 : : "is",
282 : : "lambda",
283 : : "nonlocal",
284 : : "not",
285 : : "or",
286 : : "pass",
287 : : "raise",
288 : : "return",
289 : : "try",
290 : : "while",
291 : : "with",
292 : : "yield",
293 : : };
294 : :
295 : : // This is called with CUR_CHAR() before first hex digit, and should return with
296 : : // it pointing to last hex digit
297 : : // num_digits must be greater than zero
298 : 4194 : static bool get_hex(mp_lexer_t *lex, size_t num_digits, mp_uint_t *result) {
299 : 4194 : mp_uint_t num = 0;
300 [ + + ]: 12658 : while (num_digits-- != 0) {
301 : 8480 : next_char(lex);
302 : 8480 : unichar c = CUR_CHAR(lex);
303 [ + + ]: 8480 : if (!unichar_isxdigit(c)) {
304 : : return false;
305 : : }
306 : 8464 : num = (num << 4) + unichar_xdigit_value(c);
307 : : }
308 : 4178 : *result = num;
309 : 4178 : return true;
310 : : }
311 : :
312 : 19247 : static void parse_string_literal(mp_lexer_t *lex, bool is_raw, bool is_fstring) {
313 : : // get first quoting character
314 : 19247 : char quote_char = '\'';
315 [ + + ]: 19247 : if (is_char(lex, '\"')) {
316 : 15395 : quote_char = '\"';
317 : : }
318 : 19247 : next_char(lex);
319 : :
320 : : // work out if it's a single or triple quoted literal
321 : 19247 : size_t num_quotes;
322 [ + + ]: 19247 : if (is_char_and(lex, quote_char, quote_char)) {
323 : : // triple quotes
324 : 24 : next_char(lex);
325 : 24 : next_char(lex);
326 : 24 : num_quotes = 3;
327 : : } else {
328 : : // single quotes
329 : : num_quotes = 1;
330 : : }
331 : :
332 : 19247 : size_t n_closing = 0;
333 : : #if MICROPY_PY_FSTRINGS
334 [ + + ]: 19247 : if (is_fstring) {
335 : : // assume there's going to be interpolation, so prep the injection data
336 : : // fstring_args_idx==0 && len(fstring_args)>0 means we're extracting the args.
337 : : // only when fstring_args_idx>0 will we consume the arg data
338 : : // lex->fstring_args is reset when finished, so at this point there are two cases:
339 : : // - lex->fstring_args is empty: start of a new f-string
340 : : // - lex->fstring_args is non-empty: concatenation of adjacent f-strings
341 [ + + ]: 115 : if (vstr_len(&lex->fstring_args) == 0) {
342 : 105 : vstr_add_str(&lex->fstring_args, ".format(");
343 : : }
344 : : }
345 : : #endif
346 : :
347 [ + - + + : 174228 : while (!is_end(lex) && (num_quotes > 1 || !is_char(lex, '\n')) && n_closing < num_quotes) {
+ + + + ]
348 [ + + ]: 154983 : if (is_char(lex, quote_char)) {
349 : 19273 : n_closing += 1;
350 : 19273 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
351 : : } else {
352 : 135821 : n_closing = 0;
353 : :
354 : : #if MICROPY_PY_FSTRINGS
355 [ + + + + ]: 135821 : while (is_fstring && is_char(lex, '{')) {
356 : 111 : next_char(lex);
357 [ + + ]: 111 : if (is_char(lex, '{')) {
358 : : // "{{" is passed through unchanged to be handled by str.format
359 : 8 : vstr_add_byte(&lex->vstr, '{');
360 : 8 : next_char(lex);
361 : : } else {
362 : : // wrap each argument in (), e.g.
363 : : // f"{a,b,}, {c}" --> "{}".format((a,b), (c),)
364 : 103 : vstr_add_byte(&lex->fstring_args, '(');
365 : : // remember the start of this argument (if we need it for f'{a=}').
366 : 103 : size_t i = lex->fstring_args.len;
367 : : // Extract characters inside the { until the bracket level
368 : : // is zero and we reach the conversion specifier '!',
369 : : // format specifier ':', or closing '}'. The conversion
370 : : // and format specifiers are left unchanged in the format
371 : : // string to be handled by str.format.
372 : : // (MicroPython limitation) note: this is completely
373 : : // unaware of Python syntax and will not handle any
374 : : // expression containing '}' or ':'. e.g. f'{"}"}' or f'
375 : : // {foo({})}'. However, detection of the '!' will
376 : : // specifically ensure that it's followed by [rs] and
377 : : // then either the format specifier or the closing
378 : : // brace. This allows the use of e.g. != in expressions.
379 : 103 : unsigned int nested_bracket_level = 0;
380 [ + - + + ]: 560 : while (!is_end(lex) && (nested_bracket_level != 0
381 [ + + ]: 500 : || !(is_char_or(lex, ':', '}')
382 [ + + ]: 409 : || (is_char(lex, '!')
383 [ + + ]: 20 : && is_char_following_or(lex, 'r', 's')
384 [ - + ]: 12 : && is_char_following_following_or(lex, ':', '}'))))
385 : : ) {
386 : 457 : unichar c = CUR_CHAR(lex);
387 [ + + ]: 457 : if (c == '[' || c == '{') {
388 : 12 : nested_bracket_level += 1;
389 [ + + ]: 445 : } else if (c == ']' || c == '}') {
390 : 12 : nested_bracket_level -= 1;
391 : : }
392 : : // like the default case at the end of this function, stay 8-bit clean
393 : 457 : vstr_add_byte(&lex->fstring_args, c);
394 : 457 : next_char(lex);
395 : : }
396 [ + + ]: 103 : if (lex->fstring_args.buf[lex->fstring_args.len - 1] == '=') {
397 : : // if the last character of the arg was '=', then inject "arg=" before the '{'.
398 : : // f'{a=}' --> 'a={}'.format(a)
399 : 18 : vstr_add_strn(&lex->vstr, lex->fstring_args.buf + i, lex->fstring_args.len - i);
400 : : // remove the trailing '='
401 : 18 : lex->fstring_args.len--;
402 : : }
403 : : // close the paren-wrapped arg to .format().
404 : 103 : vstr_add_byte(&lex->fstring_args, ')');
405 : : // comma-separate args to .format().
406 : 103 : vstr_add_byte(&lex->fstring_args, ',');
407 : : }
408 : 111 : vstr_add_byte(&lex->vstr, '{');
409 : : }
410 : : #endif
411 : :
412 [ + + ]: 135710 : if (is_char(lex, '\\')) {
413 : 5128 : next_char(lex);
414 : 5128 : unichar c = CUR_CHAR(lex);
415 [ + + ]: 5128 : if (is_raw) {
416 : : // raw strings allow escaping of quotes, but the backslash is also emitted
417 : 124 : vstr_add_char(&lex->vstr, '\\');
418 : : } else {
419 [ + + + + : 5004 : switch (c) {
+ + + + +
+ + + + ]
420 : : // note: "c" can never be MP_LEXER_EOF because next_char
421 : : // always inserts a newline at the end of the input stream
422 : : case '\n':
423 : : c = MP_LEXER_EOF;
424 : : break; // backslash escape the newline, just ignore it
425 : : case '\\':
426 : : break;
427 : : case '\'':
428 : : break;
429 : : case '"':
430 : : break;
431 : : case 'a':
432 : : c = 0x07;
433 : : break;
434 : : case 'b':
435 : : c = 0x08;
436 : : break;
437 : : case 't':
438 : : c = 0x09;
439 : : break;
440 : : case 'n':
441 : : c = 0x0a;
442 : : break;
443 : : case 'v':
444 : : c = 0x0b;
445 : : break;
446 : : case 'f':
447 : : c = 0x0c;
448 : : break;
449 : : case 'r':
450 : : c = 0x0d;
451 : : break;
452 : 28 : case 'u':
453 : : case 'U':
454 [ + + ]: 28 : if (lex->tok_kind == MP_TOKEN_BYTES) {
455 : : // b'\u1234' == b'\\u1234'
456 : 2 : vstr_add_char(&lex->vstr, '\\');
457 : 2 : break;
458 : : }
459 : : // Otherwise fall through.
460 : 4194 : MP_FALLTHROUGH
461 : : case 'x': {
462 : 4194 : mp_uint_t num = 0;
463 [ + - + + : 4204 : if (!get_hex(lex, (c == 'x' ? 2 : c == 'u' ? 4 : 8), &num)) {
+ + ]
464 : : // not enough hex chars for escape sequence
465 : 16 : lex->tok_kind = MP_TOKEN_INVALID;
466 : : }
467 : 4194 : c = num;
468 : 4194 : break;
469 : : }
470 : : case 'N':
471 : : // Supporting '\N{LATIN SMALL LETTER A}' == 'a' would require keeping the
472 : : // entire Unicode name table in the core. As of Unicode 6.3.0, that's nearly
473 : : // 3MB of text; even gzip-compressed and with minimal structure, it'll take
474 : : // roughly half a meg of storage. This form of Unicode escape may be added
475 : : // later on, but it's definitely not a priority right now. -- CJA 20140607
476 : 2 : mp_raise_NotImplementedError(MP_ERROR_TEXT("unicode name escapes"));
477 : 146 : break;
478 : 146 : default:
479 [ + + ]: 146 : if (c >= '0' && c <= '7') {
480 : : // Octal sequence, 1-3 chars
481 : 140 : size_t digits = 3;
482 : 140 : mp_uint_t num = c - '0';
483 [ + + + + ]: 148 : while (is_following_odigit(lex) && --digits != 0) {
484 : 8 : next_char(lex);
485 : 8 : num = num * 8 + (CUR_CHAR(lex) - '0');
486 : : }
487 : 140 : c = num;
488 : : } else {
489 : : // unrecognised escape character; CPython lets this through verbatim as '\' and then the character
490 : 6 : vstr_add_char(&lex->vstr, '\\');
491 : : }
492 : : break;
493 : : }
494 : : }
495 [ + - ]: 4466 : if (c != MP_LEXER_EOF) {
496 : : #if MICROPY_PY_BUILTINS_STR_UNICODE
497 [ + + + + ]: 5124 : if (c < 0x110000 && lex->tok_kind == MP_TOKEN_STRING) {
498 : : // Valid unicode character in a str object.
499 : 748 : vstr_add_char(&lex->vstr, c);
500 [ + - + + ]: 4374 : } else if (c < 0x100 && lex->tok_kind == MP_TOKEN_BYTES) {
501 : : // Valid byte in a bytes object.
502 : 4358 : vstr_add_byte(&lex->vstr, c);
503 : : }
504 : : #else
505 : : if (c < 0x100) {
506 : : // Without unicode everything is just added as an 8-bit byte.
507 : : vstr_add_byte(&lex->vstr, c);
508 : : }
509 : : #endif
510 : : else {
511 : : // Character out of range; this raises a generic SyntaxError.
512 : 18 : lex->tok_kind = MP_TOKEN_INVALID;
513 : : }
514 : : }
515 : : } else {
516 : : // Add the "character" as a byte so that we remain 8-bit clean.
517 : : // This way, strings are parsed correctly whether or not they contain utf-8 chars.
518 : 130582 : vstr_add_byte(&lex->vstr, CUR_CHAR(lex));
519 : : }
520 : : }
521 : 154981 : next_char(lex);
522 : : }
523 : :
524 : : // check we got the required end quotes
525 [ + + ]: 19245 : if (n_closing < num_quotes) {
526 : 20 : lex->tok_kind = MP_TOKEN_LONELY_STRING_OPEN;
527 : : }
528 : :
529 : : // cut off the end quotes from the token text
530 : 19245 : vstr_cut_tail_bytes(&lex->vstr, n_closing);
531 : 19245 : }
532 : :
533 : : // This function returns whether it has crossed a newline or not.
534 : : // It therefore always return true if stop_at_newline is true
535 : 682886 : static bool skip_whitespace(mp_lexer_t *lex, bool stop_at_newline) {
536 [ + + ]: 1238877 : while (!is_end(lex)) {
537 [ + + ]: 1230010 : if (is_physical_newline(lex)) {
538 [ + + + + ]: 180841 : if (stop_at_newline && lex->nested_bracket_level == 0) {
539 : : return true;
540 : : }
541 : 106247 : next_char(lex);
542 [ + + ]: 1049169 : } else if (is_whitespace(lex)) {
543 : 436781 : next_char(lex);
544 [ + + ]: 612389 : } else if (is_char(lex, '#')) {
545 : 12919 : next_char(lex);
546 [ + - + + ]: 563884 : while (!is_end(lex) && !is_physical_newline(lex)) {
547 : 550965 : next_char(lex);
548 : : }
549 : : // will return true on next loop
550 [ + + ]: 599470 : } else if (is_char_and(lex, '\\', '\n')) {
551 : : // line-continuation, so don't return true
552 : 40 : next_char(lex);
553 : 40 : next_char(lex);
554 : : } else {
555 : : break;
556 : : }
557 : : }
558 : : return false;
559 : : }
560 : :
561 : 589617 : void mp_lexer_to_next(mp_lexer_t *lex) {
562 : : #if MICROPY_PY_FSTRINGS
563 [ + + + + ]: 589617 : if (lex->fstring_args.len && lex->fstring_args_idx == 0) {
564 : : // moving onto the next token means the literal string is complete.
565 : : // switch into injecting the format args.
566 : 105 : vstr_add_byte(&lex->fstring_args, ')');
567 : 105 : lex->chr0_saved = lex->chr0;
568 : 105 : lex->chr1_saved = lex->chr1;
569 : 105 : lex->chr2_saved = lex->chr2;
570 : 105 : lex->chr0 = lex->fstring_args.buf[0];
571 : 105 : lex->chr1 = lex->fstring_args.buf[1];
572 : 105 : lex->chr2 = lex->fstring_args.buf[2];
573 : : // we've already extracted 3 chars, but setting this non-zero also
574 : : // means we'll start consuming the fstring data
575 : 105 : lex->fstring_args_idx = 3;
576 : : }
577 : : #endif
578 : :
579 : : // start new token text
580 : 589617 : vstr_reset(&lex->vstr);
581 : :
582 : : // skip white space and comments
583 : : // set the newline tokens at the line and column of the preceding line:
584 : : // only advance on the pointer until a new line is crossed, save the
585 : : // line and column, and then readvance it
586 : 589617 : bool had_physical_newline = skip_whitespace(lex, true);
587 : :
588 : : // set token source information
589 : 589621 : lex->tok_line = lex->line;
590 : 589621 : lex->tok_column = lex->column;
591 : :
592 [ + + ]: 589621 : if (lex->emit_dent < 0) {
593 : 23789 : lex->tok_kind = MP_TOKEN_DEDENT;
594 : 23789 : lex->emit_dent += 1;
595 : :
596 [ + + ]: 565832 : } else if (lex->emit_dent > 0) {
597 : 23793 : lex->tok_kind = MP_TOKEN_INDENT;
598 : 23793 : lex->emit_dent -= 1;
599 : :
600 [ + + ]: 542039 : } else if (had_physical_newline) {
601 : : // The cursor is at the end of the previous line, pointing to a
602 : : // physical newline. Skip any remaining whitespace, comments, and
603 : : // newlines.
604 : 74026 : skip_whitespace(lex, false);
605 : :
606 : 74026 : lex->tok_kind = MP_TOKEN_NEWLINE;
607 : :
608 : 74026 : size_t num_spaces = lex->column - 1;
609 [ + + ]: 74026 : if (num_spaces == indent_top(lex)) {
610 [ + + ]: 42774 : } else if (num_spaces > indent_top(lex)) {
611 : 23793 : indent_push(lex, num_spaces);
612 : 23793 : lex->emit_dent += 1;
613 : : } else {
614 [ + + ]: 42774 : while (num_spaces < indent_top(lex)) {
615 : 23793 : indent_pop(lex);
616 : 23793 : lex->emit_dent -= 1;
617 : : }
618 [ + + ]: 18981 : if (num_spaces != indent_top(lex)) {
619 : 4 : lex->tok_kind = MP_TOKEN_DEDENT_MISMATCH;
620 : : }
621 : : }
622 : :
623 [ + + ]: 468013 : } else if (is_end(lex)) {
624 : 3907 : lex->tok_kind = MP_TOKEN_END;
625 : :
626 [ + + ]: 464106 : } else if (is_string_or_bytes(lex)) {
627 : : // a string or bytes literal
628 : :
629 : : // Python requires adjacent string/bytes literals to be automatically
630 : : // concatenated. We do it here in the tokeniser to make efficient use of RAM,
631 : : // because then the lexer's vstr can be used to accumulate the string literal,
632 : : // in contrast to creating a parse tree of strings and then joining them later
633 : : // in the compiler. It's also more compact in code size to do it here.
634 : :
635 : : // MP_TOKEN_END is used to indicate that this is the first string token
636 : 19021 : lex->tok_kind = MP_TOKEN_END;
637 : :
638 : : // Loop to accumulate string/bytes literals
639 : 19251 : do {
640 : : // parse type codes
641 : 19251 : bool is_raw = false;
642 : 19251 : bool is_fstring = false;
643 : 19251 : mp_token_kind_t kind = MP_TOKEN_STRING;
644 : 19251 : int n_char = 0;
645 [ + + ]: 19251 : if (is_char(lex, 'u')) {
646 : : n_char = 1;
647 [ + + ]: 19249 : } else if (is_char(lex, 'b')) {
648 : 2080 : kind = MP_TOKEN_BYTES;
649 : 2080 : n_char = 1;
650 [ + + ]: 2080 : if (is_char_following(lex, 'r')) {
651 : 2 : is_raw = true;
652 : 2 : n_char = 2;
653 : : }
654 [ + + ]: 17169 : } else if (is_char(lex, 'r')) {
655 : 120 : is_raw = true;
656 : 120 : n_char = 1;
657 [ + + ]: 120 : if (is_char_following(lex, 'b')) {
658 : 4 : kind = MP_TOKEN_BYTES;
659 : 4 : n_char = 2;
660 : : }
661 : : #if MICROPY_PY_FSTRINGS
662 [ + + ]: 120 : if (is_char_following(lex, 'f')) {
663 : 2 : is_fstring = true;
664 : 2 : n_char = 2;
665 : : }
666 : : #endif
667 : : }
668 : : #if MICROPY_PY_FSTRINGS
669 [ + + ]: 17049 : else if (is_char(lex, 'f')) {
670 : 113 : is_fstring = true;
671 : 113 : n_char = 1;
672 [ + + ]: 113 : if (is_char_following(lex, 'r')) {
673 : 2 : is_raw = true;
674 : 2 : n_char = 2;
675 : : }
676 : : }
677 : : #endif
678 : :
679 : : // Set or check token kind
680 [ + + ]: 19251 : if (lex->tok_kind == MP_TOKEN_END) {
681 : 19021 : lex->tok_kind = kind;
682 [ + + ]: 230 : } else if (lex->tok_kind != kind) {
683 : : // Can't concatenate string with bytes
684 : : break;
685 : : }
686 : :
687 : : // Skip any type code characters
688 [ + + ]: 19247 : if (n_char != 0) {
689 : 2311 : next_char(lex);
690 [ + + ]: 2311 : if (n_char == 2) {
691 : 10 : next_char(lex);
692 : : }
693 : : }
694 : :
695 : : // Parse the literal
696 : 19247 : parse_string_literal(lex, is_raw, is_fstring);
697 : :
698 : : // Skip whitespace so we can check if there's another string following
699 : 19245 : skip_whitespace(lex, true);
700 : :
701 [ + + ]: 19245 : } while (is_string_or_bytes(lex));
702 : :
703 [ + + ]: 445085 : } else if (is_head_of_identifier(lex)) {
704 : 180504 : lex->tok_kind = MP_TOKEN_NAME;
705 : :
706 : : // get first char (add as byte to remain 8-bit clean and support utf-8)
707 : 180504 : vstr_add_byte(&lex->vstr, CUR_CHAR(lex));
708 : 180504 : next_char(lex);
709 : :
710 : : // get tail chars
711 [ + - + + ]: 842542 : while (!is_end(lex) && is_tail_of_identifier(lex)) {
712 : 662040 : vstr_add_byte(&lex->vstr, CUR_CHAR(lex));
713 : 662040 : next_char(lex);
714 : : }
715 : :
716 : : // Check if the name is a keyword.
717 : : // We also check for __debug__ here and convert it to its value. This is
718 : : // so the parser gives a syntax error on, eg, x.__debug__. Otherwise, we
719 : : // need to check for this special token in many places in the compiler.
720 : 180504 : const char *s = vstr_null_terminated_str(&lex->vstr);
721 [ + + ]: 3852345 : for (size_t i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) {
722 : 3852184 : int cmp = strcmp(s, tok_kw[i]);
723 [ + + ]: 3852184 : if (cmp == 0) {
724 : 48360 : lex->tok_kind = MP_TOKEN_KW_FALSE + i;
725 [ + + ]: 48360 : if (lex->tok_kind == MP_TOKEN_KW___DEBUG__) {
726 [ + + ]: 18 : lex->tok_kind = (MP_STATE_VM(mp_optimise_value) == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE);
727 : : }
728 : : break;
729 [ + + ]: 3803824 : } else if (cmp < 0) {
730 : : // Table is sorted and comparison was less-than, so stop searching
731 : : break;
732 : : }
733 : : }
734 : :
735 [ + + + + : 264583 : } else if (is_digit(lex) || (is_char(lex, '.') && is_following_digit(lex))) {
+ + ]
736 : 29453 : bool forced_integer = false;
737 [ + + ]: 29453 : if (is_char(lex, '.')) {
738 : 2 : lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
739 : : } else {
740 : 29451 : lex->tok_kind = MP_TOKEN_INTEGER;
741 [ + + + + ]: 29451 : if (is_char(lex, '0') && is_following_base_char(lex)) {
742 : 1035 : forced_integer = true;
743 : : }
744 : : }
745 : :
746 : : // get first char
747 : 29453 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
748 : 29453 : next_char(lex);
749 : :
750 : : // get tail chars
751 [ + - ]: 78697 : while (!is_end(lex)) {
752 [ + + + + ]: 78697 : if (!forced_integer && is_char_or(lex, 'e', 'E')) {
753 : 194 : lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
754 : 194 : vstr_add_char(&lex->vstr, 'e');
755 : 194 : next_char(lex);
756 [ + - + + ]: 194 : if (is_char(lex, '+') || is_char(lex, '-')) {
757 : 110 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
758 : 110 : next_char(lex);
759 : : }
760 [ + + + + : 78503 : } else if (is_letter(lex) || is_digit(lex) || is_char(lex, '.')) {
+ + ]
761 [ + + ]: 48767 : if (is_char_or3(lex, '.', 'j', 'J')) {
762 : 1574 : lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
763 : : }
764 : 48767 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
765 : 48767 : next_char(lex);
766 [ + + ]: 29741 : } else if (is_char(lex, '_')) {
767 : 288 : next_char(lex);
768 : : } else {
769 : : break;
770 : : }
771 : : }
772 : :
773 : : } else {
774 : : // search for encoded delimiter or operator
775 : :
776 : : // assert that the token enum value fits in a byte, so they all fit in tok_enc_kind
777 : : MP_STATIC_ASSERT(MP_TOKEN_NUMBER_OF <= 256);
778 : :
779 : : const char *t = tok_enc;
780 : : size_t tok_enc_index = 0;
781 [ + + + + ]: 2490054 : for (; *t != 0 && !is_char(lex, *t); t += 1) {
782 [ + + ]: 2254924 : if (*t == 'e' || *t == 'c') {
783 : 841927 : t += 1;
784 : : }
785 : 2254924 : tok_enc_index += 1;
786 : : }
787 : :
788 : 235130 : next_char(lex);
789 : :
790 [ + + ]: 235129 : if (*t == 0) {
791 : : // didn't match any delimiter or operator characters
792 : 16 : lex->tok_kind = MP_TOKEN_INVALID;
793 : :
794 [ + + ]: 235113 : } else if (*t == '!') {
795 : : // "!=" is a special case because "!" is not a valid operator
796 [ + + ]: 391 : if (is_char(lex, '=')) {
797 : 383 : next_char(lex);
798 : 383 : lex->tok_kind = MP_TOKEN_OP_NOT_EQUAL;
799 : : } else {
800 : 8 : lex->tok_kind = MP_TOKEN_INVALID;
801 : : }
802 : :
803 [ + + ]: 234722 : } else if (*t == '.') {
804 : : // "." and "..." are special cases because ".." is not a valid operator
805 [ + + ]: 20521 : if (is_char_and(lex, '.', '.')) {
806 : 14 : next_char(lex);
807 : 14 : next_char(lex);
808 : 14 : lex->tok_kind = MP_TOKEN_ELLIPSIS;
809 : : } else {
810 : 20507 : lex->tok_kind = MP_TOKEN_DEL_PERIOD;
811 : : }
812 : :
813 : : } else {
814 : : // matched a delimiter or operator character
815 : :
816 : : // get the maximum characters for a valid token
817 : 214201 : t += 1;
818 : 214201 : size_t t_index = tok_enc_index;
819 [ + + ]: 266961 : while (*t == 'c' || *t == 'e') {
820 : 57153 : t_index += 1;
821 [ + + ]: 57153 : if (is_char(lex, t[1])) {
822 : 3414 : next_char(lex);
823 : 3415 : tok_enc_index = t_index;
824 [ + + ]: 3415 : if (*t == 'e') {
825 : : break;
826 : : }
827 [ + + ]: 53739 : } else if (*t == 'c') {
828 : : break;
829 : : }
830 : 52760 : t += 2;
831 : : }
832 : :
833 : : // set token kind
834 : 214202 : lex->tok_kind = tok_enc_kind[tok_enc_index];
835 : :
836 : : // compute bracket level for implicit line joining
837 [ + + + ]: 214202 : 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) {
838 : 67384 : lex->nested_bracket_level += 1;
839 : : } 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) {
840 : 67342 : lex->nested_bracket_level -= 1;
841 : : }
842 : : }
843 : : }
844 : 589621 : }
845 : :
846 : 4045 : mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) {
847 : 4045 : mp_lexer_t *lex = m_new_obj(mp_lexer_t);
848 : :
849 : 4044 : lex->source_name = src_name;
850 : 4044 : lex->reader = reader;
851 : 4044 : lex->line = 1;
852 : 4044 : lex->column = (size_t)-2; // account for 3 dummy bytes
853 : 4044 : lex->emit_dent = 0;
854 : 4044 : lex->nested_bracket_level = 0;
855 : 4044 : lex->alloc_indent_level = MICROPY_ALLOC_LEXER_INDENT_INIT;
856 : 4044 : lex->num_indent_level = 1;
857 : 4044 : lex->indent_level = m_new(uint16_t, lex->alloc_indent_level);
858 : 4045 : vstr_init(&lex->vstr, 32);
859 : : #if MICROPY_PY_FSTRINGS
860 : 4045 : vstr_init(&lex->fstring_args, 0);
861 : 4045 : lex->fstring_args_idx = 0;
862 : : #endif
863 : :
864 : : // store sentinel for first indentation level
865 : 4045 : lex->indent_level[0] = 0;
866 : :
867 : : // load lexer with start of file, advancing lex->column to 1
868 : : // start with dummy bytes and use next_char() for proper EOL/EOF handling
869 : 4045 : lex->chr0 = lex->chr1 = lex->chr2 = 0;
870 : 4045 : next_char(lex);
871 : 4045 : next_char(lex);
872 : 4045 : next_char(lex);
873 : :
874 : : // preload first token
875 : 4044 : mp_lexer_to_next(lex);
876 : :
877 : : // Check that the first token is in the first column unless it is a
878 : : // newline. Otherwise we convert the token kind to INDENT so that
879 : : // the parser gives a syntax error.
880 [ + + + + ]: 4043 : if (lex->tok_column != 1 && lex->tok_kind != MP_TOKEN_NEWLINE) {
881 : 4 : lex->tok_kind = MP_TOKEN_INDENT;
882 : : }
883 : :
884 : 4043 : return lex;
885 : : }
886 : :
887 : 1724 : mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len, size_t free_len) {
888 : 1724 : mp_reader_t reader;
889 : 1724 : mp_reader_new_mem(&reader, (const byte *)str, len, free_len);
890 : 1724 : return mp_lexer_new(src_name, reader);
891 : : }
892 : :
893 : : #if MICROPY_READER_POSIX || MICROPY_READER_VFS
894 : :
895 : 2324 : mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
896 : 2324 : mp_reader_t reader;
897 : 2324 : mp_reader_new_file(&reader, filename);
898 : 2320 : return mp_lexer_new(filename, reader);
899 : : }
900 : :
901 : : #if MICROPY_HELPER_LEXER_UNIX
902 : :
903 : 1 : mp_lexer_t *mp_lexer_new_from_fd(qstr filename, int fd, bool close_fd) {
904 : 1 : mp_reader_t reader;
905 : 1 : mp_reader_new_file_from_fd(&reader, fd, close_fd);
906 : 1 : return mp_lexer_new(filename, reader);
907 : : }
908 : :
909 : : #endif
910 : :
911 : : #endif
912 : :
913 : 4039 : void mp_lexer_free(mp_lexer_t *lex) {
914 [ + - ]: 4039 : if (lex) {
915 : 4039 : lex->reader.close(lex->reader.data);
916 : 4039 : vstr_clear(&lex->vstr);
917 : : #if MICROPY_PY_FSTRINGS
918 : 4039 : vstr_clear(&lex->fstring_args);
919 : : #endif
920 : 4039 : m_del(uint16_t, lex->indent_level, lex->alloc_indent_level);
921 : 4039 : m_del_obj(mp_lexer_t, lex);
922 : : }
923 : 4039 : }
924 : :
925 : : #if 0
926 : : // This function is used to print the current token and should only be
927 : : // needed to debug the lexer, so it's not available via a config option.
928 : : void mp_lexer_show_token(const mp_lexer_t *lex) {
929 : : 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);
930 : : if (lex->vstr.len > 0) {
931 : : const byte *i = (const byte *)lex->vstr.buf;
932 : : const byte *j = (const byte *)i + lex->vstr.len;
933 : : printf(" ");
934 : : while (i < j) {
935 : : unichar c = utf8_get_char(i);
936 : : i = utf8_next_char(i);
937 : : if (unichar_isprint(c)) {
938 : : printf("%c", (int)c);
939 : : } else {
940 : : printf("?");
941 : : }
942 : : }
943 : : }
944 : : printf("\n");
945 : : }
946 : : #endif
947 : :
948 : : #endif // MICROPY_ENABLE_COMPILER
|