diff --git a/lib/coffee_script/rewriter.js b/lib/coffee_script/rewriter.js index df985321..8f9a3720 100644 --- a/lib/coffee_script/rewriter.js +++ b/lib/coffee_script/rewriter.js @@ -53,7 +53,7 @@ this.remove_mid_expression_newlines(); this.move_commas_outside_outdents(); this.close_open_calls_and_indexes(); - // this.add_implicit_parentheses() + this.add_implicit_parentheses(); this.add_implicit_indentation(); // this.ensure_balance(BALANCED_PAIRS) // this.rewrite_closing_parens() @@ -182,6 +182,44 @@ }); })(this)); }; + // Methods may be optionally called without parentheses, for simple cases. + // Insert the implicit parentheses here, so that the parser doesn't have to + // deal with them. + re.prototype.add_implicit_parentheses = function add_implicit_parentheses() { + var stack; + stack = [0]; + return this.scan_tokens((function(__this) { + var __func = function(prev, token, post, i) { + var __i, __j, __k, __l, idx, last, size, tmp; + if (token[0] === 'INDENT') { + stack.push(0); + } + if (token[0] === 'OUTDENT') { + last = stack.pop(); + stack[stack.length - 1] += last; + } + if (stack[stack.length - 1] > 0 && (IMPLICIT_END.indexOf(token[0]) >= 0 || !(typeof post !== "undefined" && post !== null))) { + idx = token[0] === 'OUTDENT' ? i + 1 : i; + __k = 0; __l = stack[stack.length - 1]; + for (__j=0, tmp=__k; (__k <= __l ? tmp < __l : tmp > __l); (__k <= __l ? tmp += 1 : tmp -= 1), __j++) { + this.tokens.splice(idx, 0, ['CALL_END', ')']); + } + size = stack[stack.length - 1] + 1; + stack[stack.length - 1] = 0; + return size; + } + if (!(prev && IMPLICIT_FUNC.indexOf(prev[0]) >= 0 && IMPLICIT_CALL.indexOf(token[0]) >= 0)) { + return 1; + } + this.tokens.splice(i, 0, ['CALL_START', '(']); + stack[stack.length - 1] += 1; + return 2; + }; + return (function() { + return __func.apply(__this, arguments); + }); + })(this)); + }; // Because our grammar is LALR(1), it can't handle some single-line // expressions that lack ending delimiters. Use the lexer to add the implicit // blocks, so it doesn't need to. diff --git a/src/rewriter.coffee b/src/rewriter.coffee index a2cb5d4e..1e070340 100644 --- a/src/rewriter.coffee +++ b/src/rewriter.coffee @@ -45,7 +45,7 @@ re::rewrite: (tokens) -> this.remove_mid_expression_newlines() this.move_commas_outside_outdents() this.close_open_calls_and_indexes() - # this.add_implicit_parentheses() + this.add_implicit_parentheses() this.add_implicit_indentation() # this.ensure_balance(BALANCED_PAIRS) # this.rewrite_closing_parens() @@ -132,6 +132,28 @@ re::close_open_calls_and_indexes: -> brackets[brackets.length - 1] -= 1 return 1 +# Methods may be optionally called without parentheses, for simple cases. +# Insert the implicit parentheses here, so that the parser doesn't have to +# deal with them. +re::add_implicit_parentheses: -> + stack: [0] + this.scan_tokens (prev, token, post, i) => + stack.push(0) if token[0] is 'INDENT' + if token[0] is 'OUTDENT' + last: stack.pop() + stack[stack.length - 1] += last + if stack[stack.length - 1] > 0 and (IMPLICIT_END.indexOf(token[0]) >= 0 or !post?) + idx: if token[0] is 'OUTDENT' then i + 1 else i + for tmp in [0...stack[stack.length - 1]] + this.tokens.splice(idx, 0, ['CALL_END', ')']) + size: stack[stack.length - 1] + 1 + stack[stack.length - 1]: 0 + return size + return 1 unless prev and IMPLICIT_FUNC.indexOf(prev[0]) >= 0 and IMPLICIT_CALL.indexOf(token[0]) >= 0 + this.tokens.splice(i, 0, ['CALL_START', '(']) + stack[stack.length - 1] += 1 + return 2 + # Because our grammar is LALR(1), it can't handle some single-line # expressions that lack ending delimiters. Use the lexer to add the implicit # blocks, so it doesn't need to.