fix grammar for multiline quoted strings to allow escaped whitespace on closing line

This commit is contained in:
Kat Marchán 2024-12-15 02:02:18 -08:00
parent 5d6f755832
commit 65a06289b4
No known key found for this signature in database
GPG Key ID: AEB529C08A3C7E9E
6 changed files with 39 additions and 23 deletions

46
SPEC.md
View File

@ -577,13 +577,14 @@ multi-line """[\n]
#### Interaction with Whitespace Escapes #### Interaction with Whitespace Escapes
Multi-line strings support the same mechanism for escaping whitespace Multi-line strings support the same mechanism for escaping whitespace as Quoted
as Quoted Strings. Strings.
When processing a Multi-line String, implementations MUST dedent the string _after_
resolving all whitespace escapes, but _before_ resolving other backslash escapes. When processing a Multi-line String, implementations MUST dedent the string
Furthermore, a whitespace escape that attempts to escape the final line's newline _after_ resolving all whitespace escapes, but _before_ resolving other backslash
and/or whitespace prefix is invalid since the multi-line string has to still be escapes. Furthermore, a whitespace escape that attempts to escape the final
valid with the escaped whitespace removed. line's newline and/or whitespace prefix is invalid since the multi-line string
has to still be valid with the escaped whitespace removed.
For example, the following example is illegal: For example, the following example is illegal:
@ -612,20 +613,19 @@ bar
### Raw String ### Raw String
Both [Quoted](#quoted-string) and [Multi-Line Strings](#multi-line-string) Both [Quoted](#quoted-string) and [Multi-Line Strings](#multi-line-string) have
have Raw String variants, Raw String variants, which are identical in syntax except they do not support
which are identical in syntax except they do not support `\`-escapes. `\`-escapes. This includes line-continuation escapes (`\` + `ws` collapsing to
They otherwise share the same properties as far as nothing). They otherwise share the same properties as far as literal
literal [Newline](#newline) characters go, multi-line rules, and the requirement [Newline](#newline) characters go, multi-line rules, and the requirement of
of UTF-8 representation. UTF-8 representation.
The Raw String variants are indicated by preceding the strings's opening quotes The Raw String variants are indicated by preceding the strings's opening quotes
with one or more `#` characters. with one or more `#` characters. The string is then closed by its normal closing
The string is then closed by its normal closing quotes, quotes, followed by a _matching_ number of `#` characters. This means that the
followed by a _matching_ number of `#` characters. string may contain any combination of `"` and `#` characters other than its
This means that the string may contain any combination of `"` and `#` characters closing delimiter (e.g., if a raw string starts with `##"`, it can contain `"`
other than its closing delimiter (e.g., if a raw string starts with `##"`, it can or `"#`, but not `"##` or `"###`).
contain `"` or `"#`, but not `"##` or `"###`).
Like other Strings, Raw Strings _MUST NOT_ include any of the [disallowed Like other Strings, Raw Strings _MUST NOT_ include any of the [disallowed
literal code-points](#disallowed-literal-code-points) as code points in their literal code-points](#disallowed-literal-code-points) as code points in their
@ -865,15 +865,15 @@ dotted-ident := sign? '.' ((identifier-char - digit) identifier-char*)?
identifier-char := unicode - unicode-space - newline - [\\/(){};\[\]"#=] - disallowed-literal-code-points - equals-sign identifier-char := unicode - unicode-space - newline - [\\/(){};\[\]"#=] - disallowed-literal-code-points - equals-sign
disallowed-keyword-identifiers := 'true' - 'false' - 'null' - 'inf' - '-inf' - 'nan' disallowed-keyword-identifiers := 'true' - 'false' - 'null' - 'inf' - '-inf' - 'nan'
quoted-string := '"' single-line-string-body '"' | '"""' newline multi-line-string-body newline unicode-space* '"""' quoted-string := '"' single-line-string-body '"' | '"""' newline multi-line-string-body newline (unicode-space | ws-escape)* '"""'
single-line-string-body := (string-character - newline)* single-line-string-body := (string-character - newline)*
multi-line-string-body := (('"' | '""')? string-character)* multi-line-string-body := (('"' | '""')? string-character)*
string-character := '\' escape | [^\\"] - disallowed-literal-code-points string-character := ('\' ["\\bfnrts] | 'u{' hex-digit{1, 6} '}') | ws-escape | [^\\"] - disallowed-literal-code-points
escape := ["\\bfnrts] | 'u{' hex-digit{1, 6} '}' | (unicode-space | newline)+ ws-escape := '\' (unicode-space | newline)+
hex-digit := [0-9a-fA-F] hex-digit := [0-9a-fA-F]
raw-string := '#' raw-string-quotes '#' | '#' raw-string '#' raw-string := '#' raw-string-quotes '#' | '#' raw-string '#'
raw-string-quotes := '"' single-line-raw-string-body '"' | '"""' newline multi-line-raw-string-body '"""' raw-string-quotes := '"' single-line-raw-string-body '"' | '"""' newline multi-line-raw-string-body newline '"""'
single-line-raw-string-body := '' | (single-line-raw-string-char - '"') single-line-raw-string-char*? | '"' (single-line-raw-string-char - '"') single-line-raw-string-char*? single-line-raw-string-body := '' | (single-line-raw-string-char - '"') single-line-raw-string-char*? | '"' (single-line-raw-string-char - '"') single-line-raw-string-char*?
single-line-raw-string-char := unicode - newline - disallowed-literal-code-points single-line-raw-string-char := unicode - newline - disallowed-literal-code-points
multi-line-raw-string-body := (unicode - disallowed-literal-code-points)*? multi-line-raw-string-body := (unicode - disallowed-literal-code-points)*?

View File

@ -0,0 +1 @@
node "foo bar\nbaz"

View File

@ -0,0 +1 @@
node " foo bar\n baz"

View File

@ -0,0 +1,5 @@
node """
foo \
bar
baz
\ """

View File

@ -0,0 +1,5 @@
node """
foo \
bar
baz
\ """

View File

@ -0,0 +1,4 @@
node """
foo
bar\
"""