mirror of
https://github.com/jashkenas/coffeescript.git
synced 2022-11-09 12:23:24 -05:00
This commit is contained in:
parent
b20e52da99
commit
4a4f752204
3 changed files with 39 additions and 11 deletions
|
@ -672,9 +672,7 @@
|
|||
if (dent) {
|
||||
this.outdebt -= moveOut;
|
||||
}
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
this.suppressSemicolons();
|
||||
if (!(this.tag() === 'TERMINATOR' || noNewlines)) {
|
||||
this.token('TERMINATOR', '\n', outdentLength, 0);
|
||||
}
|
||||
|
@ -703,9 +701,7 @@
|
|||
|
||||
// Generate a newline token. Consecutive newlines get merged together.
|
||||
newlineToken(offset) {
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
}
|
||||
this.suppressSemicolons();
|
||||
if (this.tag() !== 'TERMINATOR') {
|
||||
this.token('TERMINATOR', '\n', offset, 0);
|
||||
}
|
||||
|
@ -844,7 +840,7 @@
|
|||
// here. `;` and newlines are both treated as a `TERMINATOR`, we distinguish
|
||||
// parentheses that indicate a method call from regular parentheses, and so on.
|
||||
literalToken() {
|
||||
var match, message, origin, prev, ref, ref1, ref2, ref3, skipToken, tag, token, value;
|
||||
var match, message, origin, prev, ref, ref1, ref2, ref3, ref4, skipToken, tag, token, value;
|
||||
if (match = OPERATOR.exec(this.chunk)) {
|
||||
[value] = match;
|
||||
if (CODE.test(value)) {
|
||||
|
@ -884,6 +880,9 @@
|
|||
this.exportSpecifierList = false;
|
||||
}
|
||||
if (value === ';') {
|
||||
if (ref2 = prev != null ? prev[0] : void 0, indexOf.call(['=', ...UNFINISHED], ref2) >= 0) {
|
||||
this.error('unexpected ;');
|
||||
}
|
||||
this.seenFor = this.seenImport = this.seenExport = false;
|
||||
tag = 'TERMINATOR';
|
||||
} else if (value === '*' && (prev != null ? prev[0] : void 0) === 'EXPORT') {
|
||||
|
@ -903,12 +902,12 @@
|
|||
} else if (value === '?' && (prev != null ? prev.spaced : void 0)) {
|
||||
tag = 'BIN?';
|
||||
} else if (prev) {
|
||||
if (value === '(' && !prev.spaced && (ref2 = prev[0], indexOf.call(CALLABLE, ref2) >= 0)) {
|
||||
if (value === '(' && !prev.spaced && (ref3 = prev[0], indexOf.call(CALLABLE, ref3) >= 0)) {
|
||||
if (prev[0] === '?') {
|
||||
prev[0] = 'FUNC_EXIST';
|
||||
}
|
||||
tag = 'CALL_START';
|
||||
} else if (value === '[' && (((ref3 = prev[0], indexOf.call(INDEXABLE, ref3) >= 0) && !prev.spaced) || (prev[0] === '::'))) { // `.prototype` can’t be a method you can call.
|
||||
} else if (value === '[' && (((ref4 = prev[0], indexOf.call(INDEXABLE, ref4) >= 0) && !prev.spaced) || (prev[0] === '::'))) { // `.prototype` can’t be a method you can call.
|
||||
tag = 'INDEX_START';
|
||||
switch (prev[0]) {
|
||||
case '?':
|
||||
|
@ -1407,6 +1406,20 @@
|
|||
return `${options.delimiter}${body}${options.delimiter}`;
|
||||
}
|
||||
|
||||
suppressSemicolons() {
|
||||
var ref, ref1, results;
|
||||
results = [];
|
||||
while (this.value() === ';') {
|
||||
this.tokens.pop();
|
||||
if (ref = (ref1 = this.prev()) != null ? ref1[0] : void 0, indexOf.call(['=', ...UNFINISHED], ref) >= 0) {
|
||||
results.push(this.error('unexpected ;'));
|
||||
} else {
|
||||
results.push(void 0);
|
||||
}
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
// Throws an error at either a given offset from the current chunk or at the
|
||||
// location of a token (`token[2]`).
|
||||
error(message, options = {}) {
|
||||
|
|
|
@ -509,7 +509,7 @@ exports.Lexer = class Lexer
|
|||
@token 'OUTDENT', moveOut, 0, outdentLength
|
||||
moveOut -= dent
|
||||
@outdebt -= moveOut if dent
|
||||
@tokens.pop() while @value() is ';'
|
||||
@suppressSemicolons()
|
||||
|
||||
@token 'TERMINATOR', '\n', outdentLength, 0 unless @tag() is 'TERMINATOR' or noNewlines
|
||||
@indent = decreasedIndent
|
||||
|
@ -527,7 +527,7 @@ exports.Lexer = class Lexer
|
|||
|
||||
# Generate a newline token. Consecutive newlines get merged together.
|
||||
newlineToken: (offset) ->
|
||||
@tokens.pop() while @value() is ';'
|
||||
@suppressSemicolons()
|
||||
@token 'TERMINATOR', '\n', offset, 0 unless @tag() is 'TERMINATOR'
|
||||
this
|
||||
|
||||
|
@ -662,6 +662,7 @@ exports.Lexer = class Lexer
|
|||
@exportSpecifierList = no
|
||||
|
||||
if value is ';'
|
||||
@error 'unexpected ;' if prev?[0] in ['=', UNFINISHED...]
|
||||
@seenFor = @seenImport = @seenExport = no
|
||||
tag = 'TERMINATOR'
|
||||
else if value is '*' and prev?[0] is 'EXPORT'
|
||||
|
@ -1053,6 +1054,11 @@ exports.Lexer = class Lexer
|
|||
when other then (if options.double then "\\#{other}" else other)
|
||||
"#{options.delimiter}#{body}#{options.delimiter}"
|
||||
|
||||
suppressSemicolons: ->
|
||||
while @value() is ';'
|
||||
@tokens.pop()
|
||||
@error 'unexpected ;' if @prev()?[0] in ['=', UNFINISHED...]
|
||||
|
||||
# Throws an error at either a given offset from the current chunk or at the
|
||||
# location of a token (`token[2]`).
|
||||
error: (message, options = {}) ->
|
||||
|
|
|
@ -1759,3 +1759,12 @@ test "#3199: error message for throw indented comprehension", ->
|
|||
x for x in [1, 2, 3]
|
||||
^
|
||||
'''
|
||||
|
||||
test "#3098: suppressed newline should be unsuppressed by semicolon", ->
|
||||
assertErrorFormat '''
|
||||
a = ; 5
|
||||
''', '''
|
||||
[stdin]:1:5: error: unexpected ;
|
||||
a = ; 5
|
||||
^
|
||||
'''
|
||||
|
|
Loading…
Reference in a new issue