Escape newlines in heredocs with backslashes

This commit is contained in:
xixixao 2013-11-24 18:37:11 +00:00
parent e3e8b1c501
commit 35d327a304
3 changed files with 85 additions and 14 deletions

View File

@ -767,10 +767,17 @@
};
Lexer.prototype.escapeLines = function(str, heredoc) {
str = str.replace(/\\[^\S\n]*(\n|\\)\s*/g, function(escaped, character) {
if (character === '\n') {
return '';
} else {
return escaped;
}
});
if (heredoc) {
return str.replace(MULTILINER, '\\n');
} else {
return str.replace(/((^|[^\\])(\\\\)+)\n/g, '$1 \\\n').replace(/\\\s*\n\s*/g, '').replace(/\s*\n\s*/g, ' ');
return str.replace(/\s*\n\s*/g, ' ');
}
};
@ -778,8 +785,8 @@
if (!body) {
return quote + quote;
}
body = body.replace(/\\([\s\S])/g, function(match, contents) {
if (contents === quote || heredoc && contents === '\n') {
body = body.replace(RegExp("\\\\(" + quote + "|\\\\)", "g"), function(match, contents) {
if (contents === quote) {
return contents;
} else {
return match;

View File

@ -691,18 +691,20 @@ exports.Lexer = class Lexer
# Converts newlines for string literals.
escapeLines: (str, heredoc) ->
# Ignore escaped backslashes and remove escaped newlines
str = str.replace /\\[^\S\n]*(\n|\\)\s*/g, (escaped, character) ->
if character is '\n' then '' else escaped
if heredoc
str.replace MULTILINER, '\\n'
else
str.replace(/((^|[^\\])(\\\\)+)\n/g, '$1 \\\n') # escaped backslashes
.replace(/\\\s*\n\s*/g, '') # backslash at EOL
.replace(/\s*\n\s*/g, ' ')
str.replace /\s*\n\s*/g, ' '
# Constructs a string token by escaping quotes and newlines.
makeString: (body, quote, heredoc) ->
return quote + quote unless body
body = body.replace /\\([\s\S])/g, (match, contents) ->
if contents is quote or heredoc and contents is '\n' then contents else match
# Ignore escaped backslashes and unescape quotes
body = body.replace /// \\( #{quote} | \\ ) ///g, (match, contents) ->
if contents is quote then contents else match
body = body.replace /// #{quote} ///g, '\\$&'
quote + @escapeLines(body, heredoc) + quote

View File

@ -42,6 +42,8 @@ test "#3229, multiline strings", ->
indentation
doesn\'t
matter', 'indentation doesn\'t matter'
eq 'trailing ws
doesn\'t matter', 'trailing ws doesn\'t matter'
# Use backslashes at the end of a line to specify whitespace between lines.
eq 'a \
@ -72,6 +74,7 @@ test "#3229, multiline strings", ->
}", "a string inside interpolation"
# Handle escaped backslashes correctly.
eq '\\', `'\\'`
eq 'escaped backslash at EOL\\
next line', 'escaped backslash at EOL\\ next line'
eq '\\
@ -84,8 +87,10 @@ test "#3229, multiline strings", ->
next line', 'triple backslash\\next line'
eq 'several escaped backslashes\\\\\\
ok', 'several escaped backslashes\\\\\\ ok'
eq 'several escaped backslashes\\\\\\\
ok', 'several escaped backslashes\\\\\\ok'
eq 'several escaped backslashes slash\\\\\\\
ok', 'several escaped backslashes slash\\\\\\ok'
eq 'several escaped backslashes with trailing ws \\\\\\
ok', 'several escaped backslashes with trailing ws \\\\\\ ok'
# Backslashes at beginning of lines.
eq 'first line
@ -100,6 +105,67 @@ test "#3229, multiline strings", ->
backslash', 'lone backslash'
test "#3249, escape newlines in heredocs with backslashes", ->
# Ignore escaped newlines
eq '''
Set whitespace \
<- this is ignored\
none
normal indentation
''', 'Set whitespace <- this is ignorednone\n normal indentation'
eq """
Set whitespace \
<- this is ignored\
none
normal indentation
""", 'Set whitespace <- this is ignorednone\n normal indentation'
# Changed from #647
eq '''
Hello, World\
''', 'Hello, World'
# Backslash at the beginning of a literal string.
eq '''\
ok''', 'ok'
eq ''' \
ok''', ' ok'
# Same behavior in interpolated strings.
eq """
interpolation #{1}
follows #{2} \
too #{3}\
!
""", 'interpolation 1\n follows 2 too 3!'
# TODO: uncomment when #2388 is fixed
# eq """a heredoc #{
# "inside \
# interpolation"
# }""", "a heredoc inside interpolation"
# Handle escaped backslashes correctly.
eq '''
escaped backslash at EOL\\
next line
''', 'escaped backslash at EOL\\\n next line'
# Backslashes at beginning of lines.
eq '''first line
\ backslash at BOL''', 'first line\n\ backslash at BOL'
eq """first line\
\ backslash at BOL""", 'first line\ backslash at BOL'
# Edge case.
eq '''lone
\
backslash''', 'lone\n\n backslash'
#647
eq "''Hello, World\\''", '''
@ -108,10 +174,6 @@ eq "''Hello, World\\''", '''
eq '""Hello, World\\""', """
"\"Hello, World\\\""
"""
eq 'Hello, World\n', '''
Hello, World\
'''
a = """
basic heredoc