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 : 3080317 : static bool is_end(mp_lexer_t *lex) {
46 : 3080317 : return lex->chr0 == MP_LEXER_EOF;
47 : : }
48 : :
49 : 1629525 : static bool is_physical_newline(mp_lexer_t *lex) {
50 : 1629525 : return lex->chr0 == '\n';
51 : : }
52 : :
53 : 3763890 : static bool is_char(mp_lexer_t *lex, byte c) {
54 : 3763890 : return lex->chr0 == c;
55 : : }
56 : :
57 : 519137 : static bool is_char_or(mp_lexer_t *lex, byte c1, byte c2) {
58 [ + + + + ]: 519137 : return lex->chr0 == c1 || lex->chr0 == c2;
59 : : }
60 : :
61 : 46842 : static bool is_char_or3(mp_lexer_t *lex, byte c1, byte c2, byte c3) {
62 [ + + + + : 46842 : return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3;
+ - ]
63 : : }
64 : :
65 : : #if MICROPY_PY_FSTRINGS
66 : 435011 : static bool is_char_or4(mp_lexer_t *lex, byte c1, byte c2, byte c3, byte c4) {
67 [ + + + + : 435011 : return lex->chr0 == c1 || lex->chr0 == c2 || lex->chr0 == c3 || lex->chr0 == c4;
+ + + + ]
68 : : }
69 : : #endif
70 : :
71 : 2375 : static bool is_char_following(mp_lexer_t *lex, byte c) {
72 : 2375 : return lex->chr1 == c;
73 : : }
74 : :
75 : 27204 : static bool is_char_following_or(mp_lexer_t *lex, byte c1, byte c2) {
76 [ + + + + ]: 27204 : return lex->chr1 == c1 || lex->chr1 == c2;
77 : : }
78 : :
79 : 1201 : static bool is_char_following_following_or(mp_lexer_t *lex, byte c1, byte c2) {
80 [ + + + + ]: 1201 : return lex->chr2 == c1 || lex->chr2 == c2;
81 : : }
82 : :
83 : 2326782 : static bool is_char_and(mp_lexer_t *lex, byte c1, byte c2) {
84 [ + + + + ]: 2326782 : return lex->chr0 == c1 && lex->chr1 == c2;
85 : : }
86 : :
87 : 960448 : static bool is_whitespace(mp_lexer_t *lex) {
88 : 960448 : return unichar_isspace(lex->chr0);
89 : : }
90 : :
91 : 1258761 : static bool is_letter(mp_lexer_t *lex) {
92 : 1258761 : return unichar_isalpha(lex->chr0);
93 : : }
94 : :
95 : 491568 : static bool is_digit(mp_lexer_t *lex) {
96 : 491568 : return unichar_isdigit(lex->chr0);
97 : : }
98 : :
99 : 18459 : static bool is_following_digit(mp_lexer_t *lex) {
100 : 18459 : return unichar_isdigit(lex->chr1);
101 : : }
102 : :
103 : 5245 : static bool is_following_base_char(mp_lexer_t *lex) {
104 : 5245 : const unichar chr1 = lex->chr1 | 0x20;
105 [ + + + ]: 5245 : return chr1 == 'b' || chr1 == 'o' || chr1 == 'x';
106 : : }
107 : :
108 : 128 : static bool is_following_odigit(mp_lexer_t *lex) {
109 : 128 : return lex->chr1 >= '0' && lex->chr1 <= '7';
110 : : }
111 : :
112 : 450935 : static bool is_string_or_bytes(mp_lexer_t *lex) {
113 : 450935 : return is_char_or(lex, '\'', '\"')
114 : : #if MICROPY_PY_FSTRINGS
115 [ + + + + ]: 435013 : || (is_char_or4(lex, 'r', 'u', 'b', 'f') && is_char_following_or(lex, '\'', '\"'))
116 [ + + + + ]: 432750 : || (((is_char_and(lex, 'r', 'f') || is_char_and(lex, 'f', 'r'))
117 [ + - ]: 964 : && is_char_following_following_or(lex, '\'', '\"')))
118 : : #else
119 : : || (is_char_or3(lex, 'r', 'u', 'b') && is_char_following_or(lex, '\'', '\"'))
120 : : #endif
121 [ + + + + : 883685 : || ((is_char_and(lex, 'r', 'b') || is_char_and(lex, 'b', 'r'))
+ + ]
122 [ + + ]: 227 : && 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 : 1183798 : static bool is_head_of_identifier(mp_lexer_t *lex) {
127 [ + + + + : 1183798 : return is_letter(lex) || lex->chr0 == '_' || lex->chr0 >= 0x80;
+ + ]
128 : : }
129 : :
130 : 769052 : static bool is_tail_of_identifier(mp_lexer_t *lex) {
131 [ + + + + ]: 769052 : return is_head_of_identifier(lex) || is_digit(lex);
132 : : }
133 : :
134 : 2242859 : static void next_char(mp_lexer_t *lex) {
135 [ + + ]: 2242859 : if (lex->chr0 == '\n') {
136 : : // a new line
137 : 98494 : ++lex->line;
138 : 98494 : lex->column = 1;
139 [ + + ]: 2144365 : } 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 : 2144361 : ++lex->column;
145 : : }
146 : :
147 : : // shift the input queue forward
148 : 2242859 : lex->chr0 = lex->chr1;
149 : 2242859 : 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 [ + + ]: 2242859 : if (lex->fstring_args_idx) {
154 : : // if there are saved chars, then we're currently injecting fstring args
155 [ + + ]: 1505 : if (lex->fstring_args_idx < lex->fstring_args.len) {
156 : 1250 : lex->chr2 = lex->fstring_args.buf[lex->fstring_args_idx++];
157 : : } else {
158 : : // no more fstring arg bytes
159 : 255 : lex->chr2 = '\0';
160 : : }
161 : :
162 [ + + ]: 1505 : if (lex->chr0 == '\0') {
163 : : // consumed all fstring data, restore saved input queue
164 : 85 : lex->chr0 = lex->chr0_saved;
165 : 85 : lex->chr1 = lex->chr1_saved;
166 : 85 : lex->chr2 = lex->chr2_saved;
167 : : // stop consuming fstring arg data
168 : 85 : vstr_reset(&lex->fstring_args);
169 : 85 : lex->fstring_args_idx = 0;
170 : : }
171 : : } else
172 : : #endif
173 : : {
174 : 2241354 : lex->chr2 = lex->reader.readbyte(lex->reader.data);
175 : : }
176 : :
177 [ + + ]: 2242859 : 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 [ + + + + : 2242859 : if (lex->chr2 == MP_LEXER_EOF && lex->chr1 != MP_LEXER_EOF && lex->chr1 != '\n') {
+ + ]
188 : 1625 : lex->chr2 = '\n';
189 : : }
190 : 2242859 : }
191 : :
192 : 22179 : static void indent_push(mp_lexer_t *lex, size_t indent) {
193 [ + + ]: 22179 : 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 : 22179 : lex->indent_level[lex->num_indent_level++] = indent;
198 : 22179 : }
199 : :
200 : 109096 : static size_t indent_top(mp_lexer_t *lex) {
201 : 109096 : return lex->indent_level[lex->num_indent_level - 1];
202 : : }
203 : :
204 : 22179 : static void indent_pop(mp_lexer_t *lex) {
205 : 22179 : lex->num_indent_level -= 1;
206 : 22179 : }
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 : 2984 : static bool get_hex(mp_lexer_t *lex, size_t num_digits, mp_uint_t *result) {
300 : 2984 : mp_uint_t num = 0;
301 [ + + ]: 9028 : while (num_digits-- != 0) {
302 : 6060 : next_char(lex);
303 : 6060 : unichar c = CUR_CHAR(lex);
304 [ + + ]: 6060 : if (!unichar_isxdigit(c)) {
305 : : return false;
306 : : }
307 : 6044 : num = (num << 4) + unichar_xdigit_value(c);
308 : : }
309 : 2968 : *result = num;
310 : 2968 : return true;
311 : : }
312 : :
313 : 18190 : static void parse_string_literal(mp_lexer_t *lex, bool is_raw, bool is_fstring) {
314 : : // get first quoting character
315 : 18190 : char quote_char = '\'';
316 [ + + ]: 18190 : if (is_char(lex, '\"')) {
317 : 14404 : quote_char = '\"';
318 : : }
319 : 18190 : next_char(lex);
320 : :
321 : : // work out if it's a single or triple quoted literal
322 : 18190 : size_t num_quotes;
323 [ + + ]: 18190 : 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 : 18190 : size_t n_closing = 0;
334 : : #if MICROPY_PY_FSTRINGS
335 [ + + ]: 18190 : 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 : 93 : vstr_add_str(&lex->fstring_args, ".format(");
341 : : }
342 : : #endif
343 : :
344 [ + - + + : 160918 : while (!is_end(lex) && (num_quotes > 1 || !is_char(lex, '\n')) && n_closing < num_quotes) {
+ + + + ]
345 [ + + ]: 142730 : if (is_char(lex, quote_char)) {
346 : 18216 : n_closing += 1;
347 : 18216 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
348 : : } else {
349 : 124613 : n_closing = 0;
350 : :
351 : : #if MICROPY_PY_FSTRINGS
352 [ + + + + ]: 124613 : while (is_fstring && is_char(lex, '{')) {
353 : 99 : next_char(lex);
354 [ + + ]: 99 : 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 : 91 : vstr_add_byte(&lex->fstring_args, '(');
362 : : // remember the start of this argument (if we need it for f'{a=}').
363 : 91 : size_t i = lex->fstring_args.len;
364 : : // Extract characters inside the { until the bracket level
365 : : // is zero and we reach the conversion specifier '!',
366 : : // format specifier ':', or closing '}'. The conversion
367 : : // and format specifiers are left unchanged in the format
368 : : // string to be handled by str.format.
369 : : // (MicroPython limitation) note: this is completely
370 : : // unaware of Python syntax and will not handle any
371 : : // expression containing '}' or ':'. e.g. f'{"}"}' or f'
372 : : // {foo({})}'. However, detection of the '!' will
373 : : // specifically ensure that it's followed by [rs] and
374 : : // then either the format specifier or the closing
375 : : // brace. This allows the use of e.g. != in expressions.
376 : 91 : unsigned int nested_bracket_level = 0;
377 [ + - + + ]: 532 : while (!is_end(lex) && (nested_bracket_level != 0
378 [ + + ]: 472 : || !(is_char_or(lex, ':', '}')
379 [ + + ]: 393 : || (is_char(lex, '!')
380 [ + + ]: 20 : && is_char_following_or(lex, 'r', 's')
381 [ - + ]: 12 : && is_char_following_following_or(lex, ':', '}'))))
382 : : ) {
383 : 441 : unichar c = CUR_CHAR(lex);
384 [ + + ]: 441 : if (c == '[' || c == '{') {
385 : 12 : nested_bracket_level += 1;
386 [ + + ]: 429 : } else if (c == ']' || c == '}') {
387 : 12 : nested_bracket_level -= 1;
388 : : }
389 : : // like the default case at the end of this function, stay 8-bit clean
390 : 441 : vstr_add_byte(&lex->fstring_args, c);
391 : 441 : next_char(lex);
392 : : }
393 [ + + ]: 91 : if (lex->fstring_args.buf[lex->fstring_args.len - 1] == '=') {
394 : : // if the last character of the arg was '=', then inject "arg=" before the '{'.
395 : : // f'{a=}' --> 'a={}'.format(a)
396 : 18 : vstr_add_strn(&lex->vstr, lex->fstring_args.buf + i, lex->fstring_args.len - i);
397 : : // remove the trailing '='
398 : 18 : lex->fstring_args.len--;
399 : : }
400 : : // close the paren-wrapped arg to .format().
401 : 91 : vstr_add_byte(&lex->fstring_args, ')');
402 : : // comma-separate args to .format().
403 : 91 : vstr_add_byte(&lex->fstring_args, ',');
404 : : }
405 : 99 : vstr_add_byte(&lex->vstr, '{');
406 : : }
407 : : #endif
408 : :
409 [ + + ]: 124514 : if (is_char(lex, '\\')) {
410 : 3844 : next_char(lex);
411 : 3844 : unichar c = CUR_CHAR(lex);
412 [ + + ]: 3844 : if (is_raw) {
413 : : // raw strings allow escaping of quotes, but the backslash is also emitted
414 : 80 : vstr_add_char(&lex->vstr, '\\');
415 : : } else {
416 [ + + + + : 3764 : switch (c) {
+ + + + +
+ + + + ]
417 : : // note: "c" can never be MP_LEXER_EOF because next_char
418 : : // always inserts a newline at the end of the input stream
419 : : case '\n':
420 : : c = MP_LEXER_EOF;
421 : : break; // backslash escape the newline, just ignore it
422 : : case '\\':
423 : : break;
424 : : case '\'':
425 : : break;
426 : : case '"':
427 : : break;
428 : : case 'a':
429 : : c = 0x07;
430 : : break;
431 : : case 'b':
432 : : c = 0x08;
433 : : break;
434 : : case 't':
435 : : c = 0x09;
436 : : break;
437 : : case 'n':
438 : : c = 0x0a;
439 : : break;
440 : : case 'v':
441 : : c = 0x0b;
442 : : break;
443 : : case 'f':
444 : : c = 0x0c;
445 : : break;
446 : : case 'r':
447 : : c = 0x0d;
448 : : break;
449 : 28 : case 'u':
450 : : case 'U':
451 [ + + ]: 28 : if (lex->tok_kind == MP_TOKEN_BYTES) {
452 : : // b'\u1234' == b'\\u1234'
453 : 2 : vstr_add_char(&lex->vstr, '\\');
454 : 2 : break;
455 : : }
456 : : // Otherwise fall through.
457 : 2984 : MP_FALLTHROUGH
458 : : case 'x': {
459 : 2984 : mp_uint_t num = 0;
460 [ + - + + : 2994 : if (!get_hex(lex, (c == 'x' ? 2 : c == 'u' ? 4 : 8), &num)) {
+ + ]
461 : : // not enough hex chars for escape sequence
462 : 16 : lex->tok_kind = MP_TOKEN_INVALID;
463 : : }
464 : 2984 : c = num;
465 : 2984 : break;
466 : : }
467 : : case 'N':
468 : : // Supporting '\N{LATIN SMALL LETTER A}' == 'a' would require keeping the
469 : : // entire Unicode name table in the core. As of Unicode 6.3.0, that's nearly
470 : : // 3MB of text; even gzip-compressed and with minimal structure, it'll take
471 : : // roughly half a meg of storage. This form of Unicode escape may be added
472 : : // later on, but it's definitely not a priority right now. -- CJA 20140607
473 : 2 : mp_raise_NotImplementedError(MP_ERROR_TEXT("unicode name escapes"));
474 : 150 : break;
475 : 150 : default:
476 [ + + ]: 150 : if (c >= '0' && c <= '7') {
477 : : // Octal sequence, 1-3 chars
478 : 120 : size_t digits = 3;
479 : 120 : mp_uint_t num = c - '0';
480 [ + + + + ]: 128 : while (is_following_odigit(lex) && --digits != 0) {
481 : 8 : next_char(lex);
482 : 8 : num = num * 8 + (CUR_CHAR(lex) - '0');
483 : : }
484 : 120 : c = num;
485 : : } else {
486 : : // unrecognised escape character; CPython lets this through verbatim as '\' and then the character
487 : 30 : vstr_add_char(&lex->vstr, '\\');
488 : : }
489 : : break;
490 : : }
491 : : }
492 [ + - ]: 3216 : if (c != MP_LEXER_EOF) {
493 : : #if MICROPY_PY_BUILTINS_STR_UNICODE
494 [ + + + + ]: 3840 : if (c < 0x110000 && lex->tok_kind == MP_TOKEN_STRING) {
495 : : // Valid unicode character in a str object.
496 : 724 : vstr_add_char(&lex->vstr, c);
497 [ + - + + ]: 3114 : } else if (c < 0x100 && lex->tok_kind == MP_TOKEN_BYTES) {
498 : : // Valid byte in a bytes object.
499 : 3098 : vstr_add_byte(&lex->vstr, c);
500 : : }
501 : : #else
502 : : if (c < 0x100) {
503 : : // Without unicode everything is just added as an 8-bit byte.
504 : : vstr_add_byte(&lex->vstr, c);
505 : : }
506 : : #endif
507 : : else {
508 : : // Character out of range; this raises a generic SyntaxError.
509 : 18 : lex->tok_kind = MP_TOKEN_INVALID;
510 : : }
511 : : }
512 : : } else {
513 : : // Add the "character" as a byte so that we remain 8-bit clean.
514 : : // This way, strings are parsed correctly whether or not they contain utf-8 chars.
515 : 120670 : vstr_add_byte(&lex->vstr, CUR_CHAR(lex));
516 : : }
517 : : }
518 : 142729 : next_char(lex);
519 : : }
520 : :
521 : : // check we got the required end quotes
522 [ + + ]: 18188 : if (n_closing < num_quotes) {
523 : 20 : lex->tok_kind = MP_TOKEN_LONELY_STRING_OPEN;
524 : : }
525 : :
526 : : // cut off the end quotes from the token text
527 : 18188 : vstr_cut_tail_bytes(&lex->vstr, n_closing);
528 : 18188 : }
529 : :
530 : : // This function returns whether it has crossed a newline or not.
531 : : // It therefore always return true if stop_at_newline is true
532 : 637548 : static bool skip_whitespace(mp_lexer_t *lex, bool stop_at_newline) {
533 [ + + ]: 1137202 : while (!is_end(lex)) {
534 [ + + ]: 1128586 : if (is_physical_newline(lex)) {
535 [ + + + + ]: 168137 : if (stop_at_newline && lex->nested_bracket_level == 0) {
536 : : return true;
537 : : }
538 : 98386 : next_char(lex);
539 [ + + ]: 960449 : } else if (is_whitespace(lex)) {
540 : 389579 : next_char(lex);
541 [ + + ]: 570869 : } else if (is_char(lex, '#')) {
542 : 11645 : next_char(lex);
543 [ + - + + ]: 500941 : while (!is_end(lex) && !is_physical_newline(lex)) {
544 : 489296 : next_char(lex);
545 : : }
546 : : // will return true on next loop
547 [ + + ]: 559224 : } else if (is_char_and(lex, '\\', '\n')) {
548 : : // line-continuation, so don't return true
549 : 40 : next_char(lex);
550 : 40 : next_char(lex);
551 : : } else {
552 : : break;
553 : : }
554 : : }
555 : : return false;
556 : : }
557 : :
558 : 550134 : void mp_lexer_to_next(mp_lexer_t *lex) {
559 : : #if MICROPY_PY_FSTRINGS
560 [ + + + + ]: 550134 : if (lex->fstring_args.len && lex->fstring_args_idx == 0) {
561 : : // moving onto the next token means the literal string is complete.
562 : : // switch into injecting the format args.
563 : 93 : vstr_add_byte(&lex->fstring_args, ')');
564 : 93 : lex->chr0_saved = lex->chr0;
565 : 93 : lex->chr1_saved = lex->chr1;
566 : 93 : lex->chr2_saved = lex->chr2;
567 : 93 : lex->chr0 = lex->fstring_args.buf[0];
568 : 93 : lex->chr1 = lex->fstring_args.buf[1];
569 : 93 : lex->chr2 = lex->fstring_args.buf[2];
570 : : // we've already extracted 3 chars, but setting this non-zero also
571 : : // means we'll start consuming the fstring data
572 : 93 : lex->fstring_args_idx = 3;
573 : : }
574 : : #endif
575 : :
576 : : // start new token text
577 : 550134 : vstr_reset(&lex->vstr);
578 : :
579 : : // skip white space and comments
580 : : // set the newline tokens at the line and column of the preceding line:
581 : : // only advance on the pointer until a new line is crossed, save the
582 : : // line and column, and then readvance it
583 : 550134 : bool had_physical_newline = skip_whitespace(lex, true);
584 : :
585 : : // set token source information
586 : 550134 : lex->tok_line = lex->line;
587 : 550134 : lex->tok_column = lex->column;
588 : :
589 [ + + ]: 550134 : if (lex->emit_dent < 0) {
590 : 22175 : lex->tok_kind = MP_TOKEN_DEDENT;
591 : 22175 : lex->emit_dent += 1;
592 : :
593 [ + + ]: 527959 : } else if (lex->emit_dent > 0) {
594 : 22179 : lex->tok_kind = MP_TOKEN_INDENT;
595 : 22179 : lex->emit_dent -= 1;
596 : :
597 [ + + ]: 505780 : } else if (had_physical_newline) {
598 : : // The cursor is at the end of the previous line, pointing to a
599 : : // physical newline. Skip any remaining whitespace, comments, and
600 : : // newlines.
601 : 69227 : skip_whitespace(lex, false);
602 : :
603 : 69227 : lex->tok_kind = MP_TOKEN_NEWLINE;
604 : :
605 : 69227 : size_t num_spaces = lex->column - 1;
606 [ + + ]: 69227 : if (num_spaces == indent_top(lex)) {
607 [ + + ]: 39869 : } else if (num_spaces > indent_top(lex)) {
608 : 22179 : indent_push(lex, num_spaces);
609 : 22179 : lex->emit_dent += 1;
610 : : } else {
611 [ + + ]: 39869 : while (num_spaces < indent_top(lex)) {
612 : 22179 : indent_pop(lex);
613 : 22179 : lex->emit_dent -= 1;
614 : : }
615 [ + + ]: 17690 : if (num_spaces != indent_top(lex)) {
616 : 4 : lex->tok_kind = MP_TOKEN_DEDENT_MISMATCH;
617 : : }
618 : : }
619 : :
620 [ + + ]: 436553 : } else if (is_end(lex)) {
621 : 3804 : lex->tok_kind = MP_TOKEN_END;
622 : :
623 [ + + ]: 432749 : } else if (is_string_or_bytes(lex)) {
624 : : // a string or bytes literal
625 : :
626 : : // Python requires adjacent string/bytes literals to be automatically
627 : : // concatenated. We do it here in the tokeniser to make efficient use of RAM,
628 : : // because then the lexer's vstr can be used to accumulate the string literal,
629 : : // in contrast to creating a parse tree of strings and then joining them later
630 : : // in the compiler. It's also more compact in code size to do it here.
631 : :
632 : : // MP_TOKEN_END is used to indicate that this is the first string token
633 : 17996 : lex->tok_kind = MP_TOKEN_END;
634 : :
635 : : // Loop to accumulate string/bytes literals
636 : 18194 : do {
637 : : // parse type codes
638 : 18194 : bool is_raw = false;
639 : 18194 : bool is_fstring = false;
640 : 18194 : mp_token_kind_t kind = MP_TOKEN_STRING;
641 : 18194 : int n_char = 0;
642 [ + + ]: 18194 : if (is_char(lex, 'u')) {
643 : : n_char = 1;
644 [ + + ]: 18192 : } else if (is_char(lex, 'b')) {
645 : 2066 : kind = MP_TOKEN_BYTES;
646 : 2066 : n_char = 1;
647 [ + + ]: 2066 : if (is_char_following(lex, 'r')) {
648 : 2 : is_raw = true;
649 : 2 : n_char = 2;
650 : : }
651 [ + + ]: 16126 : } else if (is_char(lex, 'r')) {
652 : 108 : is_raw = true;
653 : 108 : n_char = 1;
654 [ + + ]: 108 : if (is_char_following(lex, 'b')) {
655 : 4 : kind = MP_TOKEN_BYTES;
656 : 4 : n_char = 2;
657 : : }
658 : : #if MICROPY_PY_FSTRINGS
659 [ - + ]: 108 : if (is_char_following(lex, 'f')) {
660 : : // raw-f-strings unsupported, immediately return (invalid) token.
661 : 0 : lex->tok_kind = MP_TOKEN_FSTRING_RAW;
662 : 0 : break;
663 : : }
664 : : #endif
665 : : }
666 : : #if MICROPY_PY_FSTRINGS
667 [ + + ]: 16018 : else if (is_char(lex, 'f')) {
668 [ - + ]: 93 : if (is_char_following(lex, 'r')) {
669 : : // raw-f-strings unsupported, immediately return (invalid) token.
670 : 0 : lex->tok_kind = MP_TOKEN_FSTRING_RAW;
671 : 0 : break;
672 : : }
673 : : n_char = 1;
674 : : is_fstring = true;
675 : : }
676 : : #endif
677 : :
678 : : // Set or check token kind
679 [ + + ]: 18194 : if (lex->tok_kind == MP_TOKEN_END) {
680 : 17996 : lex->tok_kind = kind;
681 [ + + ]: 198 : } else if (lex->tok_kind != kind) {
682 : : // Can't concatenate string with bytes
683 : : break;
684 : : }
685 : :
686 : : // Skip any type code characters
687 [ + + ]: 18190 : if (n_char != 0) {
688 : 2265 : next_char(lex);
689 [ + + ]: 2265 : if (n_char == 2) {
690 : 6 : next_char(lex);
691 : : }
692 : : }
693 : :
694 : : // Parse the literal
695 : 18190 : parse_string_literal(lex, is_raw, is_fstring);
696 : :
697 : : // Skip whitespace so we can check if there's another string following
698 : 18188 : skip_whitespace(lex, true);
699 : :
700 [ + + ]: 18188 : } while (is_string_or_bytes(lex));
701 : :
702 [ + + ]: 414753 : } else if (is_head_of_identifier(lex)) {
703 : 166301 : lex->tok_kind = MP_TOKEN_NAME;
704 : :
705 : : // get first char (add as byte to remain 8-bit clean and support utf-8)
706 : 166301 : vstr_add_byte(&lex->vstr, CUR_CHAR(lex));
707 : 166301 : next_char(lex);
708 : :
709 : : // get tail chars
710 [ + - + + ]: 769052 : while (!is_end(lex) && is_tail_of_identifier(lex)) {
711 : 602755 : vstr_add_byte(&lex->vstr, CUR_CHAR(lex));
712 : 602752 : next_char(lex);
713 : : }
714 : :
715 : : // Check if the name is a keyword.
716 : : // We also check for __debug__ here and convert it to its value. This is
717 : : // so the parser gives a syntax error on, eg, x.__debug__. Otherwise, we
718 : : // need to check for this special token in many places in the compiler.
719 : 166300 : const char *s = vstr_null_terminated_str(&lex->vstr);
720 [ + + ]: 3545162 : for (size_t i = 0; i < MP_ARRAY_SIZE(tok_kw); i++) {
721 : 3545006 : int cmp = strcmp(s, tok_kw[i]);
722 [ + + ]: 3545006 : if (cmp == 0) {
723 : 44416 : lex->tok_kind = MP_TOKEN_KW_FALSE + i;
724 [ + + ]: 44416 : if (lex->tok_kind == MP_TOKEN_KW___DEBUG__) {
725 [ + + ]: 18 : lex->tok_kind = (MP_STATE_VM(mp_optimise_value) == 0 ? MP_TOKEN_KW_TRUE : MP_TOKEN_KW_FALSE);
726 : : }
727 : : break;
728 [ + + ]: 3500590 : } else if (cmp < 0) {
729 : : // Table is sorted and comparison was less-than, so stop searching
730 : : break;
731 : : }
732 : : }
733 : :
734 [ + + + + : 248452 : } else if (is_digit(lex) || (is_char(lex, '.') && is_following_digit(lex))) {
+ + ]
735 : 28071 : bool forced_integer = false;
736 [ + + ]: 28071 : if (is_char(lex, '.')) {
737 : 2 : lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
738 : : } else {
739 : 28069 : lex->tok_kind = MP_TOKEN_INTEGER;
740 [ + + + + ]: 28069 : if (is_char(lex, '0') && is_following_base_char(lex)) {
741 : 913 : forced_integer = true;
742 : : }
743 : : }
744 : :
745 : : // get first char
746 : 28071 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
747 : 28071 : next_char(lex);
748 : :
749 : : // get tail chars
750 [ + - ]: 75163 : while (!is_end(lex)) {
751 [ + + + + ]: 75163 : if (!forced_integer && is_char_or(lex, 'e', 'E')) {
752 : 194 : lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
753 : 194 : vstr_add_char(&lex->vstr, 'e');
754 : 194 : next_char(lex);
755 [ + - + + ]: 194 : if (is_char(lex, '+') || is_char(lex, '-')) {
756 : 110 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
757 : 110 : next_char(lex);
758 : : }
759 [ + + + + : 74969 : } else if (is_letter(lex) || is_digit(lex) || is_char(lex, '.')) {
+ + ]
760 [ + + ]: 46842 : if (is_char_or3(lex, '.', 'j', 'J')) {
761 : 1551 : lex->tok_kind = MP_TOKEN_FLOAT_OR_IMAG;
762 : : }
763 : 46842 : vstr_add_char(&lex->vstr, CUR_CHAR(lex));
764 : 46842 : next_char(lex);
765 [ + + ]: 28127 : } else if (is_char(lex, '_')) {
766 : 56 : next_char(lex);
767 : : } else {
768 : : break;
769 : : }
770 : : }
771 : :
772 : : } else {
773 : : // search for encoded delimiter or operator
774 : :
775 : : const char *t = tok_enc;
776 : : size_t tok_enc_index = 0;
777 [ + + + + ]: 2289350 : for (; *t != 0 && !is_char(lex, *t); t += 1) {
778 [ + + ]: 2068968 : if (*t == 'e' || *t == 'c') {
779 : 767437 : t += 1;
780 : : }
781 : 2068968 : tok_enc_index += 1;
782 : : }
783 : :
784 : 220382 : next_char(lex);
785 : :
786 [ + + ]: 220383 : if (*t == 0) {
787 : : // didn't match any delimiter or operator characters
788 : 16 : lex->tok_kind = MP_TOKEN_INVALID;
789 : :
790 [ + + ]: 220367 : } else if (*t == '!') {
791 : : // "!=" is a special case because "!" is not a valid operator
792 [ + + ]: 373 : if (is_char(lex, '=')) {
793 : 365 : next_char(lex);
794 : 365 : lex->tok_kind = MP_TOKEN_OP_NOT_EQUAL;
795 : : } else {
796 : 8 : lex->tok_kind = MP_TOKEN_INVALID;
797 : : }
798 : :
799 [ + + ]: 219994 : } else if (*t == '.') {
800 : : // "." and "..." are special cases because ".." is not a valid operator
801 [ + + ]: 18457 : if (is_char_and(lex, '.', '.')) {
802 : 14 : next_char(lex);
803 : 14 : next_char(lex);
804 : 14 : lex->tok_kind = MP_TOKEN_ELLIPSIS;
805 : : } else {
806 : 18443 : lex->tok_kind = MP_TOKEN_DEL_PERIOD;
807 : : }
808 : :
809 : : } else {
810 : : // matched a delimiter or operator character
811 : :
812 : : // get the maximum characters for a valid token
813 : 201537 : t += 1;
814 : 201537 : size_t t_index = tok_enc_index;
815 [ + + ]: 250855 : while (*t == 'c' || *t == 'e') {
816 : 53518 : t_index += 1;
817 [ + + ]: 53518 : if (is_char(lex, t[1])) {
818 : 3283 : next_char(lex);
819 : 3284 : tok_enc_index = t_index;
820 [ + + ]: 3284 : if (*t == 'e') {
821 : : break;
822 : : }
823 [ + + ]: 50235 : } else if (*t == 'c') {
824 : : break;
825 : : }
826 : 49318 : t += 2;
827 : : }
828 : :
829 : : // set token kind
830 : 201538 : lex->tok_kind = tok_enc_kind[tok_enc_index];
831 : :
832 : : // compute bracket level for implicit line joining
833 [ + + + ]: 201538 : 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) {
834 : 63725 : lex->nested_bracket_level += 1;
835 : : } 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) {
836 : 63683 : lex->nested_bracket_level -= 1;
837 : : }
838 : : }
839 : : }
840 : 550135 : }
841 : :
842 : 3942 : mp_lexer_t *mp_lexer_new(qstr src_name, mp_reader_t reader) {
843 : 3942 : mp_lexer_t *lex = m_new_obj(mp_lexer_t);
844 : :
845 : 3942 : lex->source_name = src_name;
846 : 3942 : lex->reader = reader;
847 : 3942 : lex->line = 1;
848 : 3942 : lex->column = (size_t)-2; // account for 3 dummy bytes
849 : 3942 : lex->emit_dent = 0;
850 : 3942 : lex->nested_bracket_level = 0;
851 : 3942 : lex->alloc_indent_level = MICROPY_ALLOC_LEXER_INDENT_INIT;
852 : 3942 : lex->num_indent_level = 1;
853 : 3942 : lex->indent_level = m_new(uint16_t, lex->alloc_indent_level);
854 : 3942 : vstr_init(&lex->vstr, 32);
855 : : #if MICROPY_PY_FSTRINGS
856 : 3942 : vstr_init(&lex->fstring_args, 0);
857 : 3942 : lex->fstring_args_idx = 0;
858 : : #endif
859 : :
860 : : // store sentinel for first indentation level
861 : 3942 : lex->indent_level[0] = 0;
862 : :
863 : : // load lexer with start of file, advancing lex->column to 1
864 : : // start with dummy bytes and use next_char() for proper EOL/EOF handling
865 : 3942 : lex->chr0 = lex->chr1 = lex->chr2 = 0;
866 : 3942 : next_char(lex);
867 : 3942 : next_char(lex);
868 : 3942 : next_char(lex);
869 : :
870 : : // preload first token
871 : 3942 : mp_lexer_to_next(lex);
872 : :
873 : : // Check that the first token is in the first column unless it is a
874 : : // newline. Otherwise we convert the token kind to INDENT so that
875 : : // the parser gives a syntax error.
876 [ + + + + ]: 3940 : if (lex->tok_column != 1 && lex->tok_kind != MP_TOKEN_NEWLINE) {
877 : 4 : lex->tok_kind = MP_TOKEN_INDENT;
878 : : }
879 : :
880 : 3940 : return lex;
881 : : }
882 : :
883 : 1724 : mp_lexer_t *mp_lexer_new_from_str_len(qstr src_name, const char *str, size_t len, size_t free_len) {
884 : 1724 : mp_reader_t reader;
885 : 1724 : mp_reader_new_mem(&reader, (const byte *)str, len, free_len);
886 : 1724 : return mp_lexer_new(src_name, reader);
887 : : }
888 : :
889 : : #if MICROPY_READER_POSIX || MICROPY_READER_VFS
890 : :
891 : 2221 : mp_lexer_t *mp_lexer_new_from_file(qstr filename) {
892 : 2221 : mp_reader_t reader;
893 : 2221 : mp_reader_new_file(&reader, filename);
894 : 2217 : return mp_lexer_new(filename, reader);
895 : : }
896 : :
897 : : #if MICROPY_HELPER_LEXER_UNIX
898 : :
899 : 1 : mp_lexer_t *mp_lexer_new_from_fd(qstr filename, int fd, bool close_fd) {
900 : 1 : mp_reader_t reader;
901 : 1 : mp_reader_new_file_from_fd(&reader, fd, close_fd);
902 : 1 : return mp_lexer_new(filename, reader);
903 : : }
904 : :
905 : : #endif
906 : :
907 : : #endif
908 : :
909 : 3936 : void mp_lexer_free(mp_lexer_t *lex) {
910 [ + - ]: 3936 : if (lex) {
911 : 3936 : lex->reader.close(lex->reader.data);
912 : 3936 : vstr_clear(&lex->vstr);
913 : : #if MICROPY_PY_FSTRINGS
914 : 3935 : vstr_clear(&lex->fstring_args);
915 : : #endif
916 : 3936 : m_del(uint16_t, lex->indent_level, lex->alloc_indent_level);
917 : 3936 : m_del_obj(mp_lexer_t, lex);
918 : : }
919 : 3936 : }
920 : :
921 : : #if 0
922 : : // This function is used to print the current token and should only be
923 : : // needed to debug the lexer, so it's not available via a config option.
924 : : void mp_lexer_show_token(const mp_lexer_t *lex) {
925 : : 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);
926 : : if (lex->vstr.len > 0) {
927 : : const byte *i = (const byte *)lex->vstr.buf;
928 : : const byte *j = (const byte *)i + lex->vstr.len;
929 : : printf(" ");
930 : : while (i < j) {
931 : : unichar c = utf8_get_char(i);
932 : : i = utf8_next_char(i);
933 : : if (unichar_isprint(c)) {
934 : : printf("%c", (int)c);
935 : : } else {
936 : : printf("?");
937 : : }
938 : : }
939 : : }
940 : : printf("\n");
941 : : }
942 : : #endif
943 : :
944 : : #endif // MICROPY_ENABLE_COMPILER
|