diff --git a/Cakefile b/Cakefile
index 46a0df74..dc436688 100644
--- a/Cakefile
+++ b/Cakefile
@@ -29,7 +29,7 @@ task 'build', 'build the CoffeeScript language from source', ->
task 'build:full', 'checkout /lib, rebuild the source twice, and run the tests', ->
- exec 'git co lib && bin/cake build && bin/cake build && bin/cake test', (err, stdout, stderr) ->
+ exec 'git checkout lib && bin/cake build && bin/cake build && bin/cake test', (err, stdout, stderr) ->
print stdout if stdout
print stderr if stderr
throw err if err
diff --git a/extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage b/extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage
index 1bbbeaf0..16a325bb 100644
--- a/extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage
+++ b/extras/CoffeeScript.tmbundle/Syntaxes/CoffeeScript.tmLanguage
@@ -150,7 +150,7 @@
end
- (/)[igm]*
+ (/)[igmy]*
endCaptures
1
diff --git a/lib/lexer.js b/lib/lexer.js
index 988fb32e..bef8b616 100644
--- a/lib/lexer.js
+++ b/lib/lexer.js
@@ -129,15 +129,11 @@
// Matches strings, including multi-line strings. Ensures that quotation marks
// are balanced within the string's contents, and within nested interpolations.
Lexer.prototype.string_token = function string_token() {
- var merge, string, supress;
+ var merge, string;
if (!(starts(this.chunk, '"') || starts(this.chunk, "'"))) {
return false;
}
- string = this.balanced_token((supress = false), ['"', '"'], ['${', '}']);
- if (!(string)) {
- string = this.balanced_token((supress = false), ["'", "'"]);
- }
- if (!(string)) {
+ if (!((string = this.balanced_token(['"', '"'], ['${', '}']) || this.balanced_token(["'", "'"])))) {
return false;
}
this.interpolate_string(string.replace(STRING_NEWLINES, " \\\n"), (merge = true));
@@ -160,11 +156,11 @@
};
// Matches JavaScript interpolated directly into the source via backticks.
Lexer.prototype.js_token = function js_token() {
- var script, supress;
+ var script;
if (!(starts(this.chunk, '`'))) {
return false;
}
- if (!((script = this.balanced_token((supress = false), ['`', '`'])))) {
+ if (!((script = this.balanced_token(['`', '`'])))) {
return false;
}
this.token('JS', script.replace(JS_CLEANER, ''));
@@ -175,11 +171,11 @@
// to distinguish from division, so we borrow some basic heuristics from
// JavaScript and Ruby.
Lexer.prototype.regex_token = function regex_token() {
- var _a, _b, _c, _d, _e, each, flags, i, index, interp_tokens, merge, regex, str, supress;
+ var _a, _b, _c, _d, _e, each, flags, i, index, interp_tokens, merge, regex, str;
if (!(starts(this.chunk, '/'))) {
return false;
}
- if (!((regex = this.balanced_token((supress = true), ['/', '/'])))) {
+ if (!((regex = this.balanced_token(['/', '/'])))) {
return false;
}
if (regex.length < 3 || regex.match(/^\/\s+|\n/)) {
@@ -225,10 +221,10 @@
};
// Matches a token in which which the passed delimiter pairs must be correctly
// balanced (ie. strings, JS literals).
- Lexer.prototype.balanced_token = function balanced_token(supress) {
+ Lexer.prototype.balanced_token = function balanced_token() {
var delimited;
- delimited = Array.prototype.slice.call(arguments, 1);
- return this.balanced_string.apply(this, [this.chunk].concat([supress]).concat(delimited));
+ delimited = Array.prototype.slice.call(arguments, 0);
+ return this.balanced_string.apply(this, [this.chunk].concat(delimited));
};
// Matches and conumes comments. We pass through comments into JavaScript,
// so they're treated as real tokens, like any other part of the language.
@@ -432,9 +428,9 @@
// 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
// interpolations within strings etc...
- Lexer.prototype.balanced_string = function balanced_string(str, supress) {
+ Lexer.prototype.balanced_string = function balanced_string(str) {
var _a, _b, _c, _d, close, delimited, i, levels, open, pair;
- delimited = Array.prototype.slice.call(arguments, 2);
+ delimited = Array.prototype.slice.call(arguments, 1);
levels = [];
i = 0;
while (i < str.length) {
@@ -466,7 +462,7 @@
i += 1;
}
if (levels.length) {
- if (!(supress)) {
+ if (!(delimited[0][0] === '/')) {
throw new Error("SyntaxError: Unterminated " + (levels.pop()[0]) + " starting on line " + (this.line + 1));
}
return false;
@@ -485,7 +481,7 @@
// new Lexer, tokenize the interpolated contents, and merge them into the
// token stream.
Lexer.prototype.interpolate_string = function interpolate_string(str, merge) {
- var _a, _b, _c, _d, _e, _f, _g, each, expr, group, has_string, i, inner, interp, lexer, match, nested, pi, quote, supress, tokens;
+ var _a, _b, _c, _d, _e, _f, _g, each, expr, group, has_string, i, inner, interp, lexer, match, nested, pi, quote, tokens;
if (str.length < 3 || !starts(str, '"')) {
return this.token('STRING', str);
} else {
@@ -511,7 +507,7 @@
tokens.push(['IDENTIFIER', interp]);
i += group.length - 1;
pi = i + 1;
- } else if (((expr = this.balanced_string(str.substring(i), (supress = false), ['${', '}'])))) {
+ } else if (((expr = this.balanced_string(str.substring(i), ['${', '}'])))) {
if (pi < i) {
tokens.push(['STRING', '' + quote + (str.substring(pi, i)) + quote]);
}
diff --git a/src/lexer.coffee b/src/lexer.coffee
index 6f5e4024..27957c85 100644
--- a/src/lexer.coffee
+++ b/src/lexer.coffee
@@ -96,9 +96,9 @@ exports.Lexer: class Lexer
# are balanced within the string's contents, and within nested interpolations.
string_token: ->
return false unless starts(@chunk, '"') or starts(@chunk, "'")
- string: @balanced_token supress: false, ['"', '"'], ['${', '}']
- string: @balanced_token supress: false, ["'", "'"] unless string
- return false unless string
+ return false unless string:
+ @balanced_token(['"', '"'], ['${', '}']) or
+ @balanced_token ["'", "'"]
@interpolate_string string.replace(STRING_NEWLINES, " \\\n"), merge: true
@line += count string, "\n"
@i += string.length
@@ -117,7 +117,7 @@ exports.Lexer: class Lexer
# Matches JavaScript interpolated directly into the source via backticks.
js_token: ->
return false unless starts @chunk, '`'
- return false unless script: @balanced_token supress: false, ['`', '`']
+ return false unless script: @balanced_token ['`', '`']
@token 'JS', script.replace(JS_CLEANER, '')
@i += script.length
true
@@ -127,7 +127,7 @@ exports.Lexer: class Lexer
# JavaScript and Ruby.
regex_token: ->
return false unless starts @chunk, '/'
- return false unless regex: @balanced_token supress: true, ['/', '/']
+ return false unless regex: @balanced_token ['/', '/']
return false if regex.length < 3 or regex.match /^\/\s+|\n/
return false if include NOT_REGEX, @tag()
flags: ['i', 'm', 'g', 'y']
@@ -153,8 +153,8 @@ exports.Lexer: class Lexer
# Matches a token in which which the passed delimiter pairs must be correctly
# balanced (ie. strings, JS literals).
- balanced_token: (supress, delimited...) ->
- @balanced_string @chunk, supress, delimited...
+ balanced_token: (delimited...) ->
+ @balanced_string @chunk, delimited...
# Matches and conumes comments. We pass through comments into JavaScript,
# so they're treated as real tokens, like any other part of the language.
@@ -316,7 +316,7 @@ exports.Lexer: class Lexer
# 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
# interpolations within strings etc...
- balanced_string: (str, supress, delimited...) ->
+ balanced_string: (str, delimited...) ->
levels: []
i: 0
while i < str.length
@@ -337,7 +337,7 @@ exports.Lexer: class Lexer
break unless levels.length
i += 1
if levels.length
- throw new Error "SyntaxError: Unterminated ${levels.pop()[0]} starting on line ${@line + 1}" unless supress
+ throw new Error "SyntaxError: Unterminated ${levels.pop()[0]} starting on line ${@line + 1}" unless delimited[0][0] is '/'
return false
return false if i is 0
return str.substring(0, i)
@@ -370,7 +370,7 @@ exports.Lexer: class Lexer
tokens.push ['IDENTIFIER', interp]
i += group.length - 1
pi: i + 1
- else if (expr: @balanced_string str.substring(i), supress: false, ['${', '}'])
+ else if (expr: @balanced_string str.substring(i), ['${', '}'])
tokens.push ['STRING', "$quote${ str.substring(pi, i) }$quote"] if pi < i
inner: expr.substring(2, expr.length - 1)
if inner.length