Skip to content

Commit 72e1245

Browse files
committed
Provide actual support for template literals.
- Implement the lookahead and properly check the newlines. - However, that whole escape sequence check might have to be done _inside_ the token formation as this is still going to fail valid input templates such as `foo \ bar` when it will reduce to effectively `foo bar`, rather than a syntax error. Likewise for string literals.
1 parent 870a2ae commit 72e1245

File tree

3 files changed

+44
-17
lines changed

3 files changed

+44
-17
lines changed

src/calmjs/parse/lexers/es2015.py

Lines changed: 14 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,22 @@ class Lexer(ES5Lexer):
1414
"""
1515

1616
# Punctuators (ES6)
17-
t_ARROW = r'=>'
18-
t_SPREAD = r'\.\.\.'
19-
# this is now a right brace operator...
17+
# t_DOLLAR_LBRACE = r'${'
18+
# this is also a right brace punctuator...
2019
# t_RBRACE = r'}'
20+
t_ARROW = r'=>'
21+
t_SPREAD = r'\.\.\.'
22+
23+
tokens = ES5Lexer.tokens + (
24+
# ES2015 punctuators
25+
'ARROW', 'SPREAD', # => ...
26+
27+
# ES2015 terminal types
28+
'TEMPLATE',
29+
)
2130

22-
# TODO verify that the standard string rule will work.
23-
# TODO complete the actual implementation to make this actually
24-
# usable.
2531
template = r"""
26-
(?:` # opening backquote
32+
(?:(?:`|}) # opening ` or }
2733
(?: [^`\\] # no \, or `
2834
| \\[a-zA-Z!-\/:-@\[-`{-~] # or escaped characters
2935
| \\(\n|\r(?!\n)|\u2028|\u2029|\r\n) # or line continuation
@@ -32,17 +38,9 @@ class Lexer(ES5Lexer):
3238
| \\(?:[1-7][0-7]{0,2}|[0-7]{2,3}) # or octal_escape_sequence
3339
| \\0 # or <NUL> (15.10.2.11)
3440
)*? # zero or many times
35-
`) # closing backquote
41+
(?:`|\${)) # closing ` or ${
3642
""" # `
3743

38-
tokens = ES5Lexer.tokens + (
39-
# ES2015 punctuators
40-
'ARROW', 'SPREAD', # => ...
41-
42-
# ES2015 terminal types
43-
'TEMPLATE',
44-
)
45-
4644
@ply.lex.TOKEN(template)
4745
def t_TEMPLATE(self, token):
4846
# remove escape + new line sequence used for strings

src/calmjs/parse/tests/lexer.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -477,6 +477,35 @@
477477
'template_literal',
478478
('`foo`',
479479
['TEMPLATE `foo`']),
480+
), (
481+
'template_multiline',
482+
('`foo\nbar\r\nfoo`',
483+
['TEMPLATE `foo\nbar\r\nfoo`']),
484+
), (
485+
'template_other_newlines',
486+
('`foo\u2028\u2029foo`',
487+
['TEMPLATE `foo\u2028\u2029foo`']),
488+
), (
489+
'template_literal_with_dollar',
490+
('`foo$`',
491+
['TEMPLATE `foo$`']),
492+
), (
493+
'template_head_tail',
494+
(r'`hello ${name} while this`',
495+
['TEMPLATE `hello ${', 'ID name', 'TEMPLATE } while this`']),
496+
), (
497+
'template_empty_head_tail',
498+
(r'`${name}`',
499+
['TEMPLATE `${', 'ID name', 'TEMPLATE }`']),
500+
), (
501+
'template_nested',
502+
(r'`${`${a * 2}`} ${b}`',
503+
['TEMPLATE `${', 'TEMPLATE `${', 'ID a', 'MULT *', 'NUMBER 2',
504+
'TEMPLATE }`', 'TEMPLATE } ${', 'ID b', 'TEMPLATE }`']),
505+
), (
506+
'template_some_keywords',
507+
(r'`this -> ${this}.`',
508+
['TEMPLATE `this -> ${', 'THIS this', 'TEMPLATE }.`']),
480509
), (
481510
'template_literal_escape',
482511
(r'`f\`o`',

src/calmjs/parse/tests/test_es2015_lexer.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,5 +73,5 @@ def test_initial_template_character(self):
7373
run_lexer_pos, lexer_cls=Lexer), es5_pos_cases)
7474

7575
LexerES2015TestCase = build_equality_testcase(
76-
'LexerTestCase', partial(run_lexer, lexer_cls=Lexer), (
76+
'LexerES2015TestCase', partial(run_lexer, lexer_cls=Lexer), (
7777
(label, data[0], data[1],) for label, data in es2015_cases))

0 commit comments

Comments
 (0)