/lib/Shelley/Shelley/SYParser.m

http://github.com/moredip/Frank · Objective C · 248 lines · 192 code · 49 blank · 7 comment · 41 complexity · 9dff7f637f6d186dd067d03a18567376 MD5 · raw file

  1. //
  2. // SYParser.m
  3. // Shelley
  4. //
  5. // Created by Pete Hodgson on 7/17/11.
  6. // Copyright 2011 ThoughtWorks. All rights reserved.
  7. //
  8. #import "SYParser.h"
  9. #import "SYParents.h"
  10. #import "SYPredicateFilter.h"
  11. #import "SYClassFilter.h"
  12. #import "SYNthElementFilter.h"
  13. @interface SYSectionParser : NSObject {
  14. NSScanner *_scanner;
  15. NSCharacterSet *_paramChars;
  16. NSCharacterSet *_numberChars;
  17. NSMutableArray *_params;
  18. NSMutableArray *_args;
  19. }
  20. @property(readonly) NSArray *params, *args;
  21. - (id)initWithScanner: (NSScanner *)scanner;
  22. - (void) parse;
  23. - (BOOL) hasNoArgs;
  24. @end
  25. @implementation SYSectionParser
  26. @synthesize params=_params,args=_args;
  27. - (id)initWithScanner: (NSScanner *)scanner{
  28. self = [super init];
  29. if (self) {
  30. _scanner = [scanner retain];
  31. _paramChars = [[NSCharacterSet letterCharacterSet] retain];
  32. _numberChars = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."]retain];
  33. _params = [[NSMutableArray alloc] init];
  34. _args = [[NSMutableArray alloc] init];
  35. }
  36. return self;
  37. }
  38. - (void)dealloc {
  39. [_scanner release];
  40. [_paramChars release];
  41. [_numberChars release];
  42. [_params release];
  43. [_args release];
  44. [super dealloc];
  45. }
  46. - (BOOL) hasNoArgs {
  47. return [_args count] == 0;
  48. }
  49. - (BOOL) parseParamWithoutColon{
  50. NSString *paramString;
  51. if( [_scanner scanCharactersFromSet:_paramChars intoString:&paramString] ){
  52. [_params addObject:paramString];
  53. return YES;
  54. }else{
  55. return NO;
  56. }
  57. }
  58. - (BOOL) parseColon{
  59. return [_scanner scanString:@":" intoString:NULL];
  60. }
  61. - (BOOL) parseParamWithColon{
  62. if( ![self parseParamWithoutColon] )
  63. return NO;
  64. if( ![self parseColon] )
  65. [NSException raise:@"Parse Error" format:@"expected a :"];
  66. return YES;
  67. }
  68. - (BOOL) parseSingleQuote{
  69. return [_scanner scanString:@"'" intoString:NULL];
  70. }
  71. - (BOOL) parseDoubleQuote{
  72. return [_scanner scanString:@"\"" intoString:NULL];
  73. }
  74. - (NSString *)parseSingleQuotedString{
  75. if( ![self parseSingleQuote] )
  76. return nil;
  77. NSString *string;
  78. [_scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"'"] intoString:&string];
  79. [self parseSingleQuote];
  80. return string;
  81. }
  82. - (NSString *)parseDoubleQuotedString{
  83. if( ![self parseDoubleQuote] )
  84. return nil;
  85. NSString *string;
  86. [_scanner scanUpToCharactersFromSet:[NSCharacterSet characterSetWithCharactersInString:@"\""] intoString:&string];
  87. [self parseDoubleQuote];
  88. return string;
  89. }
  90. - (NSString *)parseQuotedString{
  91. NSString *string = [self parseSingleQuotedString];
  92. if( !string )
  93. string = [self parseDoubleQuotedString];
  94. return string;
  95. }
  96. - (NSNumber *) parseNumber{
  97. NSString *numberString;
  98. if( ![_scanner scanCharactersFromSet:_numberChars intoString:&numberString] )
  99. return nil;
  100. NSNumberFormatter *f = [[[NSNumberFormatter alloc] init] autorelease];
  101. return [f numberFromString:numberString];
  102. }
  103. - (id) parseArg{
  104. NSString *parsedString = [self parseQuotedString];
  105. if( parsedString )
  106. return parsedString;
  107. return [self parseNumber];
  108. }
  109. - (void) parseArgAndCollect{
  110. id arg = [self parseArg];
  111. if( arg )
  112. [_args addObject:arg];
  113. }
  114. - (void) parse{
  115. [self parseParamWithoutColon];
  116. if( ![self parseColon] ){
  117. return;
  118. }
  119. [self parseArgAndCollect];
  120. while( YES ){
  121. if( ![self parseParamWithColon] )
  122. break;
  123. [self parseArgAndCollect];
  124. }
  125. }
  126. @end
  127. @implementation SYParser
  128. - (id)initWithSelectorString:(NSString *)selectorString {
  129. self = [super init];
  130. if (self) {
  131. _scanner = [[NSScanner alloc] initWithString:selectorString];
  132. [_scanner setCharactersToBeSkipped:nil];
  133. _paramChars = [[NSCharacterSet letterCharacterSet] retain];
  134. _numberChars = [[NSCharacterSet characterSetWithCharactersInString:@"0123456789."]retain];
  135. _currentParams = [[NSMutableArray alloc] init];
  136. _currentArgs = [[NSMutableArray alloc] init];
  137. }
  138. return self;
  139. }
  140. - (void)dealloc {
  141. [_scanner release];
  142. [_paramChars release];
  143. [_numberChars release];
  144. [_currentParams release];
  145. [_currentArgs release];
  146. [super dealloc];
  147. }
  148. - (id<SYFilter>) interpretSectionIntoFilter:(SYSectionParser *)parsedSection{
  149. NSString *firstParam = [[parsedSection params] objectAtIndex:0];
  150. if( [parsedSection hasNoArgs] ){
  151. if( [firstParam isEqualToString:@"parent"] )
  152. return [[[SYParents alloc] init] autorelease];
  153. if( [firstParam isEqualToString:@"first"] )
  154. return [[[SYNthElementFilter alloc] initWithIndex:0] autorelease];
  155. else if( [firstParam isEqualToString:@"view"] )
  156. return [[[SYClassFilter alloc] initWithClass:[UIView class]] autorelease];
  157. else if( [firstParam isEqualToString:@"descendant"] )
  158. return [[[SYClassFilter alloc] initWithClass:[UIView class] includeSelf:YES] autorelease];
  159. else if( [firstParam isEqualToString:@"button"] )
  160. return [[[SYClassFilter alloc] initWithClass:[UIButton class]] autorelease];
  161. else if( [firstParam isEqualToString:@"alertView"] )
  162. return [[[SYClassFilter alloc] initWithClass:[UIAlertView class]] autorelease];
  163. else if( [firstParam isEqualToString:@"navigationButton"] )
  164. return [[[SYClassFilter alloc] initWithClass:NSClassFromString(@"UINavigationButton")] autorelease];
  165. else if( [firstParam isEqualToString:@"navigationItemView"] )
  166. return [[[SYClassFilter alloc] initWithClass:NSClassFromString(@"UINavigationItemView")] autorelease];
  167. else if( [firstParam isEqualToString:@"textField"] )
  168. return [[[SYClassFilter alloc] initWithClass:[UITextField class]] autorelease];
  169. else if( [firstParam isEqualToString:@"tableView"] )
  170. return [[[SYClassFilter alloc] initWithClass:[UITableView class]] autorelease];
  171. else if( [firstParam isEqualToString:@"tableViewCell"] )
  172. return [[[SYClassFilter alloc] initWithClass:[UITableViewCell class]] autorelease];
  173. }else if( [[parsedSection args] count] == 1 ){
  174. if( [firstParam isEqualToString:@"view"] ) {
  175. NSString *firstArg = [[parsedSection args] objectAtIndex:0];
  176. return [[[SYClassFilter alloc] initWithClass:(NSClassFromString(firstArg))] autorelease];
  177. }else if( [firstParam isEqualToString:@"index"] ) {
  178. NSNumber *firstArg = [[parsedSection args] objectAtIndex:0];
  179. return [[[SYNthElementFilter alloc] initWithIndex:[firstArg unsignedIntValue]] autorelease];
  180. }
  181. }
  182. NSString *selectorDesc;
  183. if( [parsedSection hasNoArgs] ){
  184. selectorDesc = [[parsedSection params] objectAtIndex:0];
  185. }else{
  186. selectorDesc = [[[parsedSection params] componentsJoinedByString:@":"] stringByAppendingString:@":"];
  187. }
  188. return [[[SYPredicateFilter alloc] initWithSelector:NSSelectorFromString(selectorDesc)
  189. args:[parsedSection args]] autorelease];
  190. }
  191. - (id<SYFilter>) nextFilter{
  192. [_scanner scanCharactersFromSet:[NSCharacterSet whitespaceCharacterSet] intoString:nil];
  193. if( [_scanner isAtEnd] )
  194. return nil;
  195. SYSectionParser *sectionParser = [[[SYSectionParser alloc] initWithScanner:_scanner] autorelease];
  196. [sectionParser parse];
  197. return [self interpretSectionIntoFilter:sectionParser];
  198. }
  199. @end