Fixed leading whitespace before interpolation in simple strings

This commit is contained in:
xixixao 2013-11-27 20:29:45 +00:00
parent b11d956d53
commit a61b6ee925
3 changed files with 44 additions and 38 deletions

View File

@ -166,30 +166,25 @@
};
Lexer.prototype.stringToken = function() {
var match, octalEsc, string;
switch (this.chunk.charAt(0)) {
var octalEsc, quote, string, trimmed;
switch (quote = this.chunk.charAt(0)) {
case "'":
if (!(match = SIMPLESTR.exec(this.chunk))) {
return 0;
}
string = match[0];
this.token('STRING', this.escapeLines(string), 0, string.length);
string = SIMPLESTR.exec(this.chunk)[0];
break;
case '"':
if (!(string = this.balancedString(this.chunk, '"'))) {
return 0;
}
if (0 < string.indexOf('#{', 1)) {
this.interpolateString(string.slice(1, -1), {
strOffset: 1,
lexedLength: string.length
});
} else {
this.token('STRING', this.escapeLines(string), 0, string.length);
}
break;
default:
return 0;
string = this.balancedString(this.chunk, '"');
}
if (!string) {
return 0;
}
trimmed = this.removeNewlines(string.slice(1, -1));
if (quote === '"' && 0 < string.indexOf('#{', 1)) {
this.interpolateString(trimmed, {
strOffset: 1,
lexedLength: string.length
});
} else {
this.token('STRING', quote + this.escapeLines(trimmed) + quote, 0, string.length);
}
if (octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test(string)) {
this.error("octal escape sequences " + string + " are not allowed");
@ -763,6 +758,10 @@
return LINE_CONTINUER.test(this.chunk) || ((_ref2 = this.tag()) === '\\' || _ref2 === '.' || _ref2 === '?.' || _ref2 === '?::' || _ref2 === 'UNARY' || _ref2 === 'MATH' || _ref2 === '+' || _ref2 === '-' || _ref2 === 'SHIFT' || _ref2 === 'RELATION' || _ref2 === 'COMPARE' || _ref2 === 'LOGIC' || _ref2 === 'THROW' || _ref2 === 'EXTENDS');
};
Lexer.prototype.removeNewlines = function(str) {
return str.replace(/^\s*\n\s*/, '').replace(/([^\\]|\\\\)\s*\n\s*$/, '$1');
};
Lexer.prototype.escapeLines = function(str, heredoc) {
str = str.replace(/\\[^\S\n]*(\n|\\)\s*/g, function(escaped, character) {
if (character === '\n') {
@ -774,7 +773,7 @@
if (heredoc) {
return str.replace(MULTILINER, '\\n');
} else {
return str.replace(/^(.)\s*\n\s*/, '$1').replace(/\s*\n\s*(.)$/, '$1').replace(/\s*\n\s*/g, ' ');
return str.replace(/\s*\n\s*/g, ' ');
}
};

View File

@ -186,19 +186,15 @@ exports.Lexer = class Lexer
# Matches strings, including multi-line strings. Ensures that quotation marks
# are balanced within the string's contents, and within nested interpolations.
stringToken: ->
switch @chunk.charAt 0
when "'"
return 0 unless match = SIMPLESTR.exec @chunk
string = match[0]
@token 'STRING', @escapeLines(string), 0, string.length
when '"'
return 0 unless string = @balancedString @chunk, '"'
if 0 < string.indexOf '#{', 1
@interpolateString string[1...-1], strOffset: 1, lexedLength: string.length
else
@token 'STRING', @escapeLines(string), 0, string.length
else
return 0
switch quote = @chunk.charAt 0
when "'" then [string] = SIMPLESTR.exec @chunk
when '"' then string = @balancedString @chunk, '"'
return 0 unless string
trimmed = @removeNewlines string[1...-1]
if quote is '"' and 0 < string.indexOf '#{', 1
@interpolateString trimmed, strOffset: 1, lexedLength: string.length
else
@token 'STRING', quote + @escapeLines(trimmed) + quote, 0, string.length
if octalEsc = /^(?:\\.|[^\\])*\\(?:0[0-7]|[1-7])/.test string
@error "octal escape sequences #{string} are not allowed"
string.length
@ -686,6 +682,11 @@ exports.Lexer = class Lexer
@tag() in ['\\', '.', '?.', '?::', 'UNARY', 'MATH', '+', '-', 'SHIFT', 'RELATION'
'COMPARE', 'LOGIC', 'THROW', 'EXTENDS']
# Remove newlines from beginning and (non escaped) from end of string literals.
removeNewlines: (str) ->
str.replace(/^\s*\n\s*/, '')
.replace(/([^\\]|\\\\)\s*\n\s*$/, '$1')
# Converts newlines for string literals.
escapeLines: (str, heredoc) ->
# Ignore escaped backslashes and remove escaped newlines
@ -695,9 +696,7 @@ exports.Lexer = class Lexer
str.replace MULTILINER, '\\n'
else
# Trim leading and trailing whitespace, string includes quotes
str.replace(/^(.)\s*\n\s*/, '$1')
.replace(/\s*\n\s*(.)$/, '$1')
.replace(/\s*\n\s*/g, ' ')
str.replace /\s*\n\s*/g, ' '
# Constructs a string token by escaping quotes and newlines.
makeString: (body, quote, heredoc) ->

View File

@ -81,6 +81,9 @@ test "#3229, multiline strings", ->
'string ' + "inside
interpolation"
}", "a string inside interpolation"
eq "
#{1}
", '1'
# Handle escaped backslashes correctly.
eq '\\', `'\\'`
@ -155,6 +158,11 @@ test "#3249, escape newlines in heredocs with backslashes", ->
too #{3}\
!
""", 'interpolation 1\n follows 2 too 3!'
eq """
#{1} #{2}
""", '\n1 2\n'
# TODO: uncomment when #2388 is fixed
# eq """a heredoc #{