Implemented Expression Evaluation/Parsing with Proper Error Handling
This commit is contained in:
@@ -8,6 +8,16 @@
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
3B52CEC119BB9FA900CEDCFC /* MathKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B85830D19BB5E5500D76A8D /* MathKit.framework */; };
|
||||
3B52CED019BE509C00CEDCFC /* MPParseError.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B52CECE19BE509C00CEDCFC /* MPParseError.h */; };
|
||||
3B52CED119BE509C00CEDCFC /* MPParseError.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B52CECF19BE509C00CEDCFC /* MPParseError.m */; };
|
||||
3B52CEDC19BEE63000CEDCFC /* NSRegularExpression+MPParsingAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B52CEDA19BEE63000CEDCFC /* NSRegularExpression+MPParsingAdditions.h */; };
|
||||
3B52CEDD19BEE63000CEDCFC /* NSRegularExpression+MPParsingAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B52CEDB19BEE63000CEDCFC /* NSRegularExpression+MPParsingAdditions.m */; };
|
||||
3B52CEE219C070B900CEDCFC /* MPParsedProduct.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B52CEE019C070B900CEDCFC /* MPParsedProduct.h */; };
|
||||
3B52CEE319C070B900CEDCFC /* MPParsedProduct.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B52CEE119C070B900CEDCFC /* MPParsedProduct.m */; };
|
||||
3B52CEE619C0755300CEDCFC /* MPElementParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B52CEE419C0755300CEDCFC /* MPElementParser.h */; };
|
||||
3B52CEE719C0755300CEDCFC /* MPElementParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B52CEE519C0755300CEDCFC /* MPElementParser.m */; };
|
||||
3B71432D19C0A1FC005A184E /* MPParsedFactor.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B71432B19C0A1FC005A184E /* MPParsedFactor.h */; };
|
||||
3B71432E19C0A1FC005A184E /* MPParsedFactor.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B71432C19C0A1FC005A184E /* MPParsedFactor.m */; };
|
||||
3B74BFB319A4C51800E5B5DE /* CoreText.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3B74BFB219A4C51800E5B5DE /* CoreText.framework */; };
|
||||
3B85830E19BB5E5500D76A8D /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BF9976E18DE623E009CF6C4 /* Cocoa.framework */; };
|
||||
3B85831419BB5E5500D76A8D /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 3B85831219BB5E5500D76A8D /* InfoPlist.strings */; };
|
||||
@@ -19,8 +29,6 @@
|
||||
3B85833919BB63C500D76A8D /* MPExpressionElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BFAC3961997B67400B3EF67 /* MPExpressionElement.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3B85833A19BB63D400D76A8D /* MPFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B87E35E19009D5F00259938 /* MPFunction.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3B85833E19BB651400D76A8D /* MPExpressionEvaluator.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BC46B4719B38C980033F13A /* MPExpressionEvaluator.h */; };
|
||||
3B85833F19BB651400D76A8D /* MPElementParser.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B85830519BB573A00D76A8D /* MPElementParser.h */; };
|
||||
3B85834019BB651400D76A8D /* MPParsedElement.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BE9C4B119B9CC70002CC508 /* MPParsedElement.h */; };
|
||||
3B85834119BB651E00D76A8D /* MPRangePath.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B87E35B1900933200259938 /* MPRangePath.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3B85834219BB652900D76A8D /* MPException.h in Headers */ = {isa = PBXBuildFile; fileRef = 3B0F69A719028BC600817707 /* MPException.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3B85834319BB653700D76A8D /* MPSumFunction.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BB09EC71906FD830080A5ED /* MPSumFunction.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
@@ -37,8 +45,6 @@
|
||||
3BBEA93519BB79A700133766 /* MPExpression.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BFAC38E1997B61300B3EF67 /* MPExpression.m */; };
|
||||
3BBEA93619BB79A700133766 /* MPFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B87E35F19009D5F00259938 /* MPFunction.m */; };
|
||||
3BBEA93719BB79A700133766 /* MPExpressionEvaluator.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BC46B4819B38C980033F13A /* MPExpressionEvaluator.m */; };
|
||||
3BBEA93819BB79A700133766 /* MPElementParser.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B85830619BB573A00D76A8D /* MPElementParser.m */; };
|
||||
3BBEA93919BB79A700133766 /* MPParsedElement.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BE9C4B219B9CC70002CC508 /* MPParsedElement.m */; };
|
||||
3BBEA93A19BB79A700133766 /* MPSumFunction.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BB09EC81906FD830080A5ED /* MPSumFunction.m */; };
|
||||
3BBEA93B19BB79A700133766 /* MPRangePath.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B87E35C1900933200259938 /* MPRangePath.m */; };
|
||||
3BBEA93C19BB79A700133766 /* MPException.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B0F69A819028C6000817707 /* MPException.m */; };
|
||||
@@ -52,8 +58,6 @@
|
||||
3BBEA94419BB79A700133766 /* MPSumFunctionLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BB09EE0190736160080A5ED /* MPSumFunctionLayout.m */; };
|
||||
3BBEA94F19BB79EF00133766 /* MPExpressionTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3B0F69AB1902A82C00817707 /* MPExpressionTests.m */; };
|
||||
3BBEA95019BB79EF00133766 /* MPRangeTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BBBA3941905704200824E74 /* MPRangeTests.m */; };
|
||||
3BBEA95519BB9B3500133766 /* MPParseError.h in Headers */ = {isa = PBXBuildFile; fileRef = 3BBEA95319BB9B3500133766 /* MPParseError.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
3BBEA95619BB9B3500133766 /* MPParseError.m in Sources */ = {isa = PBXBuildFile; fileRef = 3BBEA95419BB9B3500133766 /* MPParseError.m */; };
|
||||
3BC4660B19B2425A0033F13A /* MPDocument.xib in Resources */ = {isa = PBXBuildFile; fileRef = 3BF9978318DE623E009CF6C4 /* MPDocument.xib */; };
|
||||
3BC4661419B245C60033F13A /* Fonts in Resources */ = {isa = PBXBuildFile; fileRef = 3BC4661319B245C60033F13A /* Fonts */; };
|
||||
3BF9976F18DE623E009CF6C4 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 3BF9976E18DE623E009CF6C4 /* Cocoa.framework */; };
|
||||
@@ -114,10 +118,18 @@
|
||||
3B528D0F199417E10054DB5F /* MPExpressionLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPExpressionLayout.m; sourceTree = "<group>"; };
|
||||
3B528D11199417E90054DB5F /* MPFunctionLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPFunctionLayout.h; sourceTree = "<group>"; };
|
||||
3B528D12199417E90054DB5F /* MPFunctionLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPFunctionLayout.m; sourceTree = "<group>"; };
|
||||
3B52CECE19BE509C00CEDCFC /* MPParseError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPParseError.h; sourceTree = "<group>"; };
|
||||
3B52CECF19BE509C00CEDCFC /* MPParseError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPParseError.m; sourceTree = "<group>"; };
|
||||
3B52CEDA19BEE63000CEDCFC /* NSRegularExpression+MPParsingAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSRegularExpression+MPParsingAdditions.h"; sourceTree = "<group>"; };
|
||||
3B52CEDB19BEE63000CEDCFC /* NSRegularExpression+MPParsingAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSRegularExpression+MPParsingAdditions.m"; sourceTree = "<group>"; };
|
||||
3B52CEE019C070B900CEDCFC /* MPParsedProduct.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPParsedProduct.h; sourceTree = "<group>"; };
|
||||
3B52CEE119C070B900CEDCFC /* MPParsedProduct.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPParsedProduct.m; sourceTree = "<group>"; };
|
||||
3B52CEE419C0755300CEDCFC /* MPElementParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementParser.h; sourceTree = "<group>"; };
|
||||
3B52CEE519C0755300CEDCFC /* MPElementParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementParser.m; sourceTree = "<group>"; };
|
||||
3B688D9819982DF50006B4AB /* MPLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPLayout.m; sourceTree = "<group>"; };
|
||||
3B71432B19C0A1FC005A184E /* MPParsedFactor.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPParsedFactor.h; sourceTree = "<group>"; };
|
||||
3B71432C19C0A1FC005A184E /* MPParsedFactor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPParsedFactor.m; sourceTree = "<group>"; };
|
||||
3B74BFB219A4C51800E5B5DE /* CoreText.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreText.framework; path = System/Library/Frameworks/CoreText.framework; sourceTree = SDKROOT; };
|
||||
3B85830519BB573A00D76A8D /* MPElementParser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPElementParser.h; sourceTree = "<group>"; };
|
||||
3B85830619BB573A00D76A8D /* MPElementParser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPElementParser.m; sourceTree = "<group>"; };
|
||||
3B85830D19BB5E5500D76A8D /* MathKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = MathKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3B85831119BB5E5500D76A8D /* MathKit-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "MathKit-Info.plist"; sourceTree = "<group>"; };
|
||||
3B85831319BB5E5500D76A8D /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = "<group>"; };
|
||||
@@ -141,15 +153,11 @@
|
||||
3BB09EDF190736160080A5ED /* MPSumFunctionLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPSumFunctionLayout.h; sourceTree = "<group>"; };
|
||||
3BB09EE0190736160080A5ED /* MPSumFunctionLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPSumFunctionLayout.m; sourceTree = "<group>"; };
|
||||
3BBBA3941905704200824E74 /* MPRangeTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MPRangeTests.m; path = ../MathPadTests/MPRangeTests.m; sourceTree = "<group>"; };
|
||||
3BBEA95319BB9B3500133766 /* MPParseError.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPParseError.h; sourceTree = "<group>"; };
|
||||
3BBEA95419BB9B3500133766 /* MPParseError.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPParseError.m; sourceTree = "<group>"; };
|
||||
3BC4661319B245C60033F13A /* Fonts */ = {isa = PBXFileReference; lastKnownFileType = folder; path = Fonts; sourceTree = "<group>"; };
|
||||
3BC4661519B365070033F13A /* MPArrayCache.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPArrayCache.h; sourceTree = "<group>"; };
|
||||
3BC4661619B365070033F13A /* MPArrayCache.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPArrayCache.m; sourceTree = "<group>"; };
|
||||
3BC46B4719B38C980033F13A /* MPExpressionEvaluator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPExpressionEvaluator.h; sourceTree = "<group>"; };
|
||||
3BC46B4819B38C980033F13A /* MPExpressionEvaluator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPExpressionEvaluator.m; sourceTree = "<group>"; };
|
||||
3BE9C4B119B9CC70002CC508 /* MPParsedElement.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MPParsedElement.h; sourceTree = "<group>"; };
|
||||
3BE9C4B219B9CC70002CC508 /* MPParsedElement.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MPParsedElement.m; sourceTree = "<group>"; };
|
||||
3BF9976B18DE623E009CF6C4 /* MathPad.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = MathPad.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3BF9976E18DE623E009CF6C4 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
|
||||
3BF9977118DE623E009CF6C4 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
@@ -365,6 +373,8 @@
|
||||
3BFAC39B1997BC7600B3EF67 /* NSString+MPExpressionElement.m */,
|
||||
3BB09EDC190728220080A5ED /* NSIndexPath+MPAdditions.h */,
|
||||
3BB09EDD190728220080A5ED /* NSIndexPath+MPAdditions.m */,
|
||||
3B52CEDA19BEE63000CEDCFC /* NSRegularExpression+MPParsingAdditions.h */,
|
||||
3B52CEDB19BEE63000CEDCFC /* NSRegularExpression+MPParsingAdditions.m */,
|
||||
);
|
||||
name = Helpers;
|
||||
sourceTree = "<group>";
|
||||
@@ -374,12 +384,14 @@
|
||||
children = (
|
||||
3BC46B4719B38C980033F13A /* MPExpressionEvaluator.h */,
|
||||
3BC46B4819B38C980033F13A /* MPExpressionEvaluator.m */,
|
||||
3B85830519BB573A00D76A8D /* MPElementParser.h */,
|
||||
3B85830619BB573A00D76A8D /* MPElementParser.m */,
|
||||
3BBEA95319BB9B3500133766 /* MPParseError.h */,
|
||||
3BBEA95419BB9B3500133766 /* MPParseError.m */,
|
||||
3BE9C4B119B9CC70002CC508 /* MPParsedElement.h */,
|
||||
3BE9C4B219B9CC70002CC508 /* MPParsedElement.m */,
|
||||
3B52CEE419C0755300CEDCFC /* MPElementParser.h */,
|
||||
3B52CEE519C0755300CEDCFC /* MPElementParser.m */,
|
||||
3B52CEE019C070B900CEDCFC /* MPParsedProduct.h */,
|
||||
3B52CEE119C070B900CEDCFC /* MPParsedProduct.m */,
|
||||
3B71432B19C0A1FC005A184E /* MPParsedFactor.h */,
|
||||
3B71432C19C0A1FC005A184E /* MPParsedFactor.m */,
|
||||
3B52CECE19BE509C00CEDCFC /* MPParseError.h */,
|
||||
3B52CECF19BE509C00CEDCFC /* MPParseError.m */,
|
||||
);
|
||||
name = Evaluation;
|
||||
sourceTree = "<group>";
|
||||
@@ -481,21 +493,23 @@
|
||||
3B85833819BB63BD00D76A8D /* MPExpression.h in Headers */,
|
||||
3B85833919BB63C500D76A8D /* MPExpressionElement.h in Headers */,
|
||||
3B85834419BB654D00D76A8D /* NSString+MPExpressionElement.h in Headers */,
|
||||
3BBEA95519BB9B3500133766 /* MPParseError.h in Headers */,
|
||||
3B52CEDC19BEE63000CEDCFC /* NSRegularExpression+MPParsingAdditions.h in Headers */,
|
||||
3B85833A19BB63D400D76A8D /* MPFunction.h in Headers */,
|
||||
3B85834319BB653700D76A8D /* MPSumFunction.h in Headers */,
|
||||
3B85834119BB651E00D76A8D /* MPRangePath.h in Headers */,
|
||||
3B85834219BB652900D76A8D /* MPException.h in Headers */,
|
||||
3B85834519BB655200D76A8D /* NSIndexPath+MPAdditions.h in Headers */,
|
||||
3B52CED019BE509C00CEDCFC /* MPParseError.h in Headers */,
|
||||
3B85834619BB655C00D76A8D /* MPExpressionView.h in Headers */,
|
||||
3B85834719BB655F00D76A8D /* MPExpressionStorage.h in Headers */,
|
||||
3B52CEE219C070B900CEDCFC /* MPParsedProduct.h in Headers */,
|
||||
3B85833E19BB651400D76A8D /* MPExpressionEvaluator.h in Headers */,
|
||||
3B85833F19BB651400D76A8D /* MPElementParser.h in Headers */,
|
||||
3B85834019BB651400D76A8D /* MPParsedElement.h in Headers */,
|
||||
3B71432D19C0A1FC005A184E /* MPParsedFactor.h in Headers */,
|
||||
3B85834819BB65B600D76A8D /* MPLayout.h in Headers */,
|
||||
3B85834919BB65B600D76A8D /* MPExpressionLayout.h in Headers */,
|
||||
3B85834A19BB65B600D76A8D /* MPFunctionLayout.h in Headers */,
|
||||
3B85834B19BB65B600D76A8D /* MPSumFunctionLayout.h in Headers */,
|
||||
3B52CEE619C0755300CEDCFC /* MPElementParser.h in Headers */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@@ -660,23 +674,25 @@
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3B52CEE719C0755300CEDCFC /* MPElementParser.m in Sources */,
|
||||
3BBEA94219BB79A700133766 /* MPExpressionLayout.m in Sources */,
|
||||
3BBEA94119BB79A700133766 /* MPLayout.m in Sources */,
|
||||
3BBEA93D19BB79A700133766 /* NSString+MPExpressionElement.m in Sources */,
|
||||
3BBEA93819BB79A700133766 /* MPElementParser.m in Sources */,
|
||||
3BBEA94019BB79A700133766 /* MPExpressionStorage.m in Sources */,
|
||||
3BBEA93F19BB79A700133766 /* MPExpressionView.m in Sources */,
|
||||
3BBEA94419BB79A700133766 /* MPSumFunctionLayout.m in Sources */,
|
||||
3B71432E19C0A1FC005A184E /* MPParsedFactor.m in Sources */,
|
||||
3BBEA93719BB79A700133766 /* MPExpressionEvaluator.m in Sources */,
|
||||
3BBEA93A19BB79A700133766 /* MPSumFunction.m in Sources */,
|
||||
3BBEA93919BB79A700133766 /* MPParsedElement.m in Sources */,
|
||||
3BBEA93E19BB79A700133766 /* NSIndexPath+MPAdditions.m in Sources */,
|
||||
3BBEA95619BB9B3500133766 /* MPParseError.m in Sources */,
|
||||
3B52CEDD19BEE63000CEDCFC /* NSRegularExpression+MPParsingAdditions.m in Sources */,
|
||||
3BBEA93C19BB79A700133766 /* MPException.m in Sources */,
|
||||
3B52CED119BE509C00CEDCFC /* MPParseError.m in Sources */,
|
||||
3BBEA93619BB79A700133766 /* MPFunction.m in Sources */,
|
||||
3BBEA93519BB79A700133766 /* MPExpression.m in Sources */,
|
||||
3BBEA93B19BB79A700133766 /* MPRangePath.m in Sources */,
|
||||
3BBEA94319BB79A700133766 /* MPFunctionLayout.m in Sources */,
|
||||
3B52CEE319C070B900CEDCFC /* MPParsedProduct.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
|
||||
@@ -2,17 +2,36 @@
|
||||
// MPElementParser.h
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 06.09.14.
|
||||
// Created by Kim Wittenburg on 10.09.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPParsedElement.h"
|
||||
#import "MPParsedProduct.h"
|
||||
#import "MPParseError.h"
|
||||
|
||||
#define MPMaximumOperatorChainLength NSUIntegerMax
|
||||
|
||||
@interface MPElementParser : NSObject
|
||||
|
||||
- (MPParsedElement *)parseElement:(NSString *)string error:(MPParseError *__autoreleasing *)error;
|
||||
+ (BOOL)isUsingDefaultValuesFromUserDefaults;
|
||||
+ (void)setUsingDefaultValuesFromUserDefaults:(BOOL)flag;
|
||||
|
||||
@property (nonatomic) BOOL allowsImplicitMultiplications; // wether 2 3 is equal to 6 or error
|
||||
// Default value uses the key "..." in NSUserDefaults or ... if the key does not exist.
|
||||
@property (nonatomic) NSUInteger maximumOperatorChainLength; // +--++-5 -> Chain length: 6, 2 default (sign of number and operator) (0 is invalid?)
|
||||
@property (nonatomic) NSUInteger maximumOperatorChainLengthInMultiplication; // Default: 1, 0 means actually 0
|
||||
@property (nonatomic) NSUInteger maximumOperatorChainLengthInFunction; // For sin, cos, tan. Default: 1
|
||||
|
||||
- (NSArray *)parseElement:(NSString *)string
|
||||
previousProduct:(MPParsedProduct *)previousProduct
|
||||
nextFactor:(MPParsedFactor *)nextFactor
|
||||
definesVariable:(BOOL)flag
|
||||
definedVariable:(NSString *__autoreleasing *)variableName
|
||||
error:(out MPParseError *__autoreleasing *)error;
|
||||
- (NSArray *)parseElement:(NSString *)string
|
||||
previousProduct:(MPParsedProduct *)previousProduct
|
||||
nextFactor:(MPParsedFactor *)nextFactor
|
||||
error:(out MPParseError *__autoreleasing *)error;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@@ -2,184 +2,335 @@
|
||||
// MPElementParser.m
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 06.09.14.
|
||||
// Created by Kim Wittenburg on 10.09.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPElementParser.h"
|
||||
#import "NSRegularExpression+MPParsingAdditions.h"
|
||||
|
||||
#define MPMultiplicationSymbol @"*"
|
||||
|
||||
@interface MPElementParser ()
|
||||
|
||||
@property (nonatomic) NSString *input;
|
||||
@property (nonatomic) NSUInteger parsePosition;
|
||||
|
||||
- (void)setError:(MPParseError *)error;
|
||||
|
||||
- (BOOL)isAtEnd;
|
||||
|
||||
- (NSRange)parseVariableDefinition:(NSString *__autoreleasing *)variableName;
|
||||
|
||||
- (NSRange)parseWhitespaces;
|
||||
- (NSRange)parseMultiplicationSymbol;
|
||||
- (NSRange)parseOperators;
|
||||
- (NSUInteger)countOperatorsInRange:(NSRange)range
|
||||
multiplicator:(out NSDecimalNumber *__autoreleasing *)multiplicator;
|
||||
- (NSRange)parseNumber;
|
||||
- (NSDecimalNumber *)numberInRange:(NSRange)range;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPElementParser {
|
||||
NSScanner *scanner;
|
||||
MPParseError *__autoreleasing *outError;
|
||||
}
|
||||
|
||||
- (MPParsedElement *)parseElement:(NSString *)string error:(MPParseError *__autoreleasing *)error
|
||||
static BOOL useUserDefaults;
|
||||
|
||||
#pragma mark Creation Methods
|
||||
|
||||
+ (void)initialize
|
||||
{
|
||||
// Setup the Scanner
|
||||
scanner = [[NSScanner alloc] initWithString:string];
|
||||
scanner.charactersToBeSkipped = [NSCharacterSet whitespaceAndNewlineCharacterSet];
|
||||
scanner.caseSensitive = YES;
|
||||
|
||||
MPParsedElement *parsedElement = [[MPParsedElement alloc] init];
|
||||
|
||||
// Scan the defined variable
|
||||
NSString *firstCharacters = nil;
|
||||
BOOL hasLettersInFront = [scanner scanCharactersFromSet:[NSCharacterSet letterCharacterSet]
|
||||
intoString:&firstCharacters];
|
||||
BOOL foundEquals = [scanner scanString:@"="
|
||||
intoString:NULL];
|
||||
|
||||
if (hasLettersInFront && firstCharacters.length == 1 && foundEquals) {
|
||||
// Found variable definition
|
||||
parsedElement.definedVariable = firstCharacters;
|
||||
parsedElement.afterVariableDefinitionIndex = scanner.scanLocation;
|
||||
} else {
|
||||
// No variable definition found, reset the scanner
|
||||
parsedElement.definedVariable = nil;
|
||||
scanner.scanLocation = 0;
|
||||
useUserDefaults = YES;
|
||||
}
|
||||
|
||||
// Scan the Prefix
|
||||
BOOL startsWithAsterisk = [scanner scanString:@"*"
|
||||
intoString:NULL];
|
||||
BOOL productClosed;
|
||||
NSDecimalNumber *prefix = [self scanClosedProduct:&productClosed
|
||||
error:NULL];
|
||||
|
||||
// Simple Factor
|
||||
if (scanner.isAtEnd) {
|
||||
parsedElement.isFactor = YES;
|
||||
parsedElement.value = prefix == nil ? [NSDecimalNumber one] : prefix;
|
||||
parsedElement.prefixOperatorExplicit = startsWithAsterisk;
|
||||
parsedElement.suffixOperatorExplicit = !productClosed;
|
||||
parsedElement.suffixIndex = scanner.scanLocation;
|
||||
return parsedElement;
|
||||
} else if (!productClosed) {
|
||||
if (error) {
|
||||
*error = MPParseError(scanner.scanLocation, @"Missing Number");
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
self.allowsImplicitMultiplications = NO;
|
||||
self.maximumOperatorChainLength = 2;
|
||||
self.maximumOperatorChainLengthInMultiplication = 1;
|
||||
}
|
||||
return nil;
|
||||
return self;
|
||||
}
|
||||
|
||||
parsedElement.prefixOperatorExplicit = startsWithAsterisk;
|
||||
parsedElement.prefixValueExplicit = YES;
|
||||
parsedElement.prefixMultiplicator = prefix;
|
||||
#pragma mark Properties
|
||||
|
||||
parsedElement.suffixValueExplicit = YES;
|
||||
|
||||
// Scan Summands
|
||||
NSDecimalNumber *value = [NSDecimalNumber zero];
|
||||
NSDecimalNumber *currentSummand;
|
||||
while (!scanner.isAtEnd) {
|
||||
|
||||
// Add every summand but the last one
|
||||
if (currentSummand != nil) {
|
||||
value = [value decimalNumberByAdding:currentSummand];
|
||||
+ (BOOL)isUsingDefaultValuesFromUserDefaults
|
||||
{
|
||||
return useUserDefaults;
|
||||
}
|
||||
|
||||
// Find the operator (+ or -)
|
||||
NSString *operator;
|
||||
BOOL found = [scanner scanString:@"+"
|
||||
intoString:&operator];
|
||||
if (!found) {
|
||||
found = [scanner scanString:@"-"
|
||||
intoString:&operator];
|
||||
}
|
||||
if (!found && !scanner.isAtEnd) {
|
||||
// Two numbers separated by just a space
|
||||
if (error) {
|
||||
*error = MPParseError(scanner.scanLocation, @"Missing Operator");
|
||||
}
|
||||
return nil;
|
||||
} else if (!found) {
|
||||
// Reached end of string
|
||||
break;
|
||||
+ (void)setUsingDefaultValuesFromUserDefaults:(BOOL)flag
|
||||
{
|
||||
useUserDefaults = flag;
|
||||
}
|
||||
|
||||
currentSummand = [self scanClosedProduct:&productClosed
|
||||
#pragma mark Parsing Methods
|
||||
|
||||
- (BOOL)isAtEnd
|
||||
{
|
||||
return self.parsePosition >= self.input.length;
|
||||
}
|
||||
|
||||
- (void)setError:(MPParseError *)error
|
||||
{
|
||||
if (outError != NULL) {
|
||||
*outError = error;
|
||||
}
|
||||
}
|
||||
|
||||
- (NSArray *)parseElement:(NSString *)string
|
||||
previousProduct:(MPParsedProduct *)previousProduct
|
||||
nextFactor:(MPParsedFactor *)nextFactor
|
||||
error:(out MPParseError *__autoreleasing *)error
|
||||
{
|
||||
return [self parseElement:string
|
||||
previousProduct:previousProduct
|
||||
nextFactor:nextFactor
|
||||
definesVariable:NO
|
||||
definedVariable:NULL
|
||||
error:error];
|
||||
|
||||
// No number was found
|
||||
if (currentSummand == nil) {
|
||||
// The string ends wit + or -
|
||||
if (scanner.isAtEnd) {
|
||||
productClosed = NO;
|
||||
parsedElement.suffixValueExplicit = NO;
|
||||
NSInteger suffix = [operator isEqualToString:@"+"] ? 1 : -1;
|
||||
currentSummand = [[NSDecimalNumber alloc] initWithInteger:suffix];
|
||||
if (error) {
|
||||
*error = nil;
|
||||
}
|
||||
break;
|
||||
// Something else instead of a number
|
||||
} else {
|
||||
if (error) {
|
||||
*error = MPParseError(scanner.scanLocation, @"Expected Number");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
|
||||
// Process the current summand
|
||||
if ([operator isEqualToString:@"-"]) {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:[[NSDecimalNumber alloc] initWithInteger:-1]];
|
||||
}
|
||||
|
||||
// The summand ends with a *
|
||||
if (!productClosed) {
|
||||
// The string ends with a *
|
||||
if (scanner.isAtEnd) {
|
||||
parsedElement.suffixValueExplicit = YES;
|
||||
break;
|
||||
// After a * followed something else than a number
|
||||
} else {
|
||||
if (error) {
|
||||
*error = MPParseError(scanner.scanLocation, @"Unexpected Symbol");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parsedElement.value = value;
|
||||
parsedElement.suffixOperatorExplicit = !productClosed;
|
||||
parsedElement.suffixMultiplicator = currentSummand;
|
||||
parsedElement.suffixIndex = scanner.scanLocation;
|
||||
|
||||
return parsedElement;
|
||||
}
|
||||
|
||||
- (NSDecimalNumber *)scanClosedProduct:(BOOL *)closed error:(MPParseError **)error
|
||||
- (NSArray *)parseElement:(NSString *)string
|
||||
previousProduct:(MPParsedProduct *)previousProduct
|
||||
nextFactor:(MPParsedFactor *)nextFactor
|
||||
definesVariable:(BOOL)flag
|
||||
definedVariable:(NSString *__autoreleasing *)variableName
|
||||
error:(out MPParseError *__autoreleasing *)error
|
||||
{
|
||||
NSDecimal decimal;
|
||||
BOOL found = [scanner scanDecimal:&decimal];
|
||||
if (!found) {
|
||||
if (error != NULL) {
|
||||
*error = MPParseError(scanner.scanLocation, @"Unexpected Symbol");
|
||||
self.input = string;
|
||||
outError = error;
|
||||
self.parsePosition = 0;
|
||||
|
||||
NSString *definedVariable;
|
||||
NSRange variableDefinitionRange = [self parseVariableDefinition:&definedVariable];
|
||||
if (flag) {
|
||||
if (!definedVariable) {
|
||||
self.error = MPParseError(NSMakeRange(0, 0), @"Expected Variable Definition");
|
||||
return nil;
|
||||
} else if (variableName) {
|
||||
*variableName = definedVariable;
|
||||
}
|
||||
} else if (definedVariable) {
|
||||
self.error = MPParseError(variableDefinitionRange, @"Unexpected Variable Definition");
|
||||
return nil;
|
||||
}
|
||||
NSDecimalNumber *product = [NSDecimalNumber decimalNumberWithDecimal:decimal];
|
||||
while (true) {
|
||||
found = [scanner scanString:@"*"
|
||||
intoString:NULL];
|
||||
if (found) {
|
||||
found = [scanner scanDecimal:&decimal];
|
||||
if (found) {
|
||||
product = [product decimalNumberByMultiplyingBy:[NSDecimalNumber decimalNumberWithDecimal:decimal]];
|
||||
} else {
|
||||
if (closed != NULL) {
|
||||
*closed = NO;
|
||||
|
||||
NSMutableArray *products = [[NSMutableArray alloc] init];
|
||||
MPParsedProduct *currentProduct = previousProduct;
|
||||
|
||||
while (![self isAtEnd]) {
|
||||
[self parseWhitespaces];
|
||||
|
||||
NSRange multiplicationSymbolRange = [self parseMultiplicationSymbol];
|
||||
BOOL hasMultiplicationSymbol = multiplicationSymbolRange.location != NSNotFound;
|
||||
|
||||
NSRange operatorsRange = [self parseOperators];
|
||||
BOOL hasOperators = operatorsRange.location != NSNotFound;
|
||||
|
||||
// NSRange functionRange = ...
|
||||
// BOOL hasFunction = functionRange.location != NSNotFound;
|
||||
|
||||
NSRange numberRange = [self parseNumber];
|
||||
BOOL hasNumber = numberRange.location != NSNotFound;
|
||||
|
||||
|
||||
NSDecimalNumber *operatorMultiplicator;
|
||||
NSUInteger operatorCount = [self countOperatorsInRange:operatorsRange
|
||||
multiplicator:&operatorMultiplicator];
|
||||
|
||||
if (!hasNumber) {
|
||||
if ([self isAtEnd] && nextFactor != nil) {
|
||||
if (hasMultiplicationSymbol) {
|
||||
if (operatorCount > self.maximumOperatorChainLengthInFunction) {
|
||||
self.error = MPParseError(operatorsRange, @"Too many operators in multiplication.");
|
||||
return nil;
|
||||
}
|
||||
return product;
|
||||
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:operatorMultiplicator]];
|
||||
} else if (hasOperators) {
|
||||
if (operatorCount > self.maximumOperatorChainLength) {
|
||||
self.error = MPParseError(operatorsRange, @"Too many operators.");
|
||||
return nil;
|
||||
}
|
||||
[products addObject:currentProduct];
|
||||
currentProduct = [[MPParsedProduct alloc] init];
|
||||
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:[[NSDecimalNumber alloc] initWithUnsignedInteger:operatorCount]]];
|
||||
} else if (self.allowsImplicitMultiplications) {
|
||||
if (!currentProduct) {
|
||||
currentProduct = [[MPParsedProduct alloc] init];
|
||||
}
|
||||
} else {
|
||||
self.error = MPParseError(NSMakeRange(self.parsePosition, 0), @"Implicit Multiplication not allowed.");
|
||||
return nil;
|
||||
}
|
||||
break;
|
||||
} else if ([self isAtEnd]) {
|
||||
self.error = MPParseError(NSMakeRange(self.parsePosition, 0), @"Unexpected End. Expected Number.");
|
||||
return nil;
|
||||
} else {
|
||||
self.error = MPParseError(NSMakeRange(self.parsePosition, 1), @"Unexpected Symbol. Expected Number.");
|
||||
return nil;
|
||||
}
|
||||
} else {
|
||||
NSDecimalNumber *number = [self numberInRange:numberRange];
|
||||
NSDecimalNumber *value = [operatorMultiplicator decimalNumberByMultiplyingBy:number];
|
||||
|
||||
if (hasMultiplicationSymbol) {
|
||||
if (currentProduct) {
|
||||
if (operatorCount > self.maximumOperatorChainLengthInMultiplication) {
|
||||
self.error = MPParseError(operatorsRange, @"Too many operators in multiplication.");
|
||||
return nil;
|
||||
}
|
||||
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:value]];
|
||||
} else {
|
||||
self.error = MPParseError(multiplicationSymbolRange, @"Unexpected Symbol. Expected Number.");
|
||||
return nil;
|
||||
}
|
||||
} else if (hasOperators) {
|
||||
if (operatorCount > self.maximumOperatorChainLength) {
|
||||
self.error = MPParseError(operatorsRange, @"Too many operators.");
|
||||
return nil;
|
||||
}
|
||||
if (currentProduct) {
|
||||
[products addObject:currentProduct];
|
||||
}
|
||||
currentProduct = [[MPParsedProduct alloc] init];
|
||||
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:value]];
|
||||
} else if (!currentProduct) {
|
||||
currentProduct = [[MPParsedProduct alloc] init];
|
||||
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:value]];
|
||||
} else if (self.allowsImplicitMultiplications) {
|
||||
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:value]];
|
||||
} else {
|
||||
self.error = MPParseError(NSMakeRange(numberRange.location, 0), @"Implicit Multiplication not allowed.");
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
if (closed != NULL) {
|
||||
*closed = YES;
|
||||
}
|
||||
return product;
|
||||
if (nextFactor) {
|
||||
[currentProduct addFactor:nextFactor];
|
||||
}
|
||||
[products addObject:currentProduct];
|
||||
return products;
|
||||
}
|
||||
|
||||
static NSRegularExpression *variableDefinitionRegex;
|
||||
- (NSRange)parseVariableDefinition:(NSString *__autoreleasing *)variableName
|
||||
{
|
||||
if (!variableDefinitionRegex) {
|
||||
variableDefinitionRegex = [NSRegularExpression regularExpressionWithPattern:@"\\A\\s*([A-Za-z])\\s*=\\s*"
|
||||
options:0
|
||||
error:NULL];
|
||||
}
|
||||
|
||||
NSTextCheckingResult *match = [variableDefinitionRegex firstMatchInString:self.input
|
||||
fromIndex:self.parsePosition];
|
||||
if (!match) {
|
||||
return NSMakeRange(NSNotFound, 0);
|
||||
}
|
||||
self.parsePosition = NSMaxRange(match.range);
|
||||
NSRange variableDefinitionRange = [match rangeAtIndex:1];
|
||||
*variableName = [self.input substringWithRange:variableDefinitionRange];
|
||||
return variableDefinitionRange;
|
||||
}
|
||||
|
||||
static NSRegularExpression *whitespaceRegex;
|
||||
- (NSRange)parseWhitespaces
|
||||
{
|
||||
if (!whitespaceRegex) {
|
||||
whitespaceRegex = [NSRegularExpression regularExpressionWithPattern:@"\\A\\s*"
|
||||
options:0
|
||||
error:NULL];
|
||||
}
|
||||
NSTextCheckingResult *match = [whitespaceRegex firstMatchInString:self.input
|
||||
fromIndex:self.parsePosition];
|
||||
if (match) {
|
||||
self.parsePosition = NSMaxRange(match.range);
|
||||
return match.range;
|
||||
} else {
|
||||
return NSMakeRange(NSNotFound, 0);
|
||||
}
|
||||
}
|
||||
|
||||
static NSRegularExpression *multiplicationSymbolRegex;
|
||||
- (NSRange)parseMultiplicationSymbol
|
||||
{
|
||||
if (!multiplicationSymbolRegex) {
|
||||
NSString *multiplicationSymbolString = [NSRegularExpression escapedPatternForString:MPMultiplicationSymbol];
|
||||
NSString *multiplicationSymbolRegexString = [NSString stringWithFormat:@"\\A\\s*(%@)\\s*", multiplicationSymbolString];
|
||||
multiplicationSymbolRegex = [NSRegularExpression regularExpressionWithPattern:multiplicationSymbolRegexString
|
||||
options:0
|
||||
error:NULL];
|
||||
}
|
||||
NSTextCheckingResult *match = [multiplicationSymbolRegex firstMatchInString:self.input
|
||||
fromIndex:self.parsePosition];
|
||||
if (!match) {
|
||||
return NSMakeRange(NSNotFound, 0);
|
||||
}
|
||||
self.parsePosition = NSMaxRange(match.range);
|
||||
return [match rangeAtIndex:1];
|
||||
}
|
||||
|
||||
static NSRegularExpression *operatorsRegex;
|
||||
- (NSRange)parseOperators
|
||||
{
|
||||
if (!operatorsRegex) {
|
||||
operatorsRegex = [NSRegularExpression regularExpressionWithPattern:@"\\A\\s*([+-](?:\\s*[+-])*)\\s*"
|
||||
options:0
|
||||
error:NULL];
|
||||
}
|
||||
NSTextCheckingResult *match = [operatorsRegex firstMatchInString:self.input
|
||||
fromIndex:self.parsePosition];
|
||||
if (match == nil) {
|
||||
return NSMakeRange(NSNotFound, 0);
|
||||
}
|
||||
self.parsePosition = NSMaxRange(match.range);
|
||||
return [match rangeAtIndex:1];
|
||||
}
|
||||
|
||||
- (NSUInteger)countOperatorsInRange:(NSRange)range
|
||||
multiplicator:(out NSDecimalNumber *__autoreleasing *)outMultiplicator
|
||||
{
|
||||
if (range.location == NSNotFound) {
|
||||
*outMultiplicator = [NSDecimalNumber one];
|
||||
return 0;
|
||||
}
|
||||
NSString *operatorsString = [self.input substringWithRange:range];
|
||||
NSString *operators = [[operatorsString componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:@""];
|
||||
NSInteger multiplicator = 1;
|
||||
for (NSUInteger characterIndex; characterIndex < operators.length; characterIndex++) {
|
||||
if ([[operators substringWithRange:NSMakeRange(characterIndex, 1)] isEqualToString:@"-"]) {
|
||||
multiplicator *= -1;
|
||||
}
|
||||
}
|
||||
*outMultiplicator = [[NSDecimalNumber alloc] initWithInteger:multiplicator];
|
||||
return operators.length;
|
||||
}
|
||||
|
||||
- (NSRange)parseNumber
|
||||
{
|
||||
NSString *decimalSeparatorRegexString = [NSRegularExpression escapedPatternForString:[[NSLocale currentLocale] objectForKey:NSLocaleDecimalSeparator]];
|
||||
NSString *numberRegexFormat = [NSString stringWithFormat:@"\\A\\s*((?:\\d+(?:%@\\d+)?)|(?:%@\\d+))\\s*", decimalSeparatorRegexString, decimalSeparatorRegexString];
|
||||
NSRegularExpression *numberRegex = [NSRegularExpression regularExpressionWithPattern:numberRegexFormat
|
||||
options:0
|
||||
error:NULL];
|
||||
NSTextCheckingResult *match = [numberRegex firstMatchInString:self.input
|
||||
fromIndex:self.parsePosition];
|
||||
if (!match) {
|
||||
return NSMakeRange(NSNotFound, 0);
|
||||
}
|
||||
self.parsePosition = NSMaxRange(match.range);
|
||||
return [match rangeAtIndex:1];
|
||||
}
|
||||
|
||||
- (NSDecimalNumber *)numberInRange:(NSRange)range
|
||||
{
|
||||
NSString *numberString = [self.input substringWithRange:range];
|
||||
return [NSDecimalNumber decimalNumberWithString:numberString];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@@ -17,6 +17,4 @@
|
||||
|
||||
- (NSUInteger)length;
|
||||
|
||||
- (NSDecimalNumber *)evaluate:(MPParseError *__autoreleasing *)error;
|
||||
|
||||
@end
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
#import "MPExpression.h"
|
||||
#import "MPElementParser.h"
|
||||
|
||||
@class MPExpressionEvaluator, MPExpression, MPParsedElement;
|
||||
@class MPExpressionEvaluator, MPExpression, MPParsedElementOld;
|
||||
|
||||
@interface MPExpressionEvaluator : NSObject
|
||||
|
||||
@@ -25,8 +25,9 @@
|
||||
- (void)bindValue:(NSDecimalNumber *)value toVariableName:(NSString *)name;
|
||||
- (void)unbindVariableName:(NSString *)name;
|
||||
|
||||
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error;
|
||||
- (NSDecimalNumber *)evaluateVariableDefinition:(BOOL)flag error:(MPParseError *__autoreleasing *)error;
|
||||
@property (readonly, nonatomic, strong) NSString *definedVariable;
|
||||
|
||||
- (NSDecimalNumber *)evaluateWithError:(MPParseError *__autoreleasing *)error;
|
||||
- (NSDecimalNumber *)evaluateVariableDefinition:(BOOL)flag error:(MPParseError *__autoreleasing *)error;
|
||||
|
||||
@end
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
|
||||
#import "MPExpressionEvaluator.h"
|
||||
#import "MPExpression.h"
|
||||
#import "MPFunction.h"
|
||||
|
||||
@interface MPExpressionEvaluator ()
|
||||
@property (readwrite, nonatomic, strong) NSString *definedVariable;
|
||||
|
||||
@end
|
||||
|
||||
@implementation MPExpressionEvaluator {
|
||||
@@ -52,146 +54,74 @@
|
||||
|
||||
- (NSDecimalNumber *)evaluateVariableDefinition:(BOOL)flag error:(MPParseError *__autoreleasing *)error
|
||||
{
|
||||
#warning Implement Cache
|
||||
// Empty Expression
|
||||
if (self.expression.numberOfElements == 0) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Empty Expression");
|
||||
}
|
||||
*error = MPParseError(NSMakeRange(0, 0), @"Expected Expression");
|
||||
return nil;
|
||||
}
|
||||
|
||||
// Expression of just one element
|
||||
if (self.expression.numberOfElements == 1) {
|
||||
id<MPExpressionElement> singleElement = [self.expression elementAtIndex:0];
|
||||
if ([singleElement isString]) {
|
||||
MPParsedElement *parseResult = [parser parseElement:(NSString *)singleElement
|
||||
error:error];
|
||||
if ([parseResult isValidStandaloneElement:error]) {
|
||||
if (flag && parseResult.definedVariable) {
|
||||
self.definedVariable = parseResult.definedVariable;
|
||||
} else if (flag) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Expected Variable Definition");
|
||||
}
|
||||
return nil;
|
||||
} else if (parseResult.definedVariable) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Unexpected Variable Definition");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
return parseResult.standaloneValue;
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
} else {
|
||||
return [singleElement evaluate:error];
|
||||
}
|
||||
}
|
||||
NSMutableArray *products = [[NSMutableArray alloc] init];
|
||||
MPParsedProduct *currentProduct = nil;
|
||||
|
||||
// Expression with any number of elements
|
||||
NSDecimalNumber *value = [NSDecimalNumber zero];
|
||||
NSDecimalNumber *currentSummand = nil;
|
||||
for (NSUInteger elementIndex = 0; elementIndex < self.expression.numberOfElements; elementIndex++) {
|
||||
|
||||
// Process the first element
|
||||
id<MPExpressionElement> firstElement = [self.expression elementAtIndex:0];
|
||||
if ([firstElement isString]) {
|
||||
MPParsedElement *parseResult = [parser parseElement:(NSString *)firstElement
|
||||
error:error];
|
||||
if (parseResult && [parseResult isValidElementAtBeginning:error]) {
|
||||
if (flag && parseResult.definedVariable) {
|
||||
self.definedVariable = parseResult.definedVariable;
|
||||
} else if (flag) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Expected Variable Definition");
|
||||
}
|
||||
return nil;
|
||||
} else if (parseResult.definedVariable) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Unexpected Variable Definition");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
if ([parseResult isFactor]) {
|
||||
currentSummand = parseResult.value;
|
||||
} else {
|
||||
value = [parseResult valueAtBeginning];
|
||||
currentSummand = parseResult.suffixMultiplicator;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
currentSummand = [firstElement evaluate:error];
|
||||
}
|
||||
if (!currentSummand) {
|
||||
return nil;
|
||||
}
|
||||
id<MPExpressionElement> element = [self.expression elementAtIndex:elementIndex];
|
||||
|
||||
// Process the elements between the first and last element
|
||||
for (NSUInteger index = 1; index < self.expression.numberOfElements-1; index++) {
|
||||
id<MPExpressionElement> element = [self.expression elementAtIndex:index];
|
||||
if ([element isString]) {
|
||||
MPParsedElement *parseResult = [parser parseElement:(NSString *)element
|
||||
MPParsedFactor *nextFactor = nil;
|
||||
if (elementIndex < self.expression.numberOfElements - 1) {
|
||||
MPFunction *nextFunction = (MPFunction *)[self.expression elementAtIndex:elementIndex+1];
|
||||
NSDecimalNumber *functionValue = [nextFunction evaluate:error];
|
||||
if (!functionValue) {
|
||||
return nil;
|
||||
}
|
||||
nextFactor = [MPParsedFactor factorWithDecimalNumber:functionValue];
|
||||
}
|
||||
|
||||
NSArray *newProducts;
|
||||
if (elementIndex == 0 && flag) {
|
||||
NSString *definedVariable;
|
||||
newProducts = [parser parseElement:(NSString *)element
|
||||
previousProduct:currentProduct
|
||||
nextFactor:nextFactor
|
||||
definesVariable:YES
|
||||
definedVariable:&definedVariable
|
||||
error:error];
|
||||
self.definedVariable = definedVariable;
|
||||
} else {
|
||||
newProducts = [parser parseElement:(NSString *)element
|
||||
previousProduct:currentProduct
|
||||
nextFactor:nextFactor
|
||||
error:error];
|
||||
if (parseResult) {
|
||||
if (parseResult.definedVariable) {
|
||||
if (error) {
|
||||
*error = MPParseError(index, @"Unexpected Variable Definition");
|
||||
}
|
||||
if (!newProducts) {
|
||||
return nil;
|
||||
}
|
||||
if ([parseResult isFactor]) {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:parseResult.value];
|
||||
} else {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:parseResult.prefixMultiplicator];
|
||||
value = [[value decimalNumberByAdding:currentSummand] decimalNumberByAdding:parseResult.value];
|
||||
currentSummand = parseResult.suffixMultiplicator;
|
||||
|
||||
for (NSUInteger productIndex = 0; productIndex < newProducts.count-1; productIndex++) {
|
||||
[products addObject:newProducts[productIndex]];
|
||||
}
|
||||
currentProduct = newProducts.lastObject;
|
||||
|
||||
elementIndex++;
|
||||
} else {
|
||||
NSDecimalNumber *functionValue = [(MPFunction *)element evaluate:error];
|
||||
if (!functionValue) {
|
||||
return nil;
|
||||
}
|
||||
} else {
|
||||
NSDecimalNumber *result = [element evaluate:error];
|
||||
if (result) {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:result];
|
||||
} else {
|
||||
return nil;
|
||||
if (!currentProduct) {
|
||||
currentProduct = [[MPParsedProduct alloc] init];
|
||||
}
|
||||
[currentProduct addFactor:[MPParsedFactor factorWithDecimalNumber:functionValue]];
|
||||
}
|
||||
}
|
||||
|
||||
// Process the last element
|
||||
id<MPExpressionElement> lastElement = [self.expression elementAtIndex:self.expression.numberOfElements-1];
|
||||
if ([lastElement isString]) {
|
||||
MPParsedElement *parseResult = [parser parseElement:(NSString *)lastElement
|
||||
error:error];
|
||||
if (parseResult && [parseResult isValidElementAtEnd:error]) {
|
||||
if (parseResult.definedVariable) {
|
||||
if (error) {
|
||||
*error = MPParseError(0, @"Unexpected Variable Definition");
|
||||
}
|
||||
return nil;
|
||||
}
|
||||
if ([parseResult isFactor]) {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:parseResult.value];
|
||||
} else {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:parseResult.prefixMultiplicator];
|
||||
value = [[value decimalNumberByAdding:currentSummand] decimalNumberByAdding:parseResult.value];
|
||||
currentSummand = parseResult.suffixMultiplicator;
|
||||
}
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
} else {
|
||||
NSDecimalNumber *result = [lastElement evaluate:error];
|
||||
if (result) {
|
||||
currentSummand = [currentSummand decimalNumberByMultiplyingBy:result];
|
||||
} else {
|
||||
return nil;
|
||||
}
|
||||
}
|
||||
value = [value decimalNumberByAdding:currentSummand];
|
||||
[products addObject:currentProduct];
|
||||
|
||||
NSDecimalNumber *value = [NSDecimalNumber zero];
|
||||
for (MPParsedProduct *product in products) {
|
||||
value = [value decimalNumberByAdding:product.value];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
@@ -2,20 +2,25 @@
|
||||
// MPParseError.h
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 06.09.14.
|
||||
// Created by Kim Wittenburg on 08.09.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define MPParseError(index,key) [[MPParseError alloc] initWithErrorIndex:index errorMessageKey:key]
|
||||
#define MPParseError(range,key) [[MPParseError alloc] initWithErrorRange:range errorMessageKey:key]
|
||||
|
||||
@interface MPParseError : NSObject
|
||||
|
||||
- (instancetype)initWithErrorIndex:(NSUInteger)errorIndex
|
||||
errorMessageKey:(NSString *)errorMessageKey;
|
||||
- (instancetype)initWithErrorRange:(NSRange)errorRange
|
||||
errorMessageKey:(NSString *)key;
|
||||
|
||||
@property (nonatomic) NSUInteger errorIndex;
|
||||
@property (nonatomic) NSString *localizedErrorMessage;
|
||||
- (instancetype)initWithErrorRange:(NSRange)errorRange
|
||||
localizederrorMessage:(NSString *)errorMessage;
|
||||
|
||||
@property (nonatomic, strong) NSIndexPath *pathToExpression;
|
||||
|
||||
@property (nonatomic) NSRange errorRange;
|
||||
@property (nonatomic, copy) NSString *localizedErrorMessage;
|
||||
|
||||
@end
|
||||
@@ -2,7 +2,7 @@
|
||||
// MPParseError.m
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 06.09.14.
|
||||
// Created by Kim Wittenburg on 08.09.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
@@ -10,19 +10,29 @@
|
||||
|
||||
@implementation MPParseError
|
||||
|
||||
- (instancetype)initWithErrorIndex:(NSUInteger)errorIndex errorMessageKey:(NSString *)errorMessageKey
|
||||
- (instancetype)initWithErrorRange:(NSRange)errorRange errorMessageKey:(NSString *)key
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_errorIndex = errorIndex;
|
||||
_localizedErrorMessage = NSLocalizedString(errorMessageKey, nil);
|
||||
_errorRange = errorRange;
|
||||
_localizedErrorMessage = NSLocalizedString(key, nil);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithErrorRange:(NSRange)errorRange localizederrorMessage:(NSString *)errorMessage
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_errorRange = errorRange;
|
||||
_localizedErrorMessage = errorMessage;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"MPParseError<at=%ld message=\"%@\">", self.errorIndex, self.localizedErrorMessage];
|
||||
return [NSString stringWithFormat:@"MPParseError<at=(%ld, %ld) message=\"%@\">", self.errorRange.location, self.errorRange.length, self.localizedErrorMessage];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
22
MathPad/MPParsedFactor.h
Normal file
22
MathPad/MPParsedFactor.h
Normal file
@@ -0,0 +1,22 @@
|
||||
//
|
||||
// MPParsedFactor.h
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 10.09.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface MPParsedFactor : NSObject
|
||||
|
||||
+ (MPParsedFactor *)factorWithDecimalNumber:(NSDecimalNumber *)number;
|
||||
+ (MPParsedFactor *)sinFactorWithFactor:(MPParsedFactor *)factor;
|
||||
+ (MPParsedFactor *)cosFactorWithFactor:(MPParsedFactor *)factor;
|
||||
+ (MPParsedFactor *)tanFactorWithFactor:(MPParsedFactor *)factor;
|
||||
|
||||
- (instancetype)initWithDecimalNumber:(NSDecimalNumber *)number;
|
||||
|
||||
- (NSDecimalNumber *)value;
|
||||
|
||||
@end
|
||||
60
MathPad/MPParsedFactor.m
Normal file
60
MathPad/MPParsedFactor.m
Normal file
@@ -0,0 +1,60 @@
|
||||
//
|
||||
// MPParsedFactor.m
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 10.09.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPParsedFactor.h"
|
||||
|
||||
@implementation MPParsedFactor {
|
||||
NSDecimalNumber *_value;
|
||||
}
|
||||
|
||||
+ (MPParsedFactor *)factorWithDecimalNumber:(NSDecimalNumber *)number
|
||||
{
|
||||
return [[MPParsedFactor alloc] initWithDecimalNumber:number];
|
||||
}
|
||||
|
||||
+ (MPParsedFactor *)sinFactorWithFactor:(MPParsedFactor *)factor
|
||||
{
|
||||
double value = factor.value.doubleValue;
|
||||
NSDecimalNumber *actualNumber = [[NSDecimalNumber alloc] initWithDouble:sin(value)];
|
||||
return [[MPParsedFactor alloc] initWithDecimalNumber:actualNumber];
|
||||
}
|
||||
|
||||
+ (MPParsedFactor *)cosFactorWithFactor:(MPParsedFactor *)factor
|
||||
{
|
||||
double value = factor.value.doubleValue;
|
||||
NSDecimalNumber *actualNumber = [[NSDecimalNumber alloc] initWithDouble:cos(value)];
|
||||
return [[MPParsedFactor alloc] initWithDecimalNumber:actualNumber];
|
||||
}
|
||||
|
||||
+ (MPParsedFactor *)tanFactorWithFactor:(MPParsedFactor *)factor
|
||||
{
|
||||
double value = factor.value.doubleValue;
|
||||
NSDecimalNumber *actualNumber = [[NSDecimalNumber alloc] initWithDouble:tan(value)];
|
||||
return [[MPParsedFactor alloc] initWithDecimalNumber:actualNumber];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDecimalNumber:(NSDecimalNumber *)number
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_value = number;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSDecimalNumber *)value
|
||||
{
|
||||
return _value;
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"MPParsedFactor<%@>", _value];
|
||||
}
|
||||
|
||||
@end
|
||||
20
MathPad/MPParsedProduct.h
Normal file
20
MathPad/MPParsedProduct.h
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// MPParsedSummand.h
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 10.09.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "MPParsedFactor.h"
|
||||
|
||||
@interface MPParsedProduct : NSObject
|
||||
|
||||
@property (readonly, nonatomic, strong) NSArray *factors;
|
||||
|
||||
- (void)addFactor:(MPParsedFactor *)factor;
|
||||
|
||||
- (NSDecimalNumber *)value;
|
||||
|
||||
@end
|
||||
51
MathPad/MPParsedProduct.m
Normal file
51
MathPad/MPParsedProduct.m
Normal file
@@ -0,0 +1,51 @@
|
||||
//
|
||||
// MPParsedSummand.m
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 10.09.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import "MPParsedProduct.h"
|
||||
|
||||
@implementation MPParsedProduct {
|
||||
NSMutableArray *_factors;
|
||||
}
|
||||
|
||||
- (instancetype)init
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_factors = [[NSMutableArray alloc] init];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSArray *)factors
|
||||
{
|
||||
return _factors;
|
||||
}
|
||||
|
||||
- (void)addFactor:(MPParsedFactor *)factor
|
||||
{
|
||||
[_factors addObject:factor];
|
||||
}
|
||||
|
||||
- (NSDecimalNumber *)value
|
||||
{
|
||||
if (_factors.count == 0) {
|
||||
return [NSDecimalNumber zero];
|
||||
}
|
||||
NSDecimalNumber *value = [NSDecimalNumber one];
|
||||
for (MPParsedFactor *factor in _factors) {
|
||||
value = [value decimalNumberByMultiplyingBy:factor.value];
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
- (NSString *)description
|
||||
{
|
||||
return [NSString stringWithFormat:@"MPParsedProduct<%@>", [_factors componentsJoinedByString:@"*"]];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -33,6 +33,14 @@
|
||||
return 2;
|
||||
}
|
||||
|
||||
- (NSUInteger)indexOfChildAfterChildAtIndex:(NSUInteger)index
|
||||
{
|
||||
if (index != 2) {
|
||||
return 2;
|
||||
}
|
||||
return [super indexOfChildAfterChildAtIndex:index];
|
||||
}
|
||||
|
||||
- (CTLineRef)line
|
||||
{
|
||||
CTLineRef line = [self lineForPrivateCacheIndex:0 generator:^CTLineRef{
|
||||
|
||||
21
MathPad/NSRegularExpression+MPParsingAdditions.h
Normal file
21
MathPad/NSRegularExpression+MPParsingAdditions.h
Normal file
@@ -0,0 +1,21 @@
|
||||
//
|
||||
// NSRegularExpression+MPParsingAdditions.h
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 09.09.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#define MPStringRange(string) NSMakeRange(0, [string length])
|
||||
#define MPStringRangeFrom(from, string) NSMakeRange(from, [string length]-from)
|
||||
|
||||
@interface NSRegularExpression (MPParsingAdditions)
|
||||
|
||||
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string;
|
||||
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string fromIndex:(NSUInteger)start;
|
||||
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options;
|
||||
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options fromIndex:(NSUInteger)start;
|
||||
|
||||
@end
|
||||
33
MathPad/NSRegularExpression+MPParsingAdditions.m
Normal file
33
MathPad/NSRegularExpression+MPParsingAdditions.m
Normal file
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// NSRegularExpression+MPParsingAdditions.m
|
||||
// MathPad
|
||||
//
|
||||
// Created by Kim Wittenburg on 09.09.14.
|
||||
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NSRegularExpression+MPParsingAdditions.h"
|
||||
|
||||
@implementation NSRegularExpression (MPParsingAdditions)
|
||||
|
||||
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string
|
||||
{
|
||||
return [self firstMatchInString:string options:0 range:MPStringRange(string)];
|
||||
}
|
||||
|
||||
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string fromIndex:(NSUInteger)start
|
||||
{
|
||||
return [self firstMatchInString:string options:0 range:NSMakeRange(start, [string length]-start)];
|
||||
}
|
||||
|
||||
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options
|
||||
{
|
||||
return [self firstMatchInString:string options:options range:MPStringRange(string)];
|
||||
}
|
||||
|
||||
- (NSTextCheckingResult *)firstMatchInString:(NSString *)string options:(NSMatchingOptions)options fromIndex:(NSUInteger)start
|
||||
{
|
||||
return [self firstMatchInString:string options:options range:NSMakeRange(start, [string length]-start)];
|
||||
}
|
||||
|
||||
@end
|
||||
@@ -21,9 +21,4 @@
|
||||
return NO;
|
||||
}
|
||||
|
||||
- (NSDecimalNumber *)evaluate:(MPParseError *__autoreleasing *)error
|
||||
{
|
||||
return [[[MPElementParser alloc] init] parseElement:self error:error].standaloneValue;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
Reference in New Issue
Block a user