Skip to content

Commit d8f9e69

Browse files
koxudaxiamaanq
andcommitted
feat: add PEP 750 template string support
Co-authored-by: Amaan Qureshi <[email protected]>
1 parent 7ff26da commit d8f9e69

File tree

2 files changed

+82
-8
lines changed

2 files changed

+82
-8
lines changed

src/scanner.c

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ static inline void set_end_character(Delimiter *delimiter, int32_t character) {
8585
typedef struct {
8686
Array(uint16_t) indents;
8787
Array(Delimiter) delimiters;
88-
bool inside_f_string;
88+
bool inside_interpolated_string;
8989
} Scanner;
9090

9191
static inline void advance(TSLexer *lexer) { lexer->advance(lexer, false); }
@@ -177,7 +177,7 @@ bool tree_sitter_python_external_scanner_scan(void *payload, TSLexer *lexer, con
177177
lexer->mark_end(lexer);
178178
array_pop(&scanner->delimiters);
179179
lexer->result_symbol = STRING_END;
180-
scanner->inside_f_string = false;
180+
scanner->inside_interpolated_string = false;
181181
}
182182
return true;
183183
}
@@ -195,7 +195,7 @@ bool tree_sitter_python_external_scanner_scan(void *payload, TSLexer *lexer, con
195195
advance(lexer);
196196
array_pop(&scanner->delimiters);
197197
lexer->result_symbol = STRING_END;
198-
scanner->inside_f_string = false;
198+
scanner->inside_interpolated_string = false;
199199
}
200200
lexer->mark_end(lexer);
201201
return true;
@@ -280,7 +280,7 @@ bool tree_sitter_python_external_scanner_scan(void *payload, TSLexer *lexer, con
280280
if ((valid_symbols[DEDENT] ||
281281
(!valid_symbols[NEWLINE] && !(valid_symbols[STRING_START] && next_tok_is_string_start) &&
282282
!within_brackets)) &&
283-
indent_length < current_indent_length && !scanner->inside_f_string &&
283+
indent_length < current_indent_length && !scanner->inside_interpolated_string &&
284284

285285
// Wait to create a dedent token until we've consumed any
286286
// comments
@@ -303,7 +303,8 @@ bool tree_sitter_python_external_scanner_scan(void *payload, TSLexer *lexer, con
303303

304304
bool has_flags = false;
305305
while (lexer->lookahead) {
306-
if (lexer->lookahead == 'f' || lexer->lookahead == 'F') {
306+
if (lexer->lookahead == 'f' || lexer->lookahead == 'F' || lexer->lookahead == 't' ||
307+
lexer->lookahead == 'T') {
307308
set_format(&delimiter);
308309
} else if (lexer->lookahead == 'r' || lexer->lookahead == 'R') {
309310
set_raw(&delimiter);
@@ -349,7 +350,7 @@ bool tree_sitter_python_external_scanner_scan(void *payload, TSLexer *lexer, con
349350
if (end_character(&delimiter)) {
350351
array_push(&scanner->delimiters, delimiter);
351352
lexer->result_symbol = STRING_START;
352-
scanner->inside_f_string = is_format(&delimiter);
353+
scanner->inside_interpolated_string = is_format(&delimiter);
353354
return true;
354355
}
355356
if (has_flags) {
@@ -365,7 +366,7 @@ unsigned tree_sitter_python_external_scanner_serialize(void *payload, char *buff
365366

366367
size_t size = 0;
367368

368-
buffer[size++] = (char)scanner->inside_f_string;
369+
buffer[size++] = (char)scanner->inside_interpolated_string;
369370

370371
size_t delimiter_count = scanner->delimiters.size;
371372
if (delimiter_count > UINT8_MAX) {
@@ -398,7 +399,7 @@ void tree_sitter_python_external_scanner_deserialize(void *payload, const char *
398399
if (length > 0) {
399400
size_t size = 0;
400401

401-
scanner->inside_f_string = (bool)buffer[size++];
402+
scanner->inside_interpolated_string = (bool)buffer[size++];
402403

403404
size_t delimiter_count = (uint8_t)buffer[size++];
404405
if (delimiter_count > 0) {

test/corpus/literals.txt

Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -553,6 +553,79 @@ f"{value:{width + padding!r}.{precision}}"
553553
(identifier))))
554554
(string_end))))
555555

556+
================================================================================
557+
Template Strings
558+
================================================================================
559+
560+
t"Hello, {first_name} {last_name}!"
561+
t"a {b:2} {c:34.5}"
562+
tr"Path: {path}\n"
563+
t"""
564+
Multi-line template
565+
with {variable}
566+
"""
567+
t"Use {{braces}} to escape"
568+
t"Result: {a + b}"
569+
570+
--------------------------------------------------------------------------------
571+
572+
(module
573+
(expression_statement
574+
(string
575+
(string_start)
576+
(string_content)
577+
(interpolation
578+
(identifier))
579+
(string_content)
580+
(interpolation
581+
(identifier))
582+
(string_content)
583+
(string_end)))
584+
(expression_statement
585+
(string
586+
(string_start)
587+
(string_content)
588+
(interpolation
589+
(identifier)
590+
(format_specifier))
591+
(string_content)
592+
(interpolation
593+
(identifier)
594+
(format_specifier))
595+
(string_end)))
596+
(expression_statement
597+
(string
598+
(string_start)
599+
(string_content)
600+
(interpolation
601+
(identifier))
602+
(string_content)
603+
(string_end)))
604+
(expression_statement
605+
(string
606+
(string_start)
607+
(string_content)
608+
(interpolation
609+
(identifier))
610+
(string_content)
611+
(string_end)))
612+
(expression_statement
613+
(string
614+
(string_start)
615+
(string_content
616+
(escape_interpolation)
617+
(escape_interpolation))
618+
(string_end)))
619+
(expression_statement
620+
(string
621+
(string_start)
622+
(string_content)
623+
(interpolation
624+
(binary_operator
625+
(identifier)
626+
(identifier)))
627+
(string_end))))
628+
556629
================================================================================
557630
Unicode escape sequences
558631
================================================================================

0 commit comments

Comments
 (0)