diff --git a/lib/coffee_script/grammar.js b/lib/coffee_script/grammar.js index 30d17a61..b5b8ef90 100644 --- a/lib/coffee_script/grammar.js +++ b/lib/coffee_script/grammar.js @@ -381,9 +381,7 @@ SimpleArgs: [o("Expression", function() { return $1; }), o("SimpleArgs , Expression", function() { - return ([$1].push($3)).reduce(function(a, b) { - return a.concat(b); - }); + return $1 instanceof Array ? $1.concat([$3]) : [$1].concat([$3]); }) ], // Try/catch/finally exception handling blocks. diff --git a/lib/coffee_script/lexer.js b/lib/coffee_script/lexer.js index 3070ad1d..f4413f75 100644 --- a/lib/coffee_script/lexer.js +++ b/lib/coffee_script/lexer.js @@ -1,5 +1,5 @@ (function(){ - var ASSIGNMENT, CALLABLE, CODE, COMMENT, COMMENT_CLEANER, HEREDOC, HEREDOC_INDENT, IDENTIFIER, JS, JS_CLEANER, KEYWORDS, LAST_DENT, LAST_DENTS, MULTILINER, MULTI_DENT, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, Rewriter, STRING, STRING_NEWLINES, WHITESPACE, lex; + var ASSIGNMENT, BEFORE_WHEN, CALLABLE, CODE, COMMENT, COMMENT_CLEANER, HEREDOC, HEREDOC_INDENT, IDENTIFIER, JS, JS_CLEANER, KEYWORDS, LAST_DENT, LAST_DENTS, MULTILINER, MULTI_DENT, NOT_REGEX, NO_NEWLINE, NUMBER, OPERATOR, REGEX, Rewriter, STRING, STRING_NEWLINES, WHITESPACE, lex; Rewriter = require('./rewriter').Rewriter; // The lexer reads a stream of CoffeeScript and divvys it up into tagged // tokens. A minor bit of the ambiguity in the grammar has been avoided by @@ -36,6 +36,8 @@ NOT_REGEX = ['IDENTIFIER', 'NUMBER', 'REGEX', 'STRING', ')', '++', '--', ']', '}', 'FALSE', 'NULL', 'TRUE']; // Tokens which could legitimately be invoked or indexed. CALLABLE = ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING']; + // Tokens that, when immediately preceding a 'WHEN', indicate that its leading. + BEFORE_WHEN = ['INDENT', 'OUTDENT', 'TERMINATOR']; // Scan by attempting to match tokens one character at a time. Slow and steady. lex.prototype.tokenize = function tokenize(code) { this.code = code; @@ -101,7 +103,7 @@ // Keywords are special identifiers tagged with their own name, // 'if' will result in an ['IF', "if"] token. tag = KEYWORDS.indexOf(id) >= 0 ? id.toUpperCase() : 'IDENTIFIER'; - if (tag === 'WHEN' && (this.tag() === 'OUTDENT' || this.tag() === 'INDENT')) { + if (tag === 'WHEN' && BEFORE_WHEN.indexOf(this.tag()) >= 0) { tag = 'LEADING_WHEN'; } if (tag === 'IDENTIFIER' && this.value() === '::') { diff --git a/lib/coffee_script/parser.js b/lib/coffee_script/parser.js index 54c2389e..f3881b88 100755 --- a/lib/coffee_script/parser.js +++ b/lib/coffee_script/parser.js @@ -307,9 +307,7 @@ case 148:this.$ = $$[$0-2+1-1]; break; case 149:this.$ = $$[$0-1+1-1]; break; -case 150:this.$ = ([$$[$0-3+1-1]].push($$[$0-3+3-1])).reduce(function(a, b) { - return a.concat(b); - }); +case 150:this.$ = $$[$0-3+1-1] instanceof Array ? $$[$0-3+1-1].concat([$$[$0-3+3-1]]) : [$$[$0-3+1-1]].concat([$$[$0-3+3-1]]); break; case 151:this.$ = new TryNode($$[$0-3+2-1], $$[$0-3+3-1][0], $$[$0-3+3-1][1]); break; @@ -525,4 +523,4 @@ exports.main = function commonjsMain(args) { if (require.main === module) { exports.main(require("system").args); } -} +} \ No newline at end of file diff --git a/src/grammar.coffee b/src/grammar.coffee index f0cceba8..671d91a7 100644 --- a/src/grammar.coffee +++ b/src/grammar.coffee @@ -335,7 +335,7 @@ grammar: { SimpleArgs: [ o "Expression", -> $1 o "SimpleArgs , Expression", -> - ([$1].push($3)).reduce (a, b) -> a.concat(b) + if $1 instanceof Array then $1.concat([$3]) else [$1].concat([$3]) ] # Try/catch/finally exception handling blocks. @@ -384,8 +384,10 @@ grammar: { ForSource: [ o "IN Expression", -> {source: $2} o "OF Expression", -> {source: $2, object: true} - o "ForSource WHEN Expression", -> $1.filter: $3; $1 - o "ForSource BY Expression", -> $1.step: $3; $1 + o "ForSource WHEN Expression", -> + $1.filter: $3; $1 + o "ForSource BY Expression", -> + $1.step: $3; $1 ] # Switch/When blocks. diff --git a/src/lexer.coffee b/src/lexer.coffee index 69ab3cfc..6d8a7b83 100644 --- a/src/lexer.coffee +++ b/src/lexer.coffee @@ -57,6 +57,9 @@ NOT_REGEX: [ # Tokens which could legitimately be invoked or indexed. CALLABLE: ['IDENTIFIER', 'SUPER', ')', ']', '}', 'STRING'] +# Tokens that, when immediately preceding a 'WHEN', indicate that its leading. +BEFORE_WHEN: ['INDENT', 'OUTDENT', 'TERMINATOR'] + # Scan by attempting to match tokens one character at a time. Slow and steady. lex::tokenize: (code) -> @code : code # Cleanup code by remove extra line breaks, TODO: chomp @@ -94,7 +97,7 @@ lex::identifier_token: -> # Keywords are special identifiers tagged with their own name, # 'if' will result in an ['IF', "if"] token. tag: if KEYWORDS.indexOf(id) >= 0 then id.toUpperCase() else 'IDENTIFIER' - tag: 'LEADING_WHEN' if tag is 'WHEN' and (@tag() is 'OUTDENT' or @tag() is 'INDENT') + tag: 'LEADING_WHEN' if tag is 'WHEN' and BEFORE_WHEN.indexOf(@tag()) >= 0 @tag(-1, 'PROTOTYPE_ACCESS') if tag is 'IDENTIFIER' and @value() is '::' if tag is 'IDENTIFIER' and @value() is '.' and !(@value(2) is '.') if @tag(2) is '?' diff --git a/test/fixtures/execution/test_switch.coffee b/test/fixtures/execution/test_switch.coffee index b97fa011..7c6dda51 100644 --- a/test/fixtures/execution/test_switch.coffee +++ b/test/fixtures/execution/test_switch.coffee @@ -16,6 +16,7 @@ result: switch num puts result + func: (num) -> switch num when 2, 4, 6