diff --git a/src/ol/expression/lexer.js b/src/ol/expression/lexer.js index 7d1e0edd7f..9b17e00845 100644 --- a/src/ol/expression/lexer.js +++ b/src/ol/expression/lexer.js @@ -17,8 +17,10 @@ goog.provide('ol.expression.Char'); // TODO: remove this - see #785 goog.provide('ol.expression.Lexer'); goog.provide('ol.expression.Token'); goog.provide('ol.expression.TokenType'); +goog.provide('ol.expression.UnexpectedToken'); goog.require('goog.asserts'); +goog.require('goog.debug.Error'); /** @@ -143,7 +145,7 @@ ol.expression.Lexer = function(source) { ol.expression.Lexer.prototype.expect = function(value) { var match = this.match(value); if (!match) { - this.throwUnexpected({ + throw new ol.expression.UnexpectedToken({ type: ol.expression.TokenType.UNKNOWN, value: this.getCurrentChar_(), index: this.index_ @@ -468,7 +470,7 @@ ol.expression.Lexer.prototype.scanHexLiteral_ = function(code) { } if (str.length === 0 || this.isIdentifierStart_(code)) { - this.throwUnexpected({ + throw new ol.expression.UnexpectedToken({ type: ol.expression.TokenType.UNKNOWN, value: String.fromCharCode(code), index: this.index_ @@ -567,7 +569,7 @@ ol.expression.Lexer.prototype.scanNumericLiteral_ = function(code) { // numbers like 09 not allowed if (this.isDecimalDigit_(nextCode)) { - this.throwUnexpected({ + throw new ol.expression.UnexpectedToken({ type: ol.expression.TokenType.UNKNOWN, value: String.fromCharCode(nextCode), index: this.index_ @@ -612,7 +614,7 @@ ol.expression.Lexer.prototype.scanNumericLiteral_ = function(code) { } if (!this.isDecimalDigit_(code)) { - this.throwUnexpected({ + throw new ol.expression.UnexpectedToken({ type: ol.expression.TokenType.UNKNOWN, value: String.fromCharCode(code), index: this.index_ @@ -628,7 +630,7 @@ ol.expression.Lexer.prototype.scanNumericLiteral_ = function(code) { } if (this.isIdentifierStart_(code)) { - this.throwUnexpected({ + throw new ol.expression.UnexpectedToken({ type: ol.expression.TokenType.UNKNOWN, value: String.fromCharCode(code), index: this.index_ @@ -672,7 +674,7 @@ ol.expression.Lexer.prototype.scanOctalLiteral_ = function(code) { code = this.getCurrentCharCode_(); if (this.isIdentifierStart_(code) || this.isDecimalDigit_(code)) { - this.throwUnexpected({ + throw new ol.expression.UnexpectedToken({ type: ol.expression.TokenType.UNKNOWN, value: String.fromCharCode(code), index: this.index_ - 1 @@ -790,19 +792,11 @@ ol.expression.Lexer.prototype.scanPunctuator_ = function(code) { }; } - this.throwUnexpected({ + throw new ol.expression.UnexpectedToken({ type: ol.expression.TokenType.UNKNOWN, value: String.fromCharCode(code), index: this.index_ }); - - // This code is unreachable, but the compiler complains with - // JSC_MISSING_RETURN_STATEMENT without it. - return { - type: ol.expression.TokenType.UNKNOWN, - value: '', - index: 0 - }; }; @@ -841,7 +835,7 @@ ol.expression.Lexer.prototype.scanStringLiteral_ = function(quote) { if (quote !== 0) { // unterminated string literal - this.throwUnexpected(this.peek()); + throw new ol.expression.UnexpectedToken(this.peek()); } return { @@ -879,13 +873,28 @@ ol.expression.Lexer.prototype.skipWhitespace_ = function() { }; + /** - * Throw an error about an unexpected token. + * Error object for unexpected tokens. * @param {ol.expression.Token} token The unexpected token. + * @param {string=} opt_message Custom error message. + * @constructor + * @extends {goog.debug.Error} */ -ol.expression.Lexer.prototype.throwUnexpected = function(token) { - var error = new Error('Unexpected token at ' + token.index + ' : ' + - token.value); - error.token = token; - throw error; +ol.expression.UnexpectedToken = function(token, opt_message) { + var message = goog.isDef(opt_message) ? opt_message : + 'Unexpected token ' + token.value + ' at index ' + token.index; + + goog.debug.Error.call(this, message); + + /** + * @type {ol.expression.Token} + */ + this.token = token; + }; +goog.inherits(ol.expression.UnexpectedToken, goog.debug.Error); + + +/** @override */ +ol.expression.UnexpectedToken.prototype.name = 'UnexpectedToken'; diff --git a/src/ol/expression/parser.js b/src/ol/expression/parser.js index 615aca3a61..57627039b8 100644 --- a/src/ol/expression/parser.js +++ b/src/ol/expression/parser.js @@ -32,6 +32,7 @@ goog.require('ol.expression.Member'); goog.require('ol.expression.Not'); goog.require('ol.expression.Token'); goog.require('ol.expression.TokenType'); +goog.require('ol.expression.UnexpectedToken'); @@ -222,7 +223,7 @@ ol.expression.Parser.prototype.parse = function(source) { var expr = this.parseExpression_(lexer); var token = lexer.peek(); if (token.type !== ol.expression.TokenType.EOF) { - lexer.throwUnexpected(token); + throw new ol.expression.UnexpectedToken(token); } return expr; }; @@ -353,7 +354,7 @@ ol.expression.Parser.prototype.parseLeftHandSideExpression_ = function(lexer) { // only allow calls on identifiers (e.g. `foo()` not `foo.bar()`) if (!(expr instanceof ol.expression.Identifier)) { // TODO: more helpful error messages for restricted syntax - lexer.throwUnexpected(token); + throw new ol.expression.UnexpectedToken(token); } var args = this.parseArguments_(lexer); expr = this.createCallExpression_(expr, args); @@ -385,7 +386,7 @@ ol.expression.Parser.prototype.parseNonComputedMember_ = function(lexer) { token.type !== ol.expression.TokenType.KEYWORD && token.type !== ol.expression.TokenType.BOOLEAN_LITERAL && token.type !== ol.expression.TokenType.NULL_LITERAL) { - lexer.throwUnexpected(token); + throw new ol.expression.UnexpectedToken(token); } return this.createIdentifier_(String(token.value)); @@ -420,10 +421,8 @@ ol.expression.Parser.prototype.parsePrimaryExpression_ = function(lexer) { } else if (type === ol.expression.TokenType.NULL_LITERAL) { expr = this.createLiteral_(null); } else { - lexer.throwUnexpected(token); + throw new ol.expression.UnexpectedToken(token); } - // the compiler doesn't recognize that we have covered all cases here - goog.asserts.assert(goog.isDef(expr)); return expr; };