diff --git a/lib/rewriter.js b/lib/rewriter.js index 6c22623e..14a3b644 100644 --- a/lib/rewriter.js +++ b/lib/rewriter.js @@ -16,8 +16,7 @@ this.tokens = _arg; this.removeLeadingNewlines(); this.removeMidExpressionNewlines(); - this.closeOpenCalls(); - this.closeOpenIndexes(); + this.closeOpenPairs(); this.addImplicitIndentation(); this.tagPostfixConditionals(); this.addImplicitBraces(); @@ -77,37 +76,33 @@ return 0; }); }; - exports.Rewriter.prototype.closeOpenCalls = function() { - var action, condition; - condition = function(token, i) { - var _ref; - return ((_ref = token[0]) === ')' || _ref === 'CALL_END') || token[0] === 'OUTDENT' && this.tag(i - 1) === ')'; - }; - action = function(token, i) { - return this.tokens[token[0] === 'OUTDENT' ? i - 1 : i][0] = 'CALL_END'; - }; - return this.scanTokens(function(token, i) { - if (token[0] === 'CALL_START') { - this.detectEnd(i + 1, condition, action); + exports.Rewriter.prototype.closeOpenPairs = function() { + var stack, token, _i, _len, _ref; + stack = []; + _ref = this.tokens; + for (_i = 0, _len = _ref.length; _i < _len; _i++) { + token = _ref[_i]; + switch (token[0]) { + case 'CALL_START': + case 'INDEX_START': + case '(': + case '[': + stack.push(token[0]); + break; + case 'CALL_END': + case 'INDEX_END': + case ')': + case ']': + switch (stack.pop()) { + case 'CALL_START': + token[0] = 'CALL_END'; + break; + case 'INDEX_START': + token[0] = 'INDEX_END'; + } } - return 1; - }); - }; - exports.Rewriter.prototype.closeOpenIndexes = function() { - var action, condition; - condition = function(token, i) { - var _ref; - return (_ref = token[0]) === ']' || _ref === 'INDEX_END'; - }; - action = function(token, i) { - return token[0] = 'INDEX_END'; - }; - return this.scanTokens(function(token, i) { - if (token[0] === 'INDEX_START') { - this.detectEnd(i + 1, condition, action); - } - return 1; - }); + } + return this; }; exports.Rewriter.prototype.addImplicitBraces = function() { var action, condition, stack, start; diff --git a/src/rewriter.coffee b/src/rewriter.coffee index ae39b9d2..41cd3fc7 100644 --- a/src/rewriter.coffee +++ b/src/rewriter.coffee @@ -20,8 +20,7 @@ class exports.Rewriter rewrite: (@tokens) -> @removeLeadingNewlines() @removeMidExpressionNewlines() - @closeOpenCalls() - @closeOpenIndexes() + @closeOpenPairs() @addImplicitIndentation() @tagPostfixConditionals() @addImplicitBraces() @@ -68,27 +67,19 @@ class exports.Rewriter tokens.splice i, 1 0 - # The lexer has tagged the opening parenthesis of a method call. Match it with - # its paired close. We have the mis-nested outdent case included here for - # calls that close on the same line, just before their outdent. - closeOpenCalls: -> - condition = (token, i) -> - token[0] in [')', 'CALL_END'] or - token[0] is 'OUTDENT' and @tag(i - 1) is ')' - action = (token, i) -> - @tokens[if token[0] is 'OUTDENT' then i - 1 else i][0] = 'CALL_END' - @scanTokens (token, i) -> - @detectEnd i + 1, condition, action if token[0] is 'CALL_START' - 1 - - # The lexer has tagged the opening parenthesis of an indexing operation call. - # Match it with its paired close. - closeOpenIndexes: -> - condition = (token, i) -> token[0] in [']', 'INDEX_END'] - action = (token, i) -> token[0] = 'INDEX_END' - @scanTokens (token, i) -> - @detectEnd i + 1, condition, action if token[0] is 'INDEX_START' - 1 + # The lexer has tagged the opening parenthesis of a method call, or the open + # bracket of an indexing operation. Match it with its paired close. + closeOpenPairs: -> + stack = [] + for token in @tokens + switch token[0] + when 'CALL_START', 'INDEX_START', '(', '[' + stack.push token[0] + when 'CALL_END', 'INDEX_END', ')', ']' + switch stack.pop() + when 'CALL_START' then token[0] = 'CALL_END' + when 'INDEX_START' then token[0] = 'INDEX_END' + this # Object literals may be written with implicit braces, for simple cases. # Insert the missing braces here, so that the parser doesn't have to.