Skip to content

Commit 1ddc13e

Browse files
Martin JambonMartin Jambon
authored andcommitted
Tolerate unescaped newlines in string literals
1 parent c4f5c8f commit 1ddc13e

File tree

5 files changed

+21655
-21576
lines changed

5 files changed

+21655
-21576
lines changed

grammar.js

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ module.exports = grammar({
6161
$._jsx_attribute_value,
6262
$._jsx_identifier,
6363
$._lhs_expression,
64+
$._string,
6465
],
6566

6667
conflicts: $ => [
@@ -568,7 +569,7 @@ module.exports = grammar({
568569
),
569570

570571
_jsx_attribute_value: $ => choice(
571-
$.string,
572+
$.jsx_string,
572573
$.jsx_expression,
573574
$._jsx_element,
574575
$.jsx_fragment
@@ -804,25 +805,34 @@ module.exports = grammar({
804805
// Primitives
805806
//
806807

807-
string: $ => choice(
808+
// Here we tolerate unescaped newlines in double-quoted and
809+
// single-quoted string literals.
810+
// This is legal in typescript as jsx/tsx attribute values (as of
811+
// 2020), and perhaps will be valid in javascript as well in the
812+
// future.
813+
//
814+
_string: $ => choice(
808815
seq(
809816
'"',
810817
repeat(choice(
811-
token.immediate(prec(PREC.STRING, /[^"\\\n]+|\\\r?\n/)),
818+
token.immediate(prec(PREC.STRING, /[^"\\\n]+|\\?\r?\n/)),
812819
$.escape_sequence
813820
)),
814821
'"'
815822
),
816823
seq(
817824
"'",
818825
repeat(choice(
819-
token.immediate(prec(PREC.STRING, /[^'\\\n]+|\\\r?\n/)),
826+
token.immediate(prec(PREC.STRING, /[^'\\\n]+|\\?\r?\n/)),
820827
$.escape_sequence
821828
)),
822829
"'"
823830
)
824831
),
825832

833+
string: $ => $._string,
834+
jsx_string: $ => $._string,
835+
826836
escape_sequence: $ => token.immediate(seq(
827837
'\\',
828838
choice(

src/grammar.json

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2337,7 +2337,7 @@
23372337
"members": [
23382338
{
23392339
"type": "SYMBOL",
2340-
"name": "string"
2340+
"name": "jsx_string"
23412341
},
23422342
{
23432343
"type": "SYMBOL",
@@ -4411,7 +4411,7 @@
44114411
]
44124412
}
44134413
},
4414-
"string": {
4414+
"_string": {
44154415
"type": "CHOICE",
44164416
"members": [
44174417
{
@@ -4433,7 +4433,7 @@
44334433
"value": 2,
44344434
"content": {
44354435
"type": "PATTERN",
4436-
"value": "[^\"\\\\\\n]+|\\\\\\r?\\n"
4436+
"value": "[^\"\\\\\\n]+|\\\\?\\r?\\n"
44374437
}
44384438
}
44394439
},
@@ -4469,7 +4469,7 @@
44694469
"value": 2,
44704470
"content": {
44714471
"type": "PATTERN",
4472-
"value": "[^'\\\\\\n]+|\\\\\\r?\\n"
4472+
"value": "[^'\\\\\\n]+|\\\\?\\r?\\n"
44734473
}
44744474
}
44754475
},
@@ -4488,6 +4488,14 @@
44884488
}
44894489
]
44904490
},
4491+
"string": {
4492+
"type": "SYMBOL",
4493+
"name": "_string"
4494+
},
4495+
"jsx_string": {
4496+
"type": "SYMBOL",
4497+
"name": "_string"
4498+
},
44914499
"escape_sequence": {
44924500
"type": "IMMEDIATE_TOKEN",
44934501
"content": {
@@ -5981,7 +5989,8 @@
59815989
"_jsx_attribute_name",
59825990
"_jsx_attribute_value",
59835991
"_jsx_identifier",
5984-
"_lhs_expression"
5992+
"_lhs_expression",
5993+
"_string"
59855994
],
59865995
"supertypes": [
59875996
"_statement",

src/node-types.json

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1488,11 +1488,11 @@
14881488
"named": true
14891489
},
14901490
{
1491-
"type": "property_identifier",
1491+
"type": "jsx_string",
14921492
"named": true
14931493
},
14941494
{
1495-
"type": "string",
1495+
"type": "property_identifier",
14961496
"named": true
14971497
}
14981498
]
@@ -1719,6 +1719,21 @@
17191719
}
17201720
}
17211721
},
1722+
{
1723+
"type": "jsx_string",
1724+
"named": true,
1725+
"fields": {},
1726+
"children": {
1727+
"multiple": true,
1728+
"required": false,
1729+
"types": [
1730+
{
1731+
"type": "escape_sequence",
1732+
"named": true
1733+
}
1734+
]
1735+
}
1736+
},
17221737
{
17231738
"type": "labeled_statement",
17241739
"named": true,

0 commit comments

Comments
 (0)