Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Parsing with Blocks

Parsing with Blocks

CocoaHeads Hamburg

More Decks by Chris Eidhof | @chriseidhof

Other Decks in Technology

Transcript

  1. stylesheet { multiplier = if(slide.onlyHeader, 2, 1), baseFontSize = 45

    * multiplier, splitBaseFontSize = 25, backgroundColor = colorScheme.backgroundColor, bodyFont = { family = "Apercu", color = colorScheme.textColor, size = baseFontSize } }
  2. Parsing 1. String → Stream of tokens 2. Stream of

    tokens → Syntax Tree 3. Interpret Syntax Tree
  3. 1 + 2 * 3 Expr ← Sum Sum ←

    Product '+' Product Product ← Atom '*' Atom Atom ← Number
  4. 1 + 2 * 3 Expr ← Sum Sum ←

    Product '+' Product | Product Product ← Atom '*' Atom | Atom Atom ← Number
  5. (1 + 2) * 3 Expr ← Sum Sum ←

    Product '+' Product | Product Product ← Atom '*' Atom | Atom Atom ← Number | '(' Expr ')'
  6. stylesheet { multiplier = if(slide.onlyHeader, 2, 1), baseFontSize = 45

    * multiplier, splitBaseFontSize = 25, backgroundColor = colorScheme.backgroundColor, bodyFont = { family = "Apercu", color = colorScheme.textColor, size = baseFontSize } }
  7. Rule stylesheet = ^(State *p) { __block NSArray *functions =

    nil; return p.identifier().token(@"{"). manySepBy(method, comma).bind(to(functions)). token(@"}").yield(^id { return [[StylesheetObject alloc] initWithFunctions:functions]; }); };
  8. Rule method = ^(State * p) { __block NSString* name

    = nil; __block id body= nil; __block NSArray *parameters = nil; return p.identifier().bind(to(name)). optional(parameterList).bind(to(parameters)). token(@"="). rule(self.expression).bind(to(body)). yield(^id { return [[StylesheetFunction alloc] initWithName:name body:body parameters:parameters]; }); };
  9. API

  10. @interface State : NSObject @property (nonatomic, strong) id result; @property

    (nonatomic) BOOL failed; @property (nonatomic) NSString *errorMessage; @property (nonatomic) State *(^token)(NSString *); @property (nonatomic) State *(^identifier)(); @property (nonatomic) State *(^yield)(id (^)()); @property (nonatomic) State *(^bind)(void(^)(id result)); @property (nonatomic) State *(^oneOf)(NSArray *); @property (nonatomic) State *(^optional)(Rule); @property (nonatomic) State *(^eof)(); @property (nonatomic) State *(^rule)(Rule); @end
  11. self.token = ^(NSString* token) { if (self.failed) return self; NSString*

    peek = self.peek; if ([token isEqual:peek]) { return [self next:peek]; } else { NSString* msg = [NSString stringWithFormat:@"Expected '%@', saw '%@'", token, peek]; return [self fail:msg]; } };
  12. - (State *)next:(id)result { if (self.failed) return self; State *next

    = [self copy]; next.failed = NO; next.result = result; next.tokenIndex++; return next; }
  13. We created two DSLs → One for parsing (embedded) →

    One external https://github.com/chriseidhof/parsingwithblocks