forked from tombenner/nui
-
Notifications
You must be signed in to change notification settings - Fork 0
/
NUIStyleParser.m
112 lines (93 loc) · 4.35 KB
/
NUIStyleParser.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
//
// NUIStyleParser.m
// NUIDemo
//
// Created by Tom Benner on 12/4/12.
// Copyright (c) 2012 Tom Benner. All rights reserved.
//
#import "NUIStyleParser.h"
#import <Parcoa/Parcoa.h>
static ParcoaParser *_styleParser;
@implementation NUIStyleParser
#pragma mark - Style Parser Definition
+ (ParcoaParser *)buildStyleParser {
ParcoaParser *comma = [[Parcoa unichar:','] skipSurroundingSpaces];
ParcoaParser *colon = [[Parcoa unichar:':'] skipSurroundingSpaces];
ParcoaParser *semiColon = [[Parcoa unichar:';'] skipSurroundingSpaces];
ParcoaParser *openBrace = [[Parcoa unichar:'{'] skipSurroundingSpaces];
ParcoaParser *closeBrace = [[Parcoa unichar:'}'] skipSurroundingSpaces];
ParcoaParser *dash = [Parcoa unichar:'-'];
ParcoaParser *alpha = [Parcoa letter];
ParcoaParser *alphaNum = [Parcoa alphaNum];
// Token must start with a space but then can be followed by a dash or any
// alphanumeric character.
ParcoaParser *token = [[alpha then:[[alphaNum or: dash] concatMany]] concat];
ParcoaParser *value = [Parcoa takeUntil:[Parcoa isUnichar:';']];
ParcoaParser *declaration = [[token keepLeft:colon] then:[value keepLeft:semiColon]];
ParcoaParser *declarations = [[declaration many] dictionary];
ParcoaParser *classExpression = [token sepBy1:comma];
ParcoaParser *ruleSet = [[classExpression then: [declarations between:openBrace and:closeBrace]]
dictionaryWithKeys:@[@"classes", @"declarations"]];
ParcoaParser *topLevelDeclaration = [[Parcoa unichar:'@'] keepRight: declaration];
ParcoaParser *topLevelDeclarations = [[topLevelDeclaration many] dictionary];
ParcoaParser *nss = [[topLevelDeclarations then: [ruleSet many]]
dictionaryWithKeys:@[@"topLevelDeclarations", @"ruleSets"]];
return nss;
}
+ (ParcoaParser *)styleParser {
if (!_styleParser) {
_styleParser = [NUIStyleParser buildStyleParser];
}
return _styleParser;
}
- (NSDictionary *)parse:(NSString *)input {
ParcoaResult *result = [[NUIStyleParser styleParser] parse:input];
if (result.isOK) {
return result.value;
} else {
NSLog(@"Parsing failed: %@", [result traceback:input]);
return nil;
}
}
- (NSMutableDictionary*)getStylesFromFile:(NSString*)fileName
{
NSString* path = [[NSBundle mainBundle] pathForResource:fileName ofType:@"nss"];
NSString* content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
return [self getStylesFromString:content];
}
- (NSMutableDictionary *)getStylesFromString:(NSString *)content {
NSDictionary *result = [self parse:content];
if (result) {
return [self consolidateRuleSets:result[@"ruleSets"] withTopLevelDeclarations:result[@"topLevelDeclarations"]];
} else {
return [NSMutableDictionary dictionary];
}
}
#pragma mark - Consolidation
- (NSMutableDictionary*)consolidateRuleSets:(NSMutableArray*)ruleSets withTopLevelDeclarations:(NSMutableDictionary*)topLevelDeclarations
{
NSMutableDictionary *consolidatedRuleSets = [[NSMutableDictionary alloc] init];
for (NSMutableDictionary *ruleSet in ruleSets) {
NSArray *classes = [ruleSet objectForKey:@"classes"];
for (NSString *class in classes) {
if ([consolidatedRuleSets objectForKey:class] == nil) {
[consolidatedRuleSets setValue:[[NSMutableDictionary alloc] init] forKey:class];
}
[self mergeRuleSetIntoConsolidatedRuleSet:ruleSet consolidatedRuleSet:[consolidatedRuleSets objectForKey:class] topLevelDeclarations:topLevelDeclarations];
}
}
return consolidatedRuleSets;
}
- (NSMutableDictionary*)mergeRuleSetIntoConsolidatedRuleSet:(NSMutableDictionary*)ruleSet consolidatedRuleSet:(NSMutableDictionary*)consolidatedRuleSet topLevelDeclarations:(NSMutableDictionary*)topLevelDeclarations
{
NSMutableDictionary *declarations = [ruleSet objectForKey:@"declarations"];
for (NSString *property in declarations) {
NSString *value = [declarations objectForKey:property];
if ([value hasPrefix:@"@"]) {
value = [topLevelDeclarations objectForKey:[value substringFromIndex:1]];
}
[consolidatedRuleSet setValue:value forKey:property];
}
return consolidatedRuleSet;
}
@end