mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
#923 ... correct interpolation.
This commit is contained in:
parent
dd168373a1
commit
fba165408c
3 changed files with 40 additions and 28 deletions
32
lib/lexer.js
32
lib/lexer.js
|
@ -128,7 +128,7 @@
|
||||||
this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
|
this.token('STRING', (string = match[0]).replace(MULTILINER, '\\\n'));
|
||||||
break;
|
break;
|
||||||
case '"':
|
case '"':
|
||||||
if (!(string = this.balancedString(this.chunk, [['"', '"'], ['#{', '}']]))) {
|
if (!(string = this.balancedString(this.chunk, '"', '"'))) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (0 < string.indexOf('#{', 1)) {
|
if (0 < string.indexOf('#{', 1)) {
|
||||||
|
@ -447,32 +447,30 @@
|
||||||
Lexer.prototype.assignmentError = function() {
|
Lexer.prototype.assignmentError = function() {
|
||||||
throw SyntaxError("Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
|
throw SyntaxError("Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned");
|
||||||
};
|
};
|
||||||
Lexer.prototype.balancedString = function(str, delimited, options) {
|
Lexer.prototype.balancedString = function(str, start, end) {
|
||||||
var i, open, pair, stack, _i, _len, _ref;
|
var i, letter, prev, stack, _ref;
|
||||||
if (options == null) {
|
stack = [end];
|
||||||
options = {};
|
|
||||||
}
|
|
||||||
stack = [delimited[0]];
|
|
||||||
for (i = 1, _ref = str.length; (1 <= _ref ? i < _ref : i > _ref); (1 <= _ref ? i += 1 : i -= 1)) {
|
for (i = 1, _ref = str.length; (1 <= _ref ? i < _ref : i > _ref); (1 <= _ref ? i += 1 : i -= 1)) {
|
||||||
switch (str.charAt(i)) {
|
switch (letter = str.charAt(i)) {
|
||||||
case '\\':
|
case '\\':
|
||||||
i++;
|
i++;
|
||||||
continue;
|
continue;
|
||||||
case stack[stack.length - 1][1]:
|
case end:
|
||||||
stack.pop();
|
stack.pop();
|
||||||
if (!stack.length) {
|
if (!stack.length) {
|
||||||
return str.slice(0, i + 1);
|
return str.slice(0, i + 1);
|
||||||
}
|
}
|
||||||
|
end = stack[stack.length - 1];
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
for (_i = 0, _len = delimited.length; _i < _len; _i++) {
|
if (end === '}' && (letter === '"' || letter === "'")) {
|
||||||
pair = delimited[_i];
|
stack.push(end = letter);
|
||||||
if ((open = pair[0]) === str.substr(i, open.length)) {
|
} else if (end === '}' && letter === '{') {
|
||||||
stack.push(pair);
|
stack.push(end = '}');
|
||||||
i += open.length - 1;
|
} else if (end === '"' && prev === '#' && letter === '{') {
|
||||||
break;
|
stack.push(end = '}');
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
prev = letter;
|
||||||
}
|
}
|
||||||
throw new Error("unterminated " + (stack.pop()[0]) + " on line " + (this.line + 1));
|
throw new Error("unterminated " + (stack.pop()[0]) + " on line " + (this.line + 1));
|
||||||
};
|
};
|
||||||
|
@ -490,7 +488,7 @@
|
||||||
i += 1;
|
i += 1;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), [['{', '}']])))) {
|
if (!(letter === '#' && str.charAt(i + 1) === '{' && (expr = this.balancedString(str.slice(i + 1), '#{', '}')))) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
if (pi < i) {
|
if (pi < i) {
|
||||||
|
|
|
@ -139,7 +139,7 @@ exports.Lexer = class Lexer
|
||||||
return 0 unless match = SIMPLESTR.exec @chunk
|
return 0 unless match = SIMPLESTR.exec @chunk
|
||||||
@token 'STRING', (string = match[0]).replace MULTILINER, '\\\n'
|
@token 'STRING', (string = match[0]).replace MULTILINER, '\\\n'
|
||||||
when '"'
|
when '"'
|
||||||
return 0 unless string = @balancedString @chunk, [['"', '"'], ['#{', '}']]
|
return 0 unless string = @balancedString @chunk, '"', '"'
|
||||||
if 0 < string.indexOf '#{', 1
|
if 0 < string.indexOf '#{', 1
|
||||||
@interpolateString string.slice 1, -1
|
@interpolateString string.slice 1, -1
|
||||||
else
|
else
|
||||||
|
@ -387,21 +387,26 @@ exports.Lexer = class Lexer
|
||||||
# a series of delimiters, all of which must be nested correctly within the
|
# a series of delimiters, all of which must be nested correctly within the
|
||||||
# contents of the string. This method allows us to have strings within
|
# contents of the string. This method allows us to have strings within
|
||||||
# interpolations within strings, ad infinitum.
|
# interpolations within strings, ad infinitum.
|
||||||
balancedString: (str, delimited, options = {}) ->
|
balancedString: (str, start, end) ->
|
||||||
stack = [delimited[0]]
|
stack = [end]
|
||||||
for i in [1...str.length]
|
for i in [1...str.length]
|
||||||
switch str.charAt i
|
switch letter = str.charAt i
|
||||||
when '\\'
|
when '\\'
|
||||||
i++
|
i++
|
||||||
continue
|
continue
|
||||||
when stack[stack.length - 1][1]
|
when end
|
||||||
stack.pop()
|
stack.pop()
|
||||||
return str.slice 0, i + 1 unless stack.length
|
unless stack.length
|
||||||
|
return str.slice 0, i + 1
|
||||||
|
end = stack[stack.length - 1]
|
||||||
continue
|
continue
|
||||||
for pair in delimited when (open = pair[0]) is str.substr i, open.length
|
if end is '}' and letter in ['"', "'"]
|
||||||
stack.push pair
|
stack.push end = letter
|
||||||
i += open.length - 1
|
else if end is '}' and letter is '{'
|
||||||
break
|
stack.push end = '}'
|
||||||
|
else if end is '"' and prev is '#' and letter is '{'
|
||||||
|
stack.push end = '}'
|
||||||
|
prev = letter
|
||||||
throw new Error "unterminated #{ stack.pop()[0] } on line #{ @line + 1 }"
|
throw new Error "unterminated #{ stack.pop()[0] } on line #{ @line + 1 }"
|
||||||
|
|
||||||
|
|
||||||
|
@ -423,7 +428,7 @@ exports.Lexer = class Lexer
|
||||||
i += 1
|
i += 1
|
||||||
continue
|
continue
|
||||||
unless letter is '#' and str.charAt(i+1) is '{' and
|
unless letter is '#' and str.charAt(i+1) is '{' and
|
||||||
(expr = @balancedString str.slice(i+1), [['{', '}']])
|
(expr = @balancedString str.slice(i + 1), '#{', '}')
|
||||||
continue
|
continue
|
||||||
tokens.push ['NEOSTRING', str.slice(pi, i)] if pi < i
|
tokens.push ['NEOSTRING', str.slice(pi, i)] if pi < i
|
||||||
inner = expr.slice(1, -1)
|
inner = expr.slice(1, -1)
|
||||||
|
|
|
@ -107,3 +107,12 @@ eq 'multiline nested "interpolations" work', """multiline #{
|
||||||
"\"interpolations\""
|
"\"interpolations\""
|
||||||
}"
|
}"
|
||||||
} work"""
|
} work"""
|
||||||
|
|
||||||
|
|
||||||
|
# Issue #923: Tricky interpolation.
|
||||||
|
eq "#{ "{" }", "{"
|
||||||
|
|
||||||
|
eq "#{ '#{}}' } }", '#{}} }'
|
||||||
|
|
||||||
|
eq "#{"'#{ ({a: "b#{1}"}['a']) }'"}", "'b1'"
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue