Skip to content
This repository
Browse code

% can now be used as a percent

It is currently mutually exclusive with mod. A compile-time option forces you to choose one over the other.  The % term must be the second argument to a binary operator.
  • Loading branch information...
commit 832ed113251c797b0a538f68137dffd2fbebd00d 1 parent 0aad716
Dave DeLong authored December 16, 2011
6  DDMathParser/DDExpression.h
@@ -16,7 +16,11 @@ typedef enum {
16 16
 
17 17
 @class DDMathEvaluator, DDParser;
18 18
 
19  
-@interface DDExpression : NSObject <NSCoding>
  19
+@interface DDExpression : NSObject <NSCoding> {
  20
+    DDExpression *_parentExpression;
  21
+}
  22
+
  23
+@property (nonatomic, readonly) DDExpression *parentExpression;
20 24
 
21 25
 + (id) expressionFromString:(NSString *)expressionString error:(NSError **)error;
22 26
 
6  DDMathParser/DDExpression.m
@@ -19,6 +19,8 @@
19 19
 
20 20
 @implementation DDExpression
21 21
 
  22
+@synthesize parentExpression=_parentExpression;
  23
+
22 24
 + (id) expressionFromString:(NSString *)expressionString error:(NSError **)error {
23 25
     DDParser *parser = [DDParser parserWithString:expressionString error:error];
24 26
     return [parser parsedExpressionWithError:error];
@@ -105,4 +107,8 @@ - (void)encodeWithCoder:(NSCoder *)aCoder {
105 107
     return;
106 108
 }
107 109
 
  110
+- (void)_setParentExpression:(DDExpression *)parent {
  111
+    _parentExpression = parent;
  112
+}
  113
+
108 114
 @end
1  DDMathParser/DDParserTypes.h
@@ -43,6 +43,7 @@ extern NSString *const DDOperatorModulo;
43 43
 extern NSString *const DDOperatorBitwiseNot;
44 44
 extern NSString *const DDOperatorFactorial;
45 45
 extern NSString *const DDOperatorDegree;
  46
+extern NSString *const DDOperatorPercent;
46 47
 extern NSString *const DDOperatorPower;
47 48
 extern NSString *const DDOperatorParenthesisOpen;
48 49
 extern NSString *const DDOperatorParenthesisClose;
1  DDMathParser/DDParserTypes.m
@@ -31,6 +31,7 @@
31 31
 NSString *const DDOperatorBitwiseNot = @"not";
32 32
 NSString *const DDOperatorFactorial = @"factorial";
33 33
 NSString *const DDOperatorDegree = @"dtor";
  34
+NSString *const DDOperatorPercent = @"percent";
34 35
 NSString *const DDOperatorPower = @"pow";
35 36
 NSString *const DDOperatorParenthesisOpen = @"open_paren";
36 37
 NSString *const DDOperatorParenthesisClose = @"close_paren";
2  DDMathParser/_DDFunctionExpression.h
@@ -7,7 +7,7 @@
7 7
 //
8 8
 
9 9
 #import <Foundation/Foundation.h>
10  
-#import "DDExpression.h"
  10
+#import "DDExpression_Internal.h"
11 11
 
12 12
 @interface _DDFunctionExpression : DDExpression {
13 13
 	NSString * function;
9  DDMathParser/_DDFunctionExpression.m
@@ -14,6 +14,12 @@
14 14
 #import "_DDVariableExpression.h"
15 15
 #import "DDMathParserMacros.h"
16 16
 
  17
+@interface DDExpression ()
  18
+
  19
+- (void)_setParentExpression:(DDExpression *)parent;
  20
+
  21
+@end
  22
+
17 23
 @implementation _DDFunctionExpression
18 24
 
19 25
 - (id) initWithFunction:(NSString *)f arguments:(NSArray *)a error:(NSError **)error {
@@ -31,6 +37,9 @@ - (id) initWithFunction:(NSString *)f arguments:(NSArray *)a error:(NSError **)e
31 37
 		
32 38
 		function = [f copy];
33 39
 		arguments = [a copy];
  40
+        for (DDExpression *argument in arguments) {
  41
+            [argument _setParentExpression:self];
  42
+        }
34 43
 	}
35 44
 	return self;
36 45
 }
1  DDMathParser/_DDFunctionUtilities.h
@@ -43,6 +43,7 @@
43 43
 + (DDMathFunction) ceilFunction;
44 44
 + (DDMathFunction) absFunction;
45 45
 + (DDMathFunction) floorFunction;
  46
++ (DDMathFunction) percentFunction;
46 47
 
47 48
 + (DDMathFunction) sinFunction;
48 49
 + (DDMathFunction) cosFunction;
53  DDMathParser/_DDFunctionUtilities.m
@@ -11,6 +11,7 @@
11 11
 #import "DDExpression.h"
12 12
 #import "DDMathParserMacros.h"
13 13
 #import "DDMathEvaluator.h"
  14
+#import "_DDOperatorInfo.h"
14 15
 
15 16
 #define REQUIRE_N_ARGS(__n) { \
16 17
 if ([arguments count] != (__n)) { \
@@ -510,6 +511,58 @@ + (DDMathFunction) floorFunction {
510 511
 	return DD_AUTORELEASE([function copy]);
511 512
 }
512 513
 
  514
++ (DDMathFunction) percentFunction {
  515
+    DDMathFunction function = ^ DDExpression* (NSArray *arguments, NSDictionary *variables, DDMathEvaluator *evaluator, NSError **error) {
  516
+        REQUIRE_N_ARGS(1);
  517
+        
  518
+        DDExpression *percentArgument = [arguments objectAtIndex:0];
  519
+        DDExpression *percentExpression = [percentArgument parentExpression];
  520
+        DDExpression *percentContext = [percentExpression parentExpression];
  521
+        
  522
+        if (percentContext == nil || [percentExpression expressionType] != DDExpressionTypeFunction) {
  523
+            if (error) {
  524
+                *error = ERR(DDErrorCodeInvalidFormat, @"unable to determine context for percent");
  525
+            }
  526
+            return nil;
  527
+        }
  528
+        
  529
+        NSString *parentFunction = [percentContext function];
  530
+        _DDOperatorInfo *operatorInfo = [[_DDOperatorInfo infosForOperatorFunction:parentFunction] lastObject];
  531
+        if (operatorInfo == nil) {
  532
+            if (error) {
  533
+                *error = ERR(DDErrorCodeInvalidFormat, @"unable to determine context for percent");
  534
+            }
  535
+            return nil;
  536
+        }
  537
+        
  538
+        if ([operatorInfo arity] != DDOperatorArityBinary) {
  539
+            if (error) {
  540
+                *error = ERR(DDErrorCodeInvalidFormat, @"unable to determine context for percent");
  541
+            }
  542
+            return nil;
  543
+        }
  544
+        
  545
+        BOOL percentIsRightArgument = ([[percentContext arguments] objectAtIndex:1] == percentExpression);
  546
+        if ([operatorInfo defaultAssociativity] == DDOperatorAssociativityLeft && !percentIsRightArgument) {
  547
+            if (error) {
  548
+                *error = ERR(DDErrorCodeInvalidFormat, @"unable to determine context for percent");
  549
+            }
  550
+            return nil;
  551
+        }
  552
+        
  553
+        DDExpression *baseExpression = [[percentContext arguments] objectAtIndex:0];
  554
+        NSNumber *context = [baseExpression evaluateWithSubstitutions:variables evaluator:evaluator error:error];
  555
+        NSNumber *percent = [percentArgument evaluateWithSubstitutions:variables evaluator:evaluator error:error];
  556
+        
  557
+        RETURN_IF_NIL(context);
  558
+        RETURN_IF_NIL(percent);
  559
+        
  560
+        NSNumber *result = [NSNumber numberWithDouble:[context doubleValue] * ([percent doubleValue] / 100.0)];
  561
+        return [DDExpression numberExpressionWithNumber:result];
  562
+    };
  563
+    return DD_AUTORELEASE([function copy]);
  564
+}
  565
+
513 566
 + (DDMathFunction) sinFunction {
514 567
 	DDMathFunction function = ^ DDExpression* (NSArray *arguments, NSDictionary *variables, DDMathEvaluator *evaluator, NSError **error) {
515 568
 		REQUIRE_N_ARGS(1);
9  DDMathParser/_DDOperatorInfo.m
@@ -8,6 +8,8 @@
8 8
 
9 9
 #import "_DDOperatorInfo.h"
10 10
 
  11
+#define PERCENT_AS_MOD 0
  12
+
11 13
 @implementation _DDOperatorInfo
12 14
 
13 15
 @synthesize arity=_arity;
@@ -164,8 +166,10 @@ + (NSArray *)_buildOperators {
164 166
     [operators addObject:[self infoForOperatorFunction:DDOperatorDivide token:@"\u00f7" arity:DDOperatorArityBinary precedence:precedence associativity:DDOperatorAssociativityLeft]];
165 167
     precedence++;
166 168
     
  169
+#if PERCENT_AS_MOD
167 170
     [operators addObject:[self infoForOperatorFunction:DDOperatorModulo token:@"%" arity:DDOperatorArityBinary precedence:precedence associativity:DDOperatorAssociativityLeft]];
168 171
     precedence++;
  172
+#endif
169 173
     
170 174
     [operators addObject:[self infoForOperatorFunction:DDOperatorBitwiseNot token:@"~" arity:DDOperatorArityUnary precedence:precedence associativity:DDOperatorAssociativityRight]];
171 175
     precedence++;
@@ -183,6 +187,11 @@ + (NSArray *)_buildOperators {
183 187
     [operators addObject:[self infoForOperatorFunction:DDOperatorDegree token:@"\u00ba" arity:DDOperatorArityUnary precedence:precedence associativity:DDOperatorAssociativityLeft]];
184 188
     // \u00b0 is °
185 189
     [operators addObject:[self infoForOperatorFunction:DDOperatorDegree token:@"\u00b0" arity:DDOperatorArityUnary precedence:precedence associativity:DDOperatorAssociativityLeft]];
  190
+    
  191
+#if !PERCENT_AS_MOD
  192
+    [operators addObject:[self infoForOperatorFunction:DDOperatorPercent token:@"%" arity:DDOperatorArityUnary precedence:precedence associativity:DDOperatorAssociativityLeft]];
  193
+#endif
  194
+    
186 195
     precedence++;
187 196
     
188 197
     [operators addObject:[self infoForOperatorFunction:DDOperatorPower token:@"**" arity:DDOperatorArityBinary precedence:precedence associativity:DDOperatorAssociativityRight]];

0 notes on commit 832ed11

Please sign in to comment.
Something went wrong with that request. Please try again.