Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Much more descriptive error codes

  • Loading branch information...
commit e689d4ba76bafb4b0aad462dc469b2a2bdcd475e 1 parent 6f4aa6c
@davedelong authored
View
14 DDMathParser/DDMathEvaluator.m
@@ -109,9 +109,12 @@ - (NSArray *) registeredFunctions {
- (BOOL) functionExpressionFailedToResolve:(_DDFunctionExpression *)functionExpression error:(NSError **)error {
NSString *functionName = [functionExpression function];
if (error) {
- *error = ERR_FUNCTION(functionName, @"unable to resolve function: %@", functionName);
- } else {
- NSLog(@"unable to resolve function: %@", functionName);
+ *error = [NSError errorWithDomain:DDMathParserErrorDomain
+ code:DDErrorCodeUnresolvedFunction
+ userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithFormat:@"unable to resolve function: %@", functionName], NSLocalizedDescriptionKey,
+ functionName, DDUnknownFunctionKey,
+ nil]];
}
return NO;
}
@@ -239,7 +242,7 @@ + (NSDictionary *)_standardRewriteRules {
//subtraction
@"0", @"__exp1 - __exp1",
-
+
//multiplication
@"__exp1", @"1 * __exp1",
@"__exp1", @"__exp1 * 1",
@@ -277,7 +280,8 @@ - (void) _registerStandardFunctions {
[functionMap setObject:container forKey:functionName];
DD_RELEASE(container);
} else {
- NSLog(@"error registering function: %@", functionName);
+ // this would only happen when a function name has been misspelled = programmer error = raise an exception
+ [NSException raise:NSInvalidArgumentException format:@"error registering function: %@", functionName];
}
}
}
View
16 DDMathParser/DDMathParserMacros.h
@@ -10,18 +10,10 @@
#import "DDTypes.h"
-#ifndef ERR_BADARG
-#define ERR_BADARG(_f,...) ([NSError errorWithDomain:DDMathParserErrorDomain code:DDErrorCodeInvalidArgument userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:(_f), ##__VA_ARGS__] forKey:NSLocalizedDescriptionKey]])
-#endif
-
-#ifndef ERR_GENERIC
-#define ERR_GENERIC(_f,...) ([NSError errorWithDomain:DDMathParserErrorDomain code:DDErrorCodeGeneric userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:(_f), ##__VA_ARGS__] forKey:NSLocalizedDescriptionKey]])
+#ifndef ERR_ASSERT
+#define ERR_ASSERT(_e) NSAssert((_e) != nil, @"NULL out error")
#endif
-#ifndef ERR_FUNCTION
-#define ERR_FUNCTION(_func, _f,...) ([NSError errorWithDomain:DDMathParserErrorDomain code:DDErrorCodeGeneric userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSString stringWithFormat:(_f), ##__VA_ARGS__], NSLocalizedDescriptionKey, (_func), DDUnknownFunctionKey, nil]])
+#ifndef ERR
+#define ERR(_c,_f,...) [NSError errorWithDomain:DDMathParserErrorDomain code:(_c) userInfo:[NSDictionary dictionaryWithObject:[NSString stringWithFormat:(_f), ##__VA_ARGS__] forKey:NSLocalizedDescriptionKey]]
#endif
-
-#ifndef ERR_ASSERT
-#define ERR_ASSERT(_e) NSAssert((_e) != nil, @"NULL out error")
-#endif
View
25 DDMathParser/DDMathStringTokenizer.m
@@ -195,7 +195,7 @@ - (BOOL)_processUnknownOperatorToken:(DDMathStringToken *)token withError:(NSErr
if ([token operatorType] == DDOperatorInvalid) {
if (error != nil) {
- *error = ERR_GENERIC(@"unknown precedence for token: %@", token);
+ *error = ERR(DDErrorCodeUnknownOperatorPrecedence, @"unknown precedence for token: %@", token);
}
return NO;
}
@@ -342,6 +342,7 @@ - (DDMathStringToken *)_nextTokenWithError:(NSError **)error {
- (DDMathStringToken *)_parseNumberWithError:(NSError **)error {
ERR_ASSERT(error);
NSUInteger start = _characterIndex;
+ DDMathStringToken *token = nil;
while (DD_IS_DIGIT([self _peekNextCharacter])) {
_characterIndex++;
@@ -379,13 +380,17 @@ - (DDMathStringToken *)_parseNumberWithError:(NSError **)error {
NSUInteger length = _characterIndex - start;
if (length > 0) {
- NSString *rawToken = [NSString stringWithCharacters:(_characters+start) length:length];
- DDMathStringToken *token = [DDMathStringToken mathStringTokenWithToken:rawToken type:DDTokenTypeNumber];
- return token;
+ if (length != 1 || _characters[start] != '.') { // do not recognize "." as a number
+ NSString *rawToken = [NSString stringWithCharacters:(_characters+start) length:length];
+ token = [DDMathStringToken mathStringTokenWithToken:rawToken type:DDTokenTypeNumber];
+ }
}
- *error = ERR_BADARG(@"unable to parse number");
- return nil;
+ if (!token) {
+ _characterIndex = start;
+ *error = ERR(DDErrorCodeInvalidNumber, @"unable to parse number");
+ }
+ return token;
}
- (DDMathStringToken *)_parseFunctionWithError:(NSError **)error {
@@ -411,7 +416,7 @@ - (DDMathStringToken *)_parseFunctionWithError:(NSError **)error {
}
_characterIndex = start;
- *error = ERR_BADARG(@"unable to parse identifier");
+ *error = ERR(DDErrorCodeInvalidIdentifier, @"unable to parse identifier");
return nil;
}
@@ -422,7 +427,7 @@ - (DDMathStringToken *)_parseVariableWithError:(NSError **)error {
DDMathStringToken *token = [self _parseFunctionWithError:error];
if (token == nil) {
_characterIndex = start;
- *error = ERR_BADARG(@"variable names must be at least 1 character long");
+ *error = ERR(DDErrorCodeInvalidVariable, @"variable names must be at least 1 character long");
} else {
token = [DDMathStringToken mathStringTokenWithToken:[token token] type:DDTokenTypeVariable];
*error = nil;
@@ -453,14 +458,14 @@ - (DDMathStringToken *)_parseOperatorWithError:(NSError **)error {
length++;
}
- if (length > 0 && lastGood != nil) {
+ if (lastGood != nil) {
_characterIndex = start+lastGoodLength;
return [DDMathStringToken mathStringTokenWithToken:lastGood type:DDTokenTypeOperator];
}
_characterIndex = start;
- *error = ERR_BADARG(@"%C is not a valid operator", character);
+ *error = ERR(DDErrorCodeInvalidOperator, @"%C is not a valid operator", character);
return nil;
}
View
38 DDMathParser/DDTypes.h
@@ -18,10 +18,34 @@ typedef DDExpression* (^DDMathFunction)(NSArray *, NSDictionary *, DDMathEvaluat
extern NSString * const DDMathParserErrorDomain;
extern NSString * const DDUnknownFunctionKey;
-
-enum {
- DDErrorCodeGeneric = -1,
- DDErrorCodeInvalidArgument = 1,
-};
-
-typedef NSInteger DDErrorCode;
+extern NSString * const DDUnknownVariableKey;
+
+typedef enum {
+ // ERROR CODE // LOCALIZED DESCRIPTION EXAMPLE
+
+ // a generic error
+ DDErrorCodeInvalidFormat = 1,
+
+ // parsing & tokenization errors
+ DDErrorCodeInvalidOperator, //@"%C is not a valid operator"
+ DDErrorCodeInvalidIdentifier, //@"unable to parse identifier
+ DDErrorCodeInvalidVariable, //@"variable names must be at least 1 character long"
+ DDErrorCodeInvalidNumber, //@"unable to parse number"
+ DDErrorCodeUnknownOperatorPrecedence, //@"unknown precedence for token: %@
+
+ // grouping & resolution errors
+ DDErrorCodeImbalancedParentheses, //@"imbalanced parentheses", @"missing parentheses after function %@"
+ DDErrorCodeInvalidOperatorArity, //@"unknown arity for operator: %@"
+ DDErrorCodeBinaryOperatorMissingLeftOperand, //@"no left operand to binary %@"
+ DDErrorCodeBinaryOperatorMissingRightOperand, //@"no right operand to binary %@"
+ DDErrorCodeUnaryOperatorMissingLeftOperand, //@"no left operand to unary %@"
+ DDErrorCodeUnaryOperatorMissingRightOperand, //@"no right operand to unary %@"
+
+ // evaluation errors
+ DDErrorCodeUnresolvedVariable, //@"unable to resolve variable expression: %@"
+ DDErrorCodeUnresolvedFunction, //@"unable to resolve function: %@"
+ DDErrorCodeInvalidFunctionReturnType, //@"invalid return type from %@ function"
+ DDErrorCodeInvalidNumberOfArguments, //@"random() may only have up to 2 arguments"
+ DDErrorCodeInvalidArgument, //@"upper bound (%ld) of random() must be larger than lower bound (%ld)"
+
+} DDErrorCode;
View
3  DDMathParser/DDTypes.m
@@ -10,4 +10,5 @@
NSString * const DDMathParserErrorDomain = @"com.davedelong.ddmathparser";
-NSString * const DDUnknownFunctionKey = @"com.davedelong.ddmathparser.Function";
+NSString * const DDUnknownFunctionKey = @"com.davedelong.ddmathparser.Function";
+NSString * const DDUnknownVariableKey = @"com.davedelong.ddmathparser.Variable";
View
5 DDMathParser/_DDFunctionExpression.m
@@ -22,8 +22,7 @@ - (id) initWithFunction:(NSString *)f arguments:(NSArray *)a error:(NSError **)e
for (id arg in a) {
if ([arg isKindOfClass:[DDExpression class]] == NO) {
if (error != nil) {
- *error = ERR_GENERIC(@"function arguments must be DDExpression objects");
- *error = nil;
+ *error = ERR(DDErrorCodeInvalidArgument, @"function arguments must be DDExpression objects");
}
DD_RELEASE(self);
return nil;
@@ -105,7 +104,7 @@ - (NSNumber *) evaluateWithSubstitutions:(NSDictionary *)substitutions evaluator
numberValue = [evaluator evaluateString:result withSubstitutions:substitutions error:error];
} else {
if (error != nil) {
- *error = ERR_BADARG(@"invalid return type from %@ function", [self function]);
+ *error = ERR(DDErrorCodeInvalidFunctionReturnType, @"invalid return type from %@ function", [self function]);
}
return nil;
}
View
2  DDMathParser/_DDFunctionTerm.m
@@ -74,7 +74,7 @@ - (id)_initWithTokenizer:(DDMathStringTokenizer *)tokenizer error:(NSError **)er
[self _setSubterms:newSubterms];
} else {
- *error = ERR_BADARG(@"missing parentheses after function \"%@\"", t);
+ *error = ERR(DDErrorCodeImbalancedParentheses, @"missing parentheses after function \"%@\"", t);
}
return self;
}
View
10 DDMathParser/_DDFunctionUtilities.m
@@ -15,7 +15,7 @@
#define REQUIRE_N_ARGS(__n) { \
if ([arguments count] != (__n)) { \
if (error != nil) { \
- *error = ERR_GENERIC(@"%@ requires %d argument%@", NSStringFromSelector(_cmd), (__n), ((__n) == 1 ? @"" : @"s")); \
+ *error = ERR(DDErrorCodeInvalidNumberOfArguments, @"%@ requires %d argument%@", NSStringFromSelector(_cmd), (__n), ((__n) == 1 ? @"" : @"s")); \
} \
return nil; \
} \
@@ -23,8 +23,8 @@
#define REQUIRE_GTOE_N_ARGS(__n) { \
if ([arguments count] < (__n)) { \
- if (error != nil) { \
- *error = ERR_GENERIC(@"%@ requires at least %d argument%@", NSStringFromSelector(_cmd), (__n), ((__n) == 1 ? @"" : @"s")); \
+if (error != nil) { \
+ *error = ERR(DDErrorCodeInvalidNumberOfArguments, @"%@ requires at least %d argument%@", NSStringFromSelector(_cmd), (__n), ((__n) == 1 ? @"" : @"s")); \
} \
return nil; \
} \
@@ -388,7 +388,7 @@ + (DDMathFunction) randomFunction {
DDMathFunction function = ^ DDExpression* (NSArray *arguments, NSDictionary *variables, DDMathEvaluator *evaluator, NSError **error) {
if ([arguments count] > 2) {
if (error != nil) {
- *error = ERR_GENERIC(@"random() may only have up to 2 arguments");
+ *error = ERR(DDErrorCodeInvalidNumberOfArguments, @"random() may only have up to 2 arguments");
}
return nil;
}
@@ -413,7 +413,7 @@ + (DDMathFunction) randomFunction {
if ([upperBound integerValue] <= [lowerBound integerValue]) {
if (error != nil) {
- *error = ERR_GENERIC(@"upper bound (%ld) of random() must be larger than lower bound (%ld)", [upperBound integerValue], [lowerBound integerValue]);
+ *error = ERR(DDErrorCodeInvalidArgument, @"upper bound (%ld) of random() must be larger than lower bound (%ld)", [upperBound integerValue], [lowerBound integerValue]);
}
return nil;
}
View
18 DDMathParser/_DDGroupTerm.m
@@ -62,7 +62,7 @@ - (id)_initWithTokenizer:(DDMathStringTokenizer *)tokenizer error:(NSError **)er
// consume the closing parenthesis and verify it exists
if ([tokenizer nextToken] == nil) {
- *error = ERR_BADARG(@"imbalanced parentheses");
+ *error = ERR(DDErrorCodeImbalancedParentheses, @"imbalanced parentheses");
DD_RELEASE(self);
return nil;
}
@@ -115,7 +115,7 @@ - (BOOL)resolveWithParser:(DDParser *)parser error:(NSError **)error {
} else {
// more than one term is left
// but there are no more operators
- *error = ERR_BADARG(@"invalid format: %@", self);
+ *error = ERR(DDErrorCodeInvalidFormat, @"invalid format: %@", self);
return NO;
}
}
@@ -160,7 +160,7 @@ - (BOOL)_reduceTermsAroundOperatorAtIndex:(NSUInteger)index withParser:(DDParser
return [self _reduceUnaryOperatorAtIndex:index withParser:parser error:error];
}
- *error = ERR_BADARG(@"unknown arity for operator: %@", operator);
+ *error = ERR(DDErrorCodeInvalidOperatorArity, @"unknown arity for operator: %@", operator);
return NO;
}
@@ -170,11 +170,11 @@ - (BOOL)_reduceBinaryOperatorAtIndex:(NSUInteger)index withParser:(DDParser *)pa
_DDOperatorTerm *operator = [[self subterms] objectAtIndex:index];
if (index == 0) {
- *error = ERR_BADARG(@"no left operand to binary %@", operator);
+ *error = ERR(DDErrorCodeBinaryOperatorMissingLeftOperand, @"no left operand to binary %@", operator);
return NO;
}
if (index == [[self subterms] count] - 1) {
- *error = ERR_BADARG(@"no right operand to binary %@", operator);
+ *error = ERR(DDErrorCodeBinaryOperatorMissingRightOperand, @"no right operand to binary %@", operator);
return NO;
}
@@ -188,7 +188,7 @@ - (BOOL)_reduceBinaryOperatorAtIndex:(NSUInteger)index withParser:(DDParser *)pa
// this should really only happen when operator is the power operator and the exponent has 1+ negations
rightOperandRange.length++;
if (NSMaxRange(rightOperandRange)-1 >= [[self subterms] count]) {
- *error = ERR_BADARG(@"no right operand to unary %@", rightmostOperand);
+ *error = ERR(DDErrorCodeUnaryOperatorMissingRightOperand, @"no right operand to unary %@", rightmostOperand);
return NO;
}
rightmostOperand = [[self subterms] objectAtIndex:NSMaxRange(rightOperandRange)-1];
@@ -223,7 +223,7 @@ - (BOOL)_reduceUnaryOperatorAtIndex:(NSUInteger)index withParser:(DDParser *)par
if (associativity == DDOperatorAssociativityRight) {
// right associative unary operator (negate, not)
if (index == [[self subterms] count] - 1) {
- *error = ERR_BADARG(@"no right operand to unary %@", operator);
+ *error = ERR(DDErrorCodeUnaryOperatorMissingRightOperand, @"no right operand to unary %@", operator);
return NO;
}
@@ -233,7 +233,7 @@ - (BOOL)_reduceUnaryOperatorAtIndex:(NSUInteger)index withParser:(DDParser *)par
} else {
// left associative unary operator (factorial)
if (index == 0) {
- *error = ERR_BADARG(@"no left operand to unary %@", operator);
+ *error = ERR(DDErrorCodeUnaryOperatorMissingLeftOperand, @"no left operand to unary %@", operator);
return NO;
}
@@ -260,7 +260,7 @@ - (DDExpression *)expressionWithError:(NSError **)error {
_DDParserTerm *term = [[self subterms] objectAtIndex:0];
return [term expressionWithError:error];
}
- *error = ERR_GENERIC(@"Unable to create expression from term: %@", self);
+ *error = ERR(DDErrorCodeInvalidFormat, @"Unable to create expression from term: %@", self);
return nil;
}
View
4 DDMathParser/_DDParserTerm.m
@@ -66,7 +66,7 @@ + (id)termWithTokenizer:(DDMathStringTokenizer *)tokenizer error:(NSError **)err
return DD_AUTORELEASE(term);
} else {
- *error = ERR_GENERIC(@"can't create a term with a nil token");
+ *error = ERR(DDErrorCodeInvalidFormat, @"can't create a term with a nil token");
}
return nil;
}
@@ -99,7 +99,7 @@ - (BOOL)resolveWithParser:(DDParser *)parser error:(NSError **)error {
- (DDExpression *)expressionWithError:(NSError **)error {
ERR_ASSERT(error);
- *error = ERR_GENERIC(@"Subclasses must override the -%@ method", NSStringFromSelector(_cmd));
+ [NSException raise:NSInvalidArgumentException format:@"Subclasses must override the -%@ method", NSStringFromSelector(_cmd)];
return nil;
}
View
7 DDMathParser/_DDVariableExpression.m
@@ -67,7 +67,12 @@ - (NSNumber *) evaluateWithSubstitutions:(NSDictionary *)substitutions evaluator
return variableValue;
}
if (error != nil) {
- *error = ERR_GENERIC(@"unable to resolve variable expression: %@", self);
+ *error = [NSError errorWithDomain:DDMathParserErrorDomain
+ code:DDErrorCodeUnresolvedVariable
+ userInfo:[NSDictionary dictionaryWithObjectsAndKeys:
+ [NSString stringWithFormat:@"unable to resolve variable: %@", self], NSLocalizedDescriptionKey,
+ [self variable], DDUnknownVariableKey,
+ nil]];
}
return nil;
}
Please sign in to comment.
Something went wrong with that request. Please try again.