|
233 | 233 | ch === "_";
|
234 | 234 | }
|
235 | 235 |
|
| 236 | + function createErrorClass(className) { |
| 237 | + var ExtendedError = function (message) { |
| 238 | + Error.call(this, message); |
| 239 | + this.name = className; |
| 240 | + } |
| 241 | + ExtendedError.prototype = Object.create(Error.prototype); |
| 242 | + ExtendedError.prototype.constructor = ExtendedError; |
| 243 | + |
| 244 | + return ExtendedError; |
| 245 | + } |
| 246 | + |
| 247 | + var LexerError = createErrorClass("LexerError"); |
| 248 | + |
236 | 249 | function Lexer() {
|
237 | 250 | }
|
238 | 251 | Lexer.prototype = {
|
|
304 | 317 | tokens.push({type: TOK_PIPE, value: "|", start: start});
|
305 | 318 | }
|
306 | 319 | } else {
|
307 |
| - var error = new Error("Unknown character:" + stream[this._current]); |
308 |
| - error.name = "LexerError"; |
| 320 | + var error = new LexerError("Unknown character:" + stream[this._current]); |
309 | 321 | throw error;
|
310 | 322 | }
|
311 | 323 | }
|
|
500 | 512 | bindingPower[TOK_LBRACKET] = 55;
|
501 | 513 | bindingPower[TOK_LPAREN] = 60;
|
502 | 514 |
|
| 515 | + var ParserError = createErrorClass("ParserError"); |
| 516 | + |
503 | 517 | function Parser() {
|
504 | 518 | }
|
505 | 519 |
|
|
510 | 524 | var ast = this.expression(0);
|
511 | 525 | if (this._lookahead(0) !== TOK_EOF) {
|
512 | 526 | var t = this._lookaheadToken(0);
|
513 |
| - var error = new Error( |
| 527 | + var error = new ParserError( |
514 | 528 | "Unexpected token type: " + t.type + ", value: " + t.value);
|
515 |
| - error.name = "ParserError"; |
516 | 529 | throw error;
|
517 | 530 | }
|
518 | 531 | return ast;
|
|
562 | 575 | case TOK_QUOTEDIDENTIFIER:
|
563 | 576 | var node = {type: "Field", name: token.value};
|
564 | 577 | if (this._lookahead(0) === TOK_LPAREN) {
|
565 |
| - throw new Error("Quoted identifier not allowed for function names."); |
| 578 | + throw new ParserError("Quoted identifier not allowed for function names."); |
566 | 579 | }
|
567 | 580 | return node;
|
568 | 581 | case TOK_NOT:
|
|
704 | 717 | this._advance();
|
705 | 718 | } else {
|
706 | 719 | var t = this._lookaheadToken(0);
|
707 |
| - var error = new Error("Expected " + tokenType + ", got: " + t.type); |
708 |
| - error.name = "ParserError"; |
| 720 | + var error = new ParserError("Expected " + tokenType + ", got: " + t.type); |
709 | 721 | throw error;
|
710 | 722 | }
|
711 | 723 | },
|
712 | 724 |
|
713 | 725 | _errorToken: function(token) {
|
714 |
| - var error = new Error("Invalid token (" + |
| 726 | + var error = new ParserError("Invalid token (" + |
715 | 727 | token.type + "): \"" +
|
716 | 728 | token.value + "\"");
|
717 |
| - error.name = "ParserError"; |
718 | 729 | throw error;
|
719 | 730 | },
|
720 | 731 |
|
|
759 | 770 | this._advance();
|
760 | 771 | } else {
|
761 | 772 | var t = this._lookahead(0);
|
762 |
| - var error = new Error("Syntax error, unexpected token: " + |
| 773 | + var error = new ParserError("Syntax error, unexpected token: " + |
763 | 774 | t.value + "(" + t.type + ")");
|
764 |
| - error.name = "Parsererror"; |
765 | 775 | throw error;
|
766 | 776 | }
|
767 | 777 | currentToken = this._lookahead(0);
|
|
805 | 815 | right = this._parseDotRHS(rbp);
|
806 | 816 | } else {
|
807 | 817 | var t = this._lookaheadToken(0);
|
808 |
| - var error = new Error("Sytanx error, unexpected token: " + |
| 818 | + var error = new ParserError("Syntax error, unexpected token: " + |
809 | 819 | t.value + "(" + t.type + ")");
|
810 |
| - error.name = "ParserError"; |
811 | 820 | throw error;
|
812 | 821 | }
|
813 | 822 | return right;
|
|
821 | 830 | if (this._lookahead(0) === TOK_COMMA) {
|
822 | 831 | this._match(TOK_COMMA);
|
823 | 832 | if (this._lookahead(0) === TOK_RBRACKET) {
|
824 |
| - throw new Error("Unexpected token Rbracket"); |
| 833 | + throw new ParserError("Unexpected token Rbracket"); |
825 | 834 | }
|
826 | 835 | }
|
827 | 836 | }
|
|
836 | 845 | for (;;) {
|
837 | 846 | keyToken = this._lookaheadToken(0);
|
838 | 847 | if (identifierTypes.indexOf(keyToken.type) < 0) {
|
839 |
| - throw new Error("Expecting an identifier token, got: " + |
| 848 | + throw new ParserError("Expecting an identifier token, got: " + |
840 | 849 | keyToken.type);
|
841 | 850 | }
|
842 | 851 | keyName = keyToken.value;
|
|
856 | 865 | }
|
857 | 866 | };
|
858 | 867 |
|
| 868 | + var InterpreterError = createErrorClass("InterpreterError"); |
859 | 869 |
|
860 | 870 | function TreeInterpreter(runtime) {
|
861 | 871 | this.runtime = runtime;
|
|
997 | 1007 | result = first <= second;
|
998 | 1008 | break;
|
999 | 1009 | default:
|
1000 |
| - throw new Error("Unknown comparator: " + node.name); |
| 1010 | + throw new InterpreterError("Unknown comparator: " + node.name); |
1001 | 1011 | }
|
1002 | 1012 | return result;
|
1003 | 1013 | case TOK_FLATTEN:
|
|
1073 | 1083 | refNode.jmespathType = TOK_EXPREF;
|
1074 | 1084 | return refNode;
|
1075 | 1085 | default:
|
1076 |
| - throw new Error("Unknown node type: " + node.type); |
| 1086 | + throw new InterpreterError("Unknown node type: " + node.type); |
1077 | 1087 | }
|
1078 | 1088 | },
|
1079 | 1089 |
|
|
1122 | 1132 |
|
1123 | 1133 | };
|
1124 | 1134 |
|
| 1135 | + var RuntimeError = createErrorClass("RuntimeError"); |
| 1136 | + var ArgumentError = createErrorClass("ArgumentError"); |
| 1137 | + var TypeMismatchError = createErrorClass("TypeMismatchError"); |
| 1138 | + |
1125 | 1139 | function Runtime(interpreter) {
|
1126 | 1140 | this._interpreter = interpreter;
|
1127 | 1141 | this.functionTable = {
|
|
1209 | 1223 | callFunction: function(name, resolvedArgs) {
|
1210 | 1224 | var functionEntry = this.functionTable[name];
|
1211 | 1225 | if (functionEntry === undefined) {
|
1212 |
| - throw new Error("Unknown function: " + name + "()"); |
| 1226 | + throw new RuntimeError("Unknown function: " + name + "()"); |
1213 | 1227 | }
|
1214 | 1228 | this._validateArgs(name, resolvedArgs, functionEntry._signature);
|
1215 | 1229 | return functionEntry._func.call(this, resolvedArgs);
|
|
1225 | 1239 | if (signature[signature.length - 1].variadic) {
|
1226 | 1240 | if (args.length < signature.length) {
|
1227 | 1241 | pluralized = signature.length === 1 ? " argument" : " arguments";
|
1228 |
| - throw new Error("ArgumentError: " + name + "() " + |
| 1242 | + throw new ArgumentError(name + "() " + |
1229 | 1243 | "takes at least" + signature.length + pluralized +
|
1230 | 1244 | " but received " + args.length);
|
1231 | 1245 | }
|
1232 | 1246 | } else if (args.length !== signature.length) {
|
1233 | 1247 | pluralized = signature.length === 1 ? " argument" : " arguments";
|
1234 |
| - throw new Error("ArgumentError: " + name + "() " + |
| 1248 | + throw new ArgumentError(name + "() " + |
1235 | 1249 | "takes " + signature.length + pluralized +
|
1236 | 1250 | " but received " + args.length);
|
1237 | 1251 | }
|
|
1254 | 1268 | return TYPE_NAME_TABLE[typeIdentifier];
|
1255 | 1269 | })
|
1256 | 1270 | .join(',');
|
1257 |
| - throw new Error("TypeError: " + name + "() " + |
| 1271 | + throw new TypeMismatchError(name + "() " + |
1258 | 1272 | "expected argument " + (i + 1) +
|
1259 | 1273 | " to be type " + expected +
|
1260 | 1274 | " but received type " +
|
|
1547 | 1561 | var requiredType = this._getTypeName(
|
1548 | 1562 | interpreter.visit(exprefNode, sortedArray[0]));
|
1549 | 1563 | if ([TYPE_NUMBER, TYPE_STRING].indexOf(requiredType) < 0) {
|
1550 |
| - throw new Error("TypeError"); |
| 1564 | + throw new TypeMismatchError("Array elements must be of type Number or String to sort"); |
1551 | 1565 | }
|
1552 | 1566 | var that = this;
|
1553 | 1567 | // In order to get a stable sort out of an unstable
|
|
1565 | 1579 | var exprA = interpreter.visit(exprefNode, a[1]);
|
1566 | 1580 | var exprB = interpreter.visit(exprefNode, b[1]);
|
1567 | 1581 | if (that._getTypeName(exprA) !== requiredType) {
|
1568 |
| - throw new Error( |
1569 |
| - "TypeError: expected " + requiredType + ", received " + |
| 1582 | + throw new TypeMismatchError( |
| 1583 | + "expected " + requiredType + ", received " + |
1570 | 1584 | that._getTypeName(exprA));
|
1571 | 1585 | } else if (that._getTypeName(exprB) !== requiredType) {
|
1572 |
| - throw new Error( |
1573 |
| - "TypeError: expected " + requiredType + ", received " + |
| 1586 | + throw new TypeMismatchError( |
| 1587 | + "expected " + requiredType + ", received " + |
1574 | 1588 | that._getTypeName(exprB));
|
1575 | 1589 | }
|
1576 | 1590 | if (exprA > exprB) {
|
|
1631 | 1645 | var keyFunc = function(x) {
|
1632 | 1646 | var current = interpreter.visit(exprefNode, x);
|
1633 | 1647 | if (allowedTypes.indexOf(that._getTypeName(current)) < 0) {
|
1634 |
| - var msg = "TypeError: expected one of " + allowedTypes + |
| 1648 | + var msg = "expected one of " + allowedTypes + |
1635 | 1649 | ", received " + that._getTypeName(current);
|
1636 |
| - throw new Error(msg); |
| 1650 | + throw new TypeMismatchError(msg); |
1637 | 1651 | }
|
1638 | 1652 | return current;
|
1639 | 1653 | };
|
|
0 commit comments