mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
more refactors to interpolation
This commit is contained in:
parent
b5af5f66fb
commit
4b97b15c0c
3 changed files with 39 additions and 46 deletions
52
lib/lexer.js
52
lib/lexer.js
|
@ -129,14 +129,14 @@
|
||||||
// Matches strings, including multi-line strings. Ensures that quotation marks
|
// Matches strings, including multi-line strings. Ensures that quotation marks
|
||||||
// are balanced within the string's contents, and within nested interpolations.
|
// are balanced within the string's contents, and within nested interpolations.
|
||||||
Lexer.prototype.string_token = function string_token() {
|
Lexer.prototype.string_token = function string_token() {
|
||||||
var merge, string;
|
var string;
|
||||||
if (!(starts(this.chunk, '"') || starts(this.chunk, "'"))) {
|
if (!(starts(this.chunk, '"') || starts(this.chunk, "'"))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (!((string = this.balanced_token(['"', '"'], ['${', '}']) || this.balanced_token(["'", "'"])))) {
|
if (!((string = this.balanced_token(['"', '"'], ['${', '}']) || this.balanced_token(["'", "'"])))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
this.interpolate_string(string.replace(STRING_NEWLINES, " \\\n"), (merge = true));
|
this.interpolate_string(string.replace(STRING_NEWLINES, " \\\n"));
|
||||||
this.line += count(string, "\n");
|
this.line += count(string, "\n");
|
||||||
this.i += string.length;
|
this.i += string.length;
|
||||||
return true;
|
return true;
|
||||||
|
@ -171,7 +171,7 @@
|
||||||
// to distinguish from division, so we borrow some basic heuristics from
|
// to distinguish from division, so we borrow some basic heuristics from
|
||||||
// JavaScript and Ruby.
|
// JavaScript and Ruby.
|
||||||
Lexer.prototype.regex_token = function regex_token() {
|
Lexer.prototype.regex_token = function regex_token() {
|
||||||
var _a, _b, _c, _d, each, flags, i, interp_tokens, merge, regex, str;
|
var _a, flags, regex, str;
|
||||||
if (!(this.chunk.match(REGEX_START))) {
|
if (!(this.chunk.match(REGEX_START))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -182,27 +182,13 @@
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
regex += ((flags = this.chunk.substr(regex.length).match(REGEX_FLAGS)));
|
regex += ((flags = this.chunk.substr(regex.length).match(REGEX_FLAGS)));
|
||||||
if (((0 < (_d = regex.indexOf('${'))) && (_d < regex.indexOf('}'))) || regex.match(REGEX_INTERPOLATION)) {
|
if (((0 < (_a = regex.indexOf('${'))) && (_a < regex.indexOf('}'))) || regex.match(REGEX_INTERPOLATION)) {
|
||||||
str = regex.substring(1).split('/')[0];
|
str = regex.substring(1).split('/')[0];
|
||||||
str = str.replace(REGEX_ESCAPE, function(escaped) {
|
str = str.replace(REGEX_ESCAPE, function(escaped) {
|
||||||
return '\\' + escaped;
|
return '\\' + escaped;
|
||||||
});
|
});
|
||||||
this.tokens = this.tokens.concat([['(', '('], ['NEW', 'new'], ['IDENTIFIER', 'RegExp'], ['CALL_START', '(']]);
|
this.tokens = this.tokens.concat([['(', '('], ['NEW', 'new'], ['IDENTIFIER', 'RegExp'], ['CALL_START', '(']]);
|
||||||
interp_tokens = this.interpolate_string("\"" + str + "\"", (merge = false));
|
this.interpolate_string("\"" + str + "\"", true);
|
||||||
_a = interp_tokens;
|
|
||||||
for (i = 0, _b = _a.length; i < _b; i++) {
|
|
||||||
each = _a[i];
|
|
||||||
if ((_c = each[0]) === 'TOKENS') {
|
|
||||||
this.tokens = this.tokens.concat(each[1]);
|
|
||||||
} else if (_c === 'STRING') {
|
|
||||||
this.token(each[0], each[1].substring(0, 1) + each[1].substring(1, each[1].length - 1).replace(/"/g, '\\"') + each[1].substring(0, 1));
|
|
||||||
} else {
|
|
||||||
this.token(each[0], each[1]);
|
|
||||||
}
|
|
||||||
if (i < interp_tokens.length - 1) {
|
|
||||||
this.token('+', '+');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
this.tokens = this.tokens.concat([[',', ','], ['STRING', "'" + flags + "'"], [')', ')'], [')', ')']]);
|
this.tokens = this.tokens.concat([[',', ','], ['STRING', "'" + flags + "'"], [')', ')'], [')', ')']]);
|
||||||
} else {
|
} else {
|
||||||
this.token('REGEX', regex);
|
this.token('REGEX', regex);
|
||||||
|
@ -471,8 +457,8 @@
|
||||||
// If it encounters an interpolation, this method will recursively create a
|
// If it encounters an interpolation, this method will recursively create a
|
||||||
// new Lexer, tokenize the interpolated contents, and merge them into the
|
// new Lexer, tokenize the interpolated contents, and merge them into the
|
||||||
// token stream.
|
// token stream.
|
||||||
Lexer.prototype.interpolate_string = function interpolate_string(str, merge) {
|
Lexer.prototype.interpolate_string = function interpolate_string(str, escape_quotes) {
|
||||||
var _a, _b, _c, _d, each, expr, group, i, inner, interp, lexer, match, nested, pi, quote, tokens;
|
var _a, _b, _c, _d, _e, escaped, expr, group, i, inner, interp, lexer, match, nested, pi, quote, tag, token, tokens, value;
|
||||||
if (str.length < 3 || !starts(str, '"')) {
|
if (str.length < 3 || !starts(str, '"')) {
|
||||||
return this.token('STRING', str);
|
return this.token('STRING', str);
|
||||||
} else {
|
} else {
|
||||||
|
@ -524,14 +510,22 @@
|
||||||
if (!(tokens[0][0] === 'STRING')) {
|
if (!(tokens[0][0] === 'STRING')) {
|
||||||
tokens.unshift(['STRING', "''"]);
|
tokens.unshift(['STRING', "''"]);
|
||||||
}
|
}
|
||||||
if (((typeof merge !== "undefined" && merge !== null) ? merge : true)) {
|
_c = tokens;
|
||||||
_c = tokens;
|
for (i = 0, _d = _c.length; i < _d; i++) {
|
||||||
for (i = 0, _d = _c.length; i < _d; i++) {
|
token = _c[i];
|
||||||
each = _c[i];
|
_e = token;
|
||||||
each[0] === 'TOKENS' ? (this.tokens = this.tokens.concat(each[1])) : this.token(each[0], each[1]);
|
tag = _e[0];
|
||||||
if (i < tokens.length - 1) {
|
value = _e[1];
|
||||||
this.token('+', '+');
|
if (tag === 'TOKENS') {
|
||||||
}
|
this.tokens = this.tokens.concat(value);
|
||||||
|
} else if (tag === 'STRING' && escape_quotes) {
|
||||||
|
escaped = value.substring(1, value.length - 1).replace(/"/g, '\\"');
|
||||||
|
this.token(tag, "\"" + escaped + "\"");
|
||||||
|
} else {
|
||||||
|
this.token(tag, value);
|
||||||
|
}
|
||||||
|
if (i < tokens.length - 1) {
|
||||||
|
this.token('+', '+');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return tokens;
|
return tokens;
|
||||||
|
|
|
@ -99,7 +99,7 @@ exports.Lexer: class Lexer
|
||||||
return false unless string:
|
return false unless string:
|
||||||
@balanced_token(['"', '"'], ['${', '}']) or
|
@balanced_token(['"', '"'], ['${', '}']) or
|
||||||
@balanced_token ["'", "'"]
|
@balanced_token ["'", "'"]
|
||||||
@interpolate_string string.replace(STRING_NEWLINES, " \\\n"), merge: true
|
@interpolate_string string.replace(STRING_NEWLINES, " \\\n")
|
||||||
@line += count string, "\n"
|
@line += count string, "\n"
|
||||||
@i += string.length
|
@i += string.length
|
||||||
true
|
true
|
||||||
|
@ -134,13 +134,7 @@ exports.Lexer: class Lexer
|
||||||
str: regex.substring(1).split('/')[0]
|
str: regex.substring(1).split('/')[0]
|
||||||
str: str.replace REGEX_ESCAPE, (escaped) -> '\\' + escaped
|
str: str.replace REGEX_ESCAPE, (escaped) -> '\\' + escaped
|
||||||
@tokens: @tokens.concat [['(', '('], ['NEW', 'new'], ['IDENTIFIER', 'RegExp'], ['CALL_START', '(']]
|
@tokens: @tokens.concat [['(', '('], ['NEW', 'new'], ['IDENTIFIER', 'RegExp'], ['CALL_START', '(']]
|
||||||
interp_tokens: @interpolate_string "\"$str\"", merge: false
|
@interpolate_string "\"$str\"", yes
|
||||||
for each, i in interp_tokens
|
|
||||||
switch each[0]
|
|
||||||
when 'TOKENS' then @tokens: @tokens.concat each[1]
|
|
||||||
when 'STRING' then @token each[0], each[1].substring(0, 1) + each[1].substring(1, each[1].length - 1).replace(/"/g, '\\"') + each[1].substring(0, 1)
|
|
||||||
else @token each[0], each[1]
|
|
||||||
@token '+', '+' if i < interp_tokens.length - 1
|
|
||||||
@tokens: @tokens.concat [[',', ','], ['STRING', "'$flags'"], [')', ')'], [')', ')']]
|
@tokens: @tokens.concat [[',', ','], ['STRING', "'$flags'"], [')', ')'], [')', ')']]
|
||||||
else
|
else
|
||||||
@token 'REGEX', regex
|
@token 'REGEX', regex
|
||||||
|
@ -348,7 +342,7 @@ exports.Lexer: class Lexer
|
||||||
# If it encounters an interpolation, this method will recursively create a
|
# If it encounters an interpolation, this method will recursively create a
|
||||||
# new Lexer, tokenize the interpolated contents, and merge them into the
|
# new Lexer, tokenize the interpolated contents, and merge them into the
|
||||||
# token stream.
|
# token stream.
|
||||||
interpolate_string: (str, merge) ->
|
interpolate_string: (str, escape_quotes) ->
|
||||||
if str.length < 3 or not starts str, '"'
|
if str.length < 3 or not starts str, '"'
|
||||||
@token 'STRING', str
|
@token 'STRING', str
|
||||||
else
|
else
|
||||||
|
@ -380,13 +374,16 @@ exports.Lexer: class Lexer
|
||||||
i += 1
|
i += 1
|
||||||
tokens.push ['STRING', "$quote${ str.substring(pi, i) }$quote"] if pi < i and pi < str.length - 1
|
tokens.push ['STRING', "$quote${ str.substring(pi, i) }$quote"] if pi < i and pi < str.length - 1
|
||||||
tokens.unshift ['STRING', "''"] unless tokens[0][0] is 'STRING'
|
tokens.unshift ['STRING', "''"] unless tokens[0][0] is 'STRING'
|
||||||
if (merge ? true)
|
for token, i in tokens
|
||||||
for each, i in tokens
|
[tag, value]: token
|
||||||
if each[0] is 'TOKENS'
|
if tag is 'TOKENS'
|
||||||
@tokens: @tokens.concat each[1]
|
@tokens: @tokens.concat value
|
||||||
else
|
else if tag is 'STRING' and escape_quotes
|
||||||
@token each[0], each[1]
|
escaped: value.substring(1, value.length - 1).replace(/"/g, '\\"')
|
||||||
@token '+', '+' if i < tokens.length - 1
|
@token tag, "\"$escaped\""
|
||||||
|
else
|
||||||
|
@token tag, value
|
||||||
|
@token '+', '+' if i < tokens.length - 1
|
||||||
tokens
|
tokens
|
||||||
|
|
||||||
# Helpers
|
# Helpers
|
||||||
|
|
|
@ -13,5 +13,7 @@ ok '$a$b$c'.match(/\$A\$B\$C/i)
|
||||||
a: 1
|
a: 1
|
||||||
b: 2
|
b: 2
|
||||||
c: 3
|
c: 3
|
||||||
|
|
||||||
ok '123'.match(/$a$b$c/i)
|
ok '123'.match(/$a$b$c/i)
|
||||||
|
|
||||||
|
[a, b, c]: [1, 2, /\d+/]
|
||||||
|
ok (/$a$b$c$/i).toString() is '/12/\\d+/$/i'
|
||||||
|
|
Loading…
Reference in a new issue