|
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