From 19f77cfff5bf427c9996eb189d01d9055fe4dc08 Mon Sep 17 00:00:00 2001 From: Jeremy Ashkenas Date: Sat, 17 Sep 2011 21:39:24 -0400 Subject: [PATCH] Unified error handling in the lexer. --- lib/coffee-script/lexer.js | 20 +++++++------------- src/lexer.coffee | 30 +++++++++++------------------- 2 files changed, 18 insertions(+), 32 deletions(-) diff --git a/lib/coffee-script/lexer.js b/lib/coffee-script/lexer.js index 5c523baf..5267ffb3 100644 --- a/lib/coffee-script/lexer.js +++ b/lib/coffee-script/lexer.js @@ -28,7 +28,7 @@ i += this.identifierToken() || this.commentToken() || this.whitespaceToken() || this.lineToken() || this.heredocToken() || this.stringToken() || this.numberToken() || this.regexToken() || this.jsToken() || this.literalToken(); } this.closeIndentation(); - if (tag = this.ends.pop()) this.carp("missing " + tag); + if (tag = this.ends.pop()) this.error("missing " + tag); if (opts.rewrite === false) return this.tokens; return (new Rewriter).rewrite(this.tokens); }; @@ -71,7 +71,7 @@ id = new String(id); id.reserved = true; } else if (__indexOf.call(RESERVED, id) >= 0) { - this.identifierError(id); + this.error("Reserved word \"" + word + "\""); } } if (!forcedIdentifier) { @@ -323,7 +323,7 @@ prev = last(this.tokens); if (value === '=' && prev) { if (!prev[1].reserved && (_ref3 = prev[1], __indexOf.call(JS_FORBIDDEN, _ref3) >= 0)) { - this.assignmentError(); + this.error("Reserved word \"" + (this.value()) + "\" can't be assigned"); } if ((_ref4 = prev[1]) === '||' || _ref4 === '&&') { prev[0] = 'COMPOUND_ASSIGN'; @@ -376,7 +376,7 @@ indent = options.indent, herecomment = options.herecomment; if (herecomment) { if (HEREDOC_ILLEGAL.test(doc)) { - this.carp("block comment cannot contain \"*/\", starting"); + this.error("block comment cannot contain \"*/\", starting"); } if (doc.indexOf('\n') <= 0) return doc; } else { @@ -420,12 +420,6 @@ Lexer.prototype.closeIndentation = function() { return this.outdentToken(this.indent); }; - Lexer.prototype.identifierError = function(word) { - throw SyntaxError("Reserved word \"" + word + "\" on line " + (this.line + 1)); - }; - Lexer.prototype.assignmentError = function() { - throw SyntaxError("Reserved word \"" + (this.value()) + "\" on line " + (this.line + 1) + " can't be assigned"); - }; Lexer.prototype.balancedString = function(str, end) { var i, letter, match, prev, stack, _ref3; stack = [end]; @@ -451,7 +445,7 @@ } prev = letter; } - return this.carp("missing " + (stack.pop()) + ", starting"); + return this.error("missing " + (stack.pop()) + ", starting"); }; Lexer.prototype.interpolateString = function(str, options) { var expr, heredoc, i, inner, interpolated, len, letter, nested, pi, regex, tag, tokens, value, _len, _ref3, _ref4, _ref5; @@ -510,7 +504,7 @@ Lexer.prototype.pair = function(tag) { var size, wanted; if (tag !== (wanted = last(this.ends))) { - if ('OUTDENT' !== wanted) this.carp("unmatched " + tag); + if ('OUTDENT' !== wanted) this.error("unmatched " + tag); this.indent -= size = last(this.indents); this.outdentToken(size, true); return this.pair(tag); @@ -547,7 +541,7 @@ body = body.replace(RegExp("" + quote, "g"), '\\$&'); return quote + this.escapeLines(body, heredoc) + quote; }; - Lexer.prototype.carp = function(message) { + Lexer.prototype.error = function(message) { throw SyntaxError("" + message + " on line " + (this.line + 1)); }; return Lexer; diff --git a/src/lexer.coffee b/src/lexer.coffee index 3380f96a..621b4f77 100644 --- a/src/lexer.coffee +++ b/src/lexer.coffee @@ -61,7 +61,7 @@ exports.Lexer = class Lexer @literalToken() @closeIndentation() - @carp "missing #{tag}" if tag = @ends.pop() + @error "missing #{tag}" if tag = @ends.pop() return @tokens if opts.rewrite is off (new Rewriter).rewrite @tokens @@ -112,7 +112,7 @@ exports.Lexer = class Lexer id = new String id id.reserved = yes else if id in RESERVED - @identifierError id + @error "Reserved word \"#{word}\"" unless forcedIdentifier id = COFFEE_ALIAS_MAP[id] if id in COFFEE_ALIASES @@ -322,7 +322,8 @@ exports.Lexer = class Lexer tag = value prev = last @tokens if value is '=' and prev - @assignmentError() if not prev[1].reserved and prev[1] in JS_FORBIDDEN + if not prev[1].reserved and prev[1] in JS_FORBIDDEN + @error "Reserved word \"#{@value()}\" can't be assigned" if prev[1] in ['||', '&&'] prev[0] = 'COMPOUND_ASSIGN' prev[1] += '=' @@ -357,7 +358,7 @@ exports.Lexer = class Lexer {indent, herecomment} = options if herecomment if HEREDOC_ILLEGAL.test doc - @carp "block comment cannot contain \"*/\", starting" + @error "block comment cannot contain \"*/\", starting" return doc if doc.indexOf('\n') <= 0 else while match = HEREDOC_INDENT.exec doc @@ -392,16 +393,6 @@ exports.Lexer = class Lexer closeIndentation: -> @outdentToken @indent - # The error for when you try to use a forbidden word in JavaScript as - # an identifier. - identifierError: (word) -> - throw SyntaxError "Reserved word \"#{word}\" on line #{@line + 1}" - - # The error for when you try to assign to a reserved word in JavaScript, - # like "function" or "default". - assignmentError: -> - throw SyntaxError "Reserved word \"#{@value()}\" on line #{@line + 1} can't be assigned" - # Matches a balanced group such as a single or double-quoted string. Pass in # a series of delimiters, all of which must be nested correctly within the # contents of the string. This method allows us to have strings within @@ -428,7 +419,7 @@ exports.Lexer = class Lexer else if end is '"' and prev is '#' and letter is '{' stack.push end = '}' prev = letter - @carp "missing #{ stack.pop() }, starting" + @error "missing #{ stack.pop() }, starting" # Expand variables and expressions inside double-quoted strings using # Ruby-like notation for substitution of arbitrary expressions. @@ -481,7 +472,7 @@ exports.Lexer = class Lexer # correctly balanced throughout the course of the token stream. pair: (tag) -> unless tag is wanted = last @ends - @carp "unmatched #{tag}" unless 'OUTDENT' is wanted + @error "unmatched #{tag}" unless 'OUTDENT' is wanted # Auto-close INDENT to support syntax like this: # # el.click((event) -> @@ -524,9 +515,10 @@ exports.Lexer = class Lexer if contents in ['\n', quote] then contents else match body = body.replace /// #{quote} ///g, '\\$&' quote + @escapeLines(body, heredoc) + quote - - # Throws a syntax error from current `@line`. - carp: (message) -> throw SyntaxError "#{message} on line #{ @line + 1}" + + # Throws a syntax error on the current `@line`. + error: (message) -> + throw SyntaxError "#{message} on line #{ @line + 1}" # Constants # ---------