1
0
Fork 0
mirror of https://github.com/jashkenas/coffeescript.git synced 2022-11-09 12:23:24 -05:00

Merge pull request #3320 from xixixao/issue1275

Fix #1275
This commit is contained in:
Jeremy Ashkenas 2014-01-22 10:54:18 -08:00
commit d2f90d2236
3 changed files with 55 additions and 27 deletions

View file

@ -1,6 +1,6 @@
// Generated by CoffeeScript 1.6.3 // Generated by CoffeeScript 1.6.3
(function() { (function() {
var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, invertLiterate, key, last, locationDataToString, repeat, starts, throwSyntaxError, _ref, _ref1, var BOM, BOOL, CALLABLE, CODE, COFFEE_ALIASES, COFFEE_ALIAS_MAP, COFFEE_KEYWORDS, COMMENT, COMPARE, COMPOUND_ASSIGN, HEREDOC, HEREDOC_ILLEGAL, HEREDOC_INDENT, HEREGEX, HEREGEX_OMIT, IDENTIFIER, INDENTABLE_CLOSERS, INDEXABLE, INVERSES, JSTOKEN, JS_FORBIDDEN, JS_KEYWORDS, LINE_BREAK, LINE_CONTINUER, LOGIC, Lexer, MATH, MULTILINER, MULTI_DENT, NOT_REGEX, NOT_SPACED_REGEX, NUMBER, OPERATOR, REGEX, RELATION, RESERVED, Rewriter, SHIFT, SIMPLESTR, STRICT_PROSCRIBED, TRAILING_SPACES, UNARY, WHITESPACE, compact, count, invertLiterate, key, last, locationDataToString, repeat, starts, throwSyntaxError, _ref, _ref1,
__indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
_ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES; _ref = require('./rewriter'), Rewriter = _ref.Rewriter, INVERSES = _ref.INVERSES;
@ -351,36 +351,42 @@
this.indents.push(diff); this.indents.push(diff);
this.ends.push('OUTDENT'); this.ends.push('OUTDENT');
this.outdebt = this.indebt = 0; this.outdebt = this.indebt = 0;
this.indent = size;
} else if (size < this.baseIndent) { } else if (size < this.baseIndent) {
this.error('missing indentation', indent.length); this.error('missing indentation', indent.length);
} else { } else {
this.indebt = 0; this.indebt = 0;
this.outdentToken(this.indent - size, noNewlines, indent.length); this.outdentToken(this.indent - size, noNewlines, indent.length);
} }
this.indent = size;
return indent.length; return indent.length;
}; };
Lexer.prototype.outdentToken = function(moveOut, noNewlines, outdentLength) { Lexer.prototype.outdentToken = function(moveOut, noNewlines, outdentLength) {
var dent, len; var decreasedIndent, dent, lastIndent, _ref2;
decreasedIndent = this.indent - moveOut;
while (moveOut > 0) { while (moveOut > 0) {
len = this.indents.length - 1; lastIndent = this.indents[this.indents.length - 1];
if (this.indents[len] === void 0) { if (!lastIndent) {
moveOut = 0; moveOut = 0;
} else if (this.indents[len] === this.outdebt) { } else if (lastIndent === this.outdebt) {
moveOut -= this.outdebt; moveOut -= this.outdebt;
this.outdebt = 0; this.outdebt = 0;
} else if (this.indents[len] < this.outdebt) { } else if (lastIndent < this.outdebt) {
this.outdebt -= this.indents[len]; this.outdebt -= lastIndent;
moveOut -= this.indents[len]; moveOut -= lastIndent;
} else { } else {
dent = this.indents.pop() + this.outdebt; dent = this.indents.pop() + this.outdebt;
moveOut -= dent; if (outdentLength && (_ref2 = this.chunk[outdentLength], __indexOf.call(INDENTABLE_CLOSERS, _ref2) >= 0)) {
decreasedIndent -= dent - moveOut;
moveOut = dent;
}
this.outdebt = 0; this.outdebt = 0;
this.pair('OUTDENT'); this.pair('OUTDENT');
this.token('OUTDENT', dent, 0, outdentLength); this.token('OUTDENT', moveOut, 0, outdentLength);
moveOut -= dent;
} }
} }
this.indent = decreasedIndent;
if (dent) { if (dent) {
this.outdebt -= moveOut; this.outdebt -= moveOut;
} }
@ -685,13 +691,12 @@
}; };
Lexer.prototype.pair = function(tag) { Lexer.prototype.pair = function(tag) {
var size, wanted; var wanted;
if (tag !== (wanted = last(this.ends))) { if (tag !== (wanted = last(this.ends))) {
if ('OUTDENT' !== wanted) { if ('OUTDENT' !== wanted) {
this.error("unmatched " + tag); this.error("unmatched " + tag);
} }
this.indent -= size = last(this.indents); this.outdentToken(last(this.indents), true);
this.outdentToken(size, true);
return this.pair(tag); return this.pair(tag);
} }
return this.ends.pop(); return this.ends.pop();
@ -910,4 +915,6 @@
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']; LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'];
INDENTABLE_CLOSERS = [')', '}', ']'];
}).call(this); }).call(this);

View file

@ -327,37 +327,43 @@ exports.Lexer = class Lexer
@indents.push diff @indents.push diff
@ends.push 'OUTDENT' @ends.push 'OUTDENT'
@outdebt = @indebt = 0 @outdebt = @indebt = 0
@indent = size
else if size < @baseIndent else if size < @baseIndent
@error 'missing indentation', indent.length @error 'missing indentation', indent.length
else else
@indebt = 0 @indebt = 0
@outdentToken @indent - size, noNewlines, indent.length @outdentToken @indent - size, noNewlines, indent.length
@indent = size
indent.length indent.length
# Record an outdent token or multiple tokens, if we happen to be moving back # Record an outdent token or multiple tokens, if we happen to be moving back
# inwards past several recorded indents. # inwards past several recorded indents. Sets new @indent value.
outdentToken: (moveOut, noNewlines, outdentLength) -> outdentToken: (moveOut, noNewlines, outdentLength) ->
decreasedIndent = @indent - moveOut
while moveOut > 0 while moveOut > 0
len = @indents.length - 1 lastIndent = @indents[@indents.length - 1]
if @indents[len] is undefined if not lastIndent
moveOut = 0 moveOut = 0
else if @indents[len] is @outdebt else if lastIndent is @outdebt
moveOut -= @outdebt moveOut -= @outdebt
@outdebt = 0 @outdebt = 0
else if @indents[len] < @outdebt else if lastIndent < @outdebt
@outdebt -= @indents[len] @outdebt -= lastIndent
moveOut -= @indents[len] moveOut -= lastIndent
else else
dent = @indents.pop() + @outdebt dent = @indents.pop() + @outdebt
moveOut -= dent if outdentLength and @chunk[outdentLength] in INDENTABLE_CLOSERS
decreasedIndent -= dent - moveOut
moveOut = dent
@outdebt = 0 @outdebt = 0
# pair might call outdentToken, so preserve decreasedIndent
@pair 'OUTDENT' @pair 'OUTDENT'
@token 'OUTDENT', dent, 0, outdentLength @token 'OUTDENT', moveOut, 0, outdentLength
moveOut -= dent
@outdebt -= moveOut if dent @outdebt -= moveOut if dent
@tokens.pop() while @value() is ';' @tokens.pop() while @value() is ';'
@token 'TERMINATOR', '\n', outdentLength, 0 unless @tag() is 'TERMINATOR' or noNewlines @token 'TERMINATOR', '\n', outdentLength, 0 unless @tag() is 'TERMINATOR' or noNewlines
@indent = decreasedIndent
this this
# Matches and consumes non-meaningful whitespace. Tag the previous token # Matches and consumes non-meaningful whitespace. Tag the previous token
@ -606,8 +612,7 @@ exports.Lexer = class Lexer
# el.click((event) -> # el.click((event) ->
# el.hide()) # el.hide())
# #
@indent -= size = last @indents @outdentToken last(@indents), true
@outdentToken size, true
return @pair tag return @pair tag
@ends.pop() @ends.pop()
@ -881,3 +886,6 @@ INDEXABLE = CALLABLE.concat 'NUMBER', 'BOOL', 'NULL', 'UNDEFINED'
# occurs at the start of a line. We disambiguate these from trailing whens to # occurs at the start of a line. We disambiguate these from trailing whens to
# avoid an ambiguity in the grammar. # avoid an ambiguity in the grammar.
LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR'] LINE_BREAK = ['INDENT', 'OUTDENT', 'TERMINATOR']
# Additional indent in front of these is ignored.
INDENTABLE_CLOSERS = [')', '}', ']']

View file

@ -199,7 +199,7 @@ test "#1299: Disallow token misnesting", ->
test "#2981: Enforce initial indentation", -> test "#2981: Enforce initial indentation", ->
try try
CoffeeScript.compile ' a\nb' CoffeeScript.compile ' a\nb-'
ok no ok no
catch e catch e
eq 'missing indentation', e.message eq 'missing indentation', e.message
@ -212,3 +212,16 @@ test "'single-line' expression containing multiple lines", ->
then -b then -b
else null else null
""" """
test "#1275: allow indentation before closing brackets", ->
array = [
1
2
3
]
eq array, array
do ->
(
a = 1
)
eq 1, a