diff --git a/HTMLKit.xcodeproj/project.pbxproj b/HTMLKit.xcodeproj/project.pbxproj
index a4c407d..bf20a73 100644
--- a/HTMLKit.xcodeproj/project.pbxproj
+++ b/HTMLKit.xcodeproj/project.pbxproj
@@ -8,7 +8,6 @@
/* Begin PBXBuildFile section */
62079BE91AF56F1E00D3B402 /* CSSSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 62079BE71AF56F1E00D3B402 /* CSSSelector.h */; };
- 620802021AFD939200F2962F /* CSSTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 623F13A81AFC11D900C90BF4 /* CSSTokenizer.h */; };
620C877B1BD44CBE00FB3EEE /* CSSCompoundSelector.h in Headers */ = {isa = PBXBuildFile; fileRef = 620C87791BD44CBE00FB3EEE /* CSSCompoundSelector.h */; settings = {ASSET_TAGS = (); }; };
620C877C1BD44CBE00FB3EEE /* CSSCompoundSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 620C877A1BD44CBE00FB3EEE /* CSSCompoundSelector.m */; settings = {ASSET_TAGS = (); }; };
620C877D1BD44CBE00FB3EEE /* CSSCompoundSelector.m in Sources */ = {isa = PBXBuildFile; fileRef = 620C877A1BD44CBE00FB3EEE /* CSSCompoundSelector.m */; settings = {ASSET_TAGS = (); }; };
@@ -70,8 +69,6 @@
6239755F1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 6239755D1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m */; };
623CAF9D1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 623CAF9C1AD88BEA00E34C32 /* HTMLKitParserPerformance.m */; };
623CAF9E1AD88BEA00E34C32 /* HTMLKitParserPerformance.m in Sources */ = {isa = PBXBuildFile; fileRef = 623CAF9C1AD88BEA00E34C32 /* HTMLKitParserPerformance.m */; };
- 623F13AB1AFC11D900C90BF4 /* CSSTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 623F13A91AFC11D900C90BF4 /* CSSTokenizer.m */; };
- 623F13AC1AFC11D900C90BF4 /* CSSTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 623F13A91AFC11D900C90BF4 /* CSSTokenizer.m */; };
624493A619CCC54100BCDDF4 /* HTMLTokenizer.h in Headers */ = {isa = PBXBuildFile; fileRef = 624493A419CCC54100BCDDF4 /* HTMLTokenizer.h */; };
624493A719CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493A519CCC54100BCDDF4 /* HTMLTokenizer.m */; };
624493A819CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */ = {isa = PBXBuildFile; fileRef = 624493A519CCC54100BCDDF4 /* HTMLTokenizer.m */; };
@@ -116,9 +113,6 @@
624B371E1B24E9BA0010BDDF /* CSSInputStream.h in Headers */ = {isa = PBXBuildFile; fileRef = 624B371C1B24E9BA0010BDDF /* CSSInputStream.h */; };
624B371F1B24E9BA0010BDDF /* CSSInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B371D1B24E9BA0010BDDF /* CSSInputStream.m */; };
624B37201B24E9BA0010BDDF /* CSSInputStream.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B371D1B24E9BA0010BDDF /* CSSInputStream.m */; };
- 624B7DDC1B2E3AAB00A4BD61 /* CSSToken.h in Headers */ = {isa = PBXBuildFile; fileRef = 624B7DDA1B2E3AAB00A4BD61 /* CSSToken.h */; };
- 624B7DDD1B2E3AAB00A4BD61 /* CSSToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B7DDB1B2E3AAB00A4BD61 /* CSSToken.m */; };
- 624B7DDE1B2E3AAB00A4BD61 /* CSSToken.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B7DDB1B2E3AAB00A4BD61 /* CSSToken.m */; };
624B9FB21AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */; };
624B9FB31AE0313300646C4C /* HTMLKitStringCategoryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */; };
624B9FB51AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */; };
@@ -274,8 +268,6 @@
6239755C1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTML5LibTreeConstructionTest.h; sourceTree = ""; };
6239755D1AC364BB007E26F1 /* HTML5LibTreeConstructionTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTML5LibTreeConstructionTest.m; sourceTree = ""; };
623CAF9C1AD88BEA00E34C32 /* HTMLKitParserPerformance.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitParserPerformance.m; sourceTree = ""; };
- 623F13A81AFC11D900C90BF4 /* CSSTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSTokenizer.h; sourceTree = ""; };
- 623F13A91AFC11D900C90BF4 /* CSSTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSTokenizer.m; sourceTree = ""; };
624493A419CCC54100BCDDF4 /* HTMLTokenizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizer.h; sourceTree = ""; };
624493A519CCC54100BCDDF4 /* HTMLTokenizer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLTokenizer.m; sourceTree = ""; };
624493A919CCE84A00BCDDF4 /* HTMLTokenizerStates.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HTMLTokenizerStates.h; sourceTree = ""; };
@@ -307,8 +299,6 @@
624B371C1B24E9BA0010BDDF /* CSSInputStream.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSInputStream.h; sourceTree = ""; };
624B371D1B24E9BA0010BDDF /* CSSInputStream.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSInputStream.m; sourceTree = ""; };
624B37211B250BB50010BDDF /* CSSCodePoints.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CSSCodePoints.h; sourceTree = ""; };
- 624B7DDA1B2E3AAB00A4BD61 /* CSSToken.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CSSToken.h; sourceTree = ""; };
- 624B7DDB1B2E3AAB00A4BD61 /* CSSToken.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CSSToken.m; sourceTree = ""; };
624B9FB11AE0313300646C4C /* HTMLKitStringCategoryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitStringCategoryTests.m; sourceTree = ""; };
624B9FB41AE0391400646C4C /* HTMLKitOrderedDictionaryTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitOrderedDictionaryTests.m; sourceTree = ""; };
624FC3791AE591D80015DDF9 /* HTMLKitNodesTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HTMLKitNodesTests.m; sourceTree = ""; };
@@ -418,10 +408,6 @@
624B371D1B24E9BA0010BDDF /* CSSInputStream.m */,
62F501631BC9576B0069F47B /* CSSNthExpressionParser.h */,
62F501641BC9576B0069F47B /* CSSNthExpressionParser.m */,
- 623F13A81AFC11D900C90BF4 /* CSSTokenizer.h */,
- 623F13A91AFC11D900C90BF4 /* CSSTokenizer.m */,
- 624B7DDA1B2E3AAB00A4BD61 /* CSSToken.h */,
- 624B7DDB1B2E3AAB00A4BD61 /* CSSToken.m */,
62079BE71AF56F1E00D3B402 /* CSSSelector.h */,
62FC60451BD0519B0042BBE7 /* CSSSelector.m */,
62FA98061BD5A7E200A2AF86 /* CSSSelectorBlock.h */,
@@ -711,7 +697,6 @@
62D89DB21AE7081600B6243D /* HTMLTokenizerCharacters.h in Headers */,
62D89DB31AE7081600B6243D /* HTMLNamespaces.h in Headers */,
624B28BC1B03DAB70048D328 /* HTMLNodeFilter.h in Headers */,
- 624B7DDC1B2E3AAB00A4BD61 /* CSSToken.h in Headers */,
624B28BF1B0413200048D328 /* CSSAttributeSelector.h in Headers */,
62D89DB41AE7081600B6243D /* HTMLElementTypes.h in Headers */,
628AF6331BC9A63D00496128 /* CSSNthExpressionSelector.h in Headers */,
@@ -747,7 +732,6 @@
625A150819C78ABA00AD0C32 /* HTMLInputStreamReader.h in Headers */,
62FA04E31BCC360D009ABF98 /* CSSCombinatorSelector.h in Headers */,
6238579B1A9E8934003A45D9 /* HTMLComment.h in Headers */,
- 620802021AFD939200F2962F /* CSSTokenizer.h in Headers */,
62AE593519F97D880043F069 /* HTMLParseErrorToken.h in Headers */,
62AE594919F9948A0043F069 /* HTMLCharacterToken.h in Headers */,
623857961A9E8606003A45D9 /* HTMLDocumentType.h in Headers */,
@@ -935,12 +919,10 @@
625A150A19C78ABA00AD0C32 /* HTMLInputStreamReader.m in Sources */,
628AF6351BC9A63D00496128 /* CSSNthExpressionSelector.m in Sources */,
623857931A9E772B003A45D9 /* HTMLDocument.m in Sources */,
- 624B7DDE1B2E3AAB00A4BD61 /* CSSToken.m in Sources */,
623406E81ADB05AD004677A3 /* HTMLDocumentFragment.m in Sources */,
624717B91B21FE5400B38302 /* HTMLNodeFilter.m in Sources */,
620EE94B1BC46F2A0028ED34 /* CSSPseudoClassSelector.m in Sources */,
624493A819CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */,
- 623F13AC1AFC11D900C90BF4 /* CSSTokenizer.m in Sources */,
624B28BA1B03DA820048D328 /* CSSTypeSelector.m in Sources */,
625A14BE19C7829400AD0C32 /* HTMLKit.m in Sources */,
62FC60471BD0519B0042BBE7 /* CSSSelector.m in Sources */,
@@ -1009,12 +991,10 @@
620C877C1BD44CBE00FB3EEE /* CSSCompoundSelector.m in Sources */,
625A150919C78ABA00AD0C32 /* HTMLInputStreamReader.m in Sources */,
623857921A9E772B003A45D9 /* HTMLDocument.m in Sources */,
- 624B7DDD1B2E3AAB00A4BD61 /* CSSToken.m in Sources */,
623406E71ADB05AD004677A3 /* HTMLDocumentFragment.m in Sources */,
624717B81B21FE5400B38302 /* HTMLNodeFilter.m in Sources */,
620EE94A1BC46F2A0028ED34 /* CSSPseudoClassSelector.m in Sources */,
624493A719CCC54100BCDDF4 /* HTMLTokenizer.m in Sources */,
- 623F13AB1AFC11D900C90BF4 /* CSSTokenizer.m in Sources */,
624B28B91B03DA820048D328 /* CSSTypeSelector.m in Sources */,
625A150219C783DE00AD0C32 /* HTMLKit.m in Sources */,
623857971A9E8606003A45D9 /* HTMLDocumentType.m in Sources */,
diff --git a/HTMLKit/CSSToken.h b/HTMLKit/CSSToken.h
deleted file mode 100644
index bc3383e..0000000
--- a/HTMLKit/CSSToken.h
+++ /dev/null
@@ -1,86 +0,0 @@
-//
-// CSSToken.h
-// HTMLKit
-//
-// Created by Iska on 15/06/15.
-// Copyright (c) 2015 BrainCookie. All rights reserved.
-//
-
-#import
-
-typedef NS_ENUM(NSUInteger, CSSTokenType)
-{
- CSSTokenTypeIdent,
- CSSTokenTypeFunction,
- CSSTokenTypeAtKeyword,
- CSSTokenTypeHash,
- CSSTokenTypeString,
- CSSTokenTypeBadString,
- CSSTokenTypeURL,
- CSSTokenTypeBadURL,
- CSSTokenTypeDelim,
- CSSTokenTypeNumber,
- CSSTokenTypePercentage,
- CSSTokenTypeDimension,
- CSSTokenTypeUnicodeRange,
- CSSTokenTypeIncludeMatch,
- CSSTokenTypeDashMatch,
- CSSTokenTypePrefixMatch,
- CSSTokenTypeSuffixMatch,
- CSSTokenTypeSubstringMatch,
- CSSTokenTypeColumn,
- CSSTokenTypeWhitespace,
- CSSTokenTypeCommentDeclarationOpen,
- CSSTokenTypeCommentDeclarationClose,
- CSSTokenTypeColon,
- CSSTokenTypeSemicolon,
- CSSTokenTypeComma,
- CSSTokenTypeSquareBracketOpen,
- CSSTokenTypeSquareBracketClose,
- CSSTokenTypeParenthesisOpen,
- CSSTokenTypeParenthesisClose,
- CSSTokenTypeCurlyBracketOpen,
- CSSTokenTypeCurlyBracketClose,
- CSSTokenTypeEOF
-};
-
-@interface CSSToken : NSObject
-
-@property (nonatomic, assign) CSSTokenType type;
-@property (nonatomic, assign) NSUInteger location;
-@property (nonatomic, assign) NSUInteger length;
-@property (nonatomic, copy) NSString *text;
-
-+ (instancetype)tokenWithType:(CSSTokenType)type;
-
-@end
-
-#pragma mark - Unicode Range
-
-@interface CSSUnicodeRangeToken : CSSToken
-@property (nonatomic, assign) unsigned int start;
-@property (nonatomic, assign) unsigned int end;
-@end
-
-#pragma mark - Numeric Tokens
-
-typedef NS_ENUM(NSUInteger, CSSNumericTokenType)
-{
- CSSNumericTokenTypeInteger,
- CSSNumericTokenTypeNumber
-};
-
-@interface CSSNumericToken : CSSToken
-@property (nonatomic, assign) CSSNumericTokenType numericType;
-@property (nonatomic, strong) NSNumber *value;
-@end
-
-@interface CSSDimensionToken : CSSNumericToken
-@property (nonatomic, copy) NSString *unit;
-@end
-
-@interface CSSNumberToken : CSSNumericToken
-@end
-
-@interface CSSPercentageToken : CSSNumericToken
-@end
diff --git a/HTMLKit/CSSToken.m b/HTMLKit/CSSToken.m
deleted file mode 100644
index c91fb0a..0000000
--- a/HTMLKit/CSSToken.m
+++ /dev/null
@@ -1,69 +0,0 @@
-//
-// CSSToken.m
-// HTMLKit
-//
-// Created by Iska on 15/06/15.
-// Copyright (c) 2015 BrainCookie. All rights reserved.
-//
-
-#import "CSSToken.h"
-
-@implementation CSSToken
-
-+ (instancetype)tokenWithType:(CSSTokenType)type
-{
- CSSToken *token = [[self alloc] init];
- token.type = type;
- return token;
-}
-
-- (instancetype)initWithType:(CSSTokenType)type
-{
- self = [super init];
- if (self) {
- self.type = type;
- }
- return self;
-}
-
-@end
-
-#pragma mark - Unicode Range
-
-@implementation CSSUnicodeRangeToken
-@end
-
-#pragma mark - Numeric
-
-@implementation CSSNumericToken
-@end
-
-@implementation CSSDimensionToken
-
-- (instancetype)init
-{
- self = [self initWithType:CSSTokenTypeDimension];
- return self;
-}
-
-@end
-
-@implementation CSSNumberToken
-
-- (instancetype)init
-{
- self = [self initWithType:CSSTokenTypeNumber];
- return self;
-}
-
-@end
-
-@implementation CSSPercentageToken
-
-- (instancetype)init
-{
- self = [self initWithType:CSSTokenTypePercentage];
- return self;
-}
-
-@end
\ No newline at end of file
diff --git a/HTMLKit/CSSTokenizer.h b/HTMLKit/CSSTokenizer.h
deleted file mode 100644
index 262468d..0000000
--- a/HTMLKit/CSSTokenizer.h
+++ /dev/null
@@ -1,18 +0,0 @@
-//
-// CSSTokenizer.h
-// HTMLKit
-//
-// Created by Iska on 07/05/15.
-// Copyright (c) 2015 BrainCookie. All rights reserved.
-//
-
-#import
-#import "CSSToken.h"
-
-@interface CSSTokenizer : NSEnumerator
-
-@property (nonatomic, readonly, strong) NSString *string;
-
-- (instancetype)initWithString:(NSString *)string;
-
-@end
diff --git a/HTMLKit/CSSTokenizer.m b/HTMLKit/CSSTokenizer.m
deleted file mode 100644
index b22c808..0000000
--- a/HTMLKit/CSSTokenizer.m
+++ /dev/null
@@ -1,663 +0,0 @@
- //
-// CSSTokenizer.m
-// HTMLKit
-//
-// Created by Iska on 07/05/15.
-// Copyright (c) 2015 BrainCookie. All rights reserved.
-//
-
-#import "CSSTokenizer.h"
-#import "CSSInputStream.h"
-#import "CSSTokenizerCodePoints.h"
-#import "NSString+HTMLKit.h"
-
-@interface CSSTokenizer ()
-{
- NSString *_string;
- CSSInputStream *_inputStream;
-}
-@end
-
-@implementation CSSTokenizer
-@synthesize string = _string;
-
-#pragma mark - Lifecycle
-
-- (instancetype)initWithString:(NSString *)string
-{
- self = [super init];
- if (self) {
- _string = [self preprocessInput:string];
- _inputStream = [[CSSInputStream alloc] initWithString:_string];
- }
- return self;
-}
-
-#pragma mark - Preprocess
-
-- (NSString *)preprocessInput:(NSString *)string
-{
- string = [string stringByReplacingOccurrencesOfString:@"\r\n" withString:@"\n"];
- string = [string stringByReplacingOccurrencesOfString:@"\r" withString:@"\n"];
- string = [string stringByReplacingOccurrencesOfString:@"\f" withString:@"\n"];
- string = [string stringByReplacingOccurrencesOfString:@"\0" withString:@"\uFFFD"];
-
- return string;
-}
-
-#pragma mark - Enumerator
-
-- (id)nextObject
-{
- CSSToken *token = [self consumeToken];
- if (token.type == CSSTokenTypeEOF) {
- return nil;
- }
- return token;
-}
-
-#pragma mark - Tokenize
-
-- (void)parseError
-{
- NSString *errorMessage = [NSString stringWithFormat:@"Parse error at %lu", (unsigned long)_inputStream.location];
- NSLog(@"%@", errorMessage);
-}
-
-- (CSSToken *)consumeToken
-{
- [self consumeComments];
-
- NSUInteger start = _inputStream.location;
- UniChar codePoint = [_inputStream consumeNextCodePoint];
- CSSToken *token = nil;
-
- if (isWhitespace(codePoint)) {
- token = [self consumeWhitespace];
- } else if (isQuote(codePoint)) {
- token = [self consumeStringTokenWithEndingCodePoint:codePoint];
- } else if (isDigit(codePoint)) {
- token = [self consumeNumericToken];
- } else if (codePoint == NUMBER_SIGN) {
- if (isName([_inputStream nextCodePoint]) ||
- isValidEscape([_inputStream nextCodePoint], [_inputStream nextCodePointAtOffset:1])) {
- token = [CSSToken tokenWithType:CSSTokenTypeHash];
- if (isIdentifierStart([_inputStream nextCodePoint],
- [_inputStream nextCodePointAtOffset:1],
- [_inputStream nextCodePointAtOffset:2])) {
- token.type = CSSTokenTypeIdent;
- }
- token.text = [self consumeName];
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == DOLLAR_SIGN) {
- if ([_inputStream nextCodePoint] == EQUALS_SIGN) {
- [_inputStream consumeNextCodePoint];
- token = [CSSToken tokenWithType:CSSTokenTypeSuffixMatch];
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == LEFT_PARENTHESIS) {
- token = [CSSToken tokenWithType:CSSTokenTypeParenthesisOpen];
- } else if (codePoint == RIGHT_PARENTHESIS) {
- token = [CSSToken tokenWithType:CSSTokenTypeParenthesisClose];
- } else if (codePoint == ASTERIX) {
- if ([_inputStream nextCodePoint] == EQUALS_SIGN) {
- [_inputStream consumeNextCodePoint];
- token = [CSSToken tokenWithType:CSSTokenTypeSubstringMatch];
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == PLUS_SIGN) {
- if (isNumberStart([_inputStream currentCodePoint],
- [_inputStream nextCodePoint],
- [_inputStream nextCodePointAtOffset:1])) {
- [_inputStream reconsumeCurrentCodePoint];
- token = [self consumeNumericToken];
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == COMMA) {
- token = [CSSToken tokenWithType:CSSTokenTypeComma];
- } else if (codePoint == HYPHEN_MINUS) {
- if (isNumberStart([_inputStream currentCodePoint],
- [_inputStream nextCodePoint],
- [_inputStream nextCodePointAtOffset:1])) {
- [_inputStream reconsumeCurrentCodePoint];
- token = [self consumeNumericToken];
- } else if (isIdentifierStart([_inputStream currentCodePoint],
- [_inputStream nextCodePoint],
- [_inputStream nextCodePointAtOffset:1])){
- [_inputStream reconsumeCurrentCodePoint];
- token = [self consumeIdentLikeToken];
- } else if ([_inputStream nextCodePoint] == HYPHEN_MINUS &&
- [_inputStream nextCodePointAtOffset:1] == GREATERTHAN) {
- [_inputStream consumeNextCodePoint];
- [_inputStream consumeNextCodePoint];
- token = [CSSToken tokenWithType:CSSTokenTypeCommentDeclarationClose];
- }
- } else if (codePoint == FULL_STOP) {
- if (isNumberStart(codePoint, [_inputStream nextCodePoint], [_inputStream nextCodePointAtOffset:2])) {
- [_inputStream reconsumeCurrentCodePoint];
- token = [self consumeNumericToken];
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == SOLIDUS) {
- if ([_inputStream nextCodePoint] == ASTERIX) {
- [_inputStream reconsumeCurrentCodePoint];
- [self consumeComments];
- token = [self consumeToken];
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == COLON) {
- token = [CSSToken tokenWithType:CSSTokenTypeColon];
- } else if (codePoint == SEMICOLON) {
- token = [CSSToken tokenWithType:CSSTokenTypeSemicolon];
- } else if (codePoint == LESS_THAN_SIGN) {
- if ([_inputStream nextCodePoint] == EXCLAMATION_MARK &&
- [_inputStream nextCodePointAtOffset:1] == HYPHEN_MINUS &&
- [_inputStream nextCodePointAtOffset:2] == HYPHEN_MINUS) {
- [_inputStream consumeNextCodePoint];
- [_inputStream consumeNextCodePoint];
- [_inputStream consumeNextCodePoint];
- token = [CSSToken tokenWithType:CSSTokenTypeCommentDeclarationOpen];
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == COMMERCIAL_AT) {
- if (isIdentifierStart([_inputStream nextCodePoint],
- [_inputStream nextCodePointAtOffset:1],
- [_inputStream nextCodePointAtOffset:2])) {
- NSString *name = [self consumeName];
- token = [CSSToken tokenWithType:CSSTokenTypeAtKeyword];
- token.text = name;
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == LEFT_SQUARE_BRACKET) {
- token = [CSSToken tokenWithType:CSSTokenTypeSquareBracketOpen];
- } else if (codePoint == REVERSE_SOLIDUS) {
- if (isValidEscape(codePoint, [_inputStream nextCodePoint])) {
- [_inputStream reconsumeCurrentCodePoint];
- token = [self consumeIdentLikeToken];
- } else {
- [self parseError];
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == RIGHT_SQUARE_BRACKET) {
- token = [CSSToken tokenWithType:CSSTokenTypeSquareBracketClose];
- } else if (codePoint == CIRCUMFLEX_ACCENT) {
- if ([_inputStream nextCodePoint] == EQUALS_SIGN) {
- [_inputStream consumeNextCodePoint];
- token = [CSSToken tokenWithType:CSSTokenTypePrefixMatch];
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == LEFT_CURLY_BRACKET) {
- token = [CSSToken tokenWithType:CSSTokenTypeCurlyBracketOpen];
- } else if (codePoint == RIGHT_CURLY_BRACKET) {
- token = [CSSToken tokenWithType:CSSTokenTypeCurlyBracketClose];
- } else if (codePoint == LATIN_CAPITAL_LETTER_U || codePoint == LATIN_SMALL_LETTER_U) {
- if ([_inputStream nextCodePoint] == PLUS_SIGN &&
- (isHexDigit([_inputStream nextCodePointAtOffset:1]) ||
- [_inputStream nextCodePointAtOffset:1] == QUOTATION_MARK)) {
- [_inputStream consumeNextCodePoint];
- token = [self consumeUnicodeRange];
- } else {
- [_inputStream reconsumeCurrentCodePoint];
- token = [self consumeIdentLikeToken];
- }
- } else if (codePoint == VERTICAL_LINE) {
- if ([_inputStream nextCodePoint] == EQUALS_SIGN) {
- [_inputStream consumeNextCodePoint];
- token = [CSSToken tokenWithType:CSSTokenTypeDashMatch];
- } else if ([_inputStream nextCodePoint] == VERTICAL_LINE) {
- [_inputStream consumeNextCodePoint];
- token = [CSSToken tokenWithType:CSSTokenTypeColumn];
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == TILDE) {
- if ([_inputStream nextCodePoint] == EQUALS_SIGN) {
- [_inputStream consumeNextCodePoint];
- token = [CSSToken tokenWithType:CSSTokenTypeIncludeMatch];
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
- } else if (codePoint == EOF_CHARACTER) {
- token = [CSSToken tokenWithType:CSSTokenTypeEOF];
- } else {
- token = [CSSToken tokenWithType:CSSTokenTypeDelim];
- }
-
- token.location = start;
- token.length = _inputStream.location - start;
- token.text = [_string substringWithRange:NSMakeRange(token.location, token.length)];
-
- return token;
-}
-
-- (void)consumeComments
-{
- while ([_inputStream nextCodePointAtOffset:0] == SOLIDUS &&
- [_inputStream nextCodePointAtOffset:1] == ASTERIX) {
- [_inputStream consumeNextCodePoint];
- [_inputStream consumeNextCodePoint];
- while (YES) {
- UniChar codePoint = [_inputStream consumeNextCodePoint];
- if (codePoint == EOF_CHARACTER) {
- return;
- }
- if (codePoint == ASTERIX && [_inputStream nextCodePoint] == SOLIDUS) {
- [_inputStream consumeNextCodePoint];
- break;
- }
- }
- }
-}
-
-- (CSSToken *)consumeWhitespace
-{
- CFMutableStringRef value = CFStringCreateMutable(kCFAllocatorDefault, 0);
-
- while (isWhitespace([_inputStream nextCodePoint])) {
- UniChar codePoint = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(value, &codePoint, 1);
- }
-
- CSSToken *token = [CSSToken tokenWithType:CSSTokenTypeWhitespace];
- token.text = (__bridge_transfer NSString *)(value);
- return token;
-}
-
-- (CSSToken *)consumeNumericToken
-{
- NSNumber *value = nil;
- CSSNumericTokenType type = [self consumeNumber:&value];
-
- if (isIdentifierStart([_inputStream nextCodePoint],
- [_inputStream nextCodePointAtOffset:1],
- [_inputStream nextCodePointAtOffset:2])) {
- CSSDimensionToken *token = [CSSDimensionToken new];
- token.numericType = type;
- token.value = value;
- token.unit = [self consumeName];
- return token;
- } else if ([_inputStream nextCodePoint] == PERCENTAGE_SIGN) {
- CSSPercentageToken *token = [CSSPercentageToken tokenWithType:CSSTokenTypePercentage];
- token.value = value;
- return token;
- } else {
- CSSNumericToken *token = [CSSNumericToken tokenWithType:CSSTokenTypeNumber];
- token.numericType = type;
- token.value = value;
- return token;
- }
-}
-
-- (CSSToken *)consumeIdentLikeToken
-{
- NSString *name = [self consumeName];
-
- if ([name isEqualToStringIgnoringCase:@"url"] &&
- [_inputStream nextCodePoint] == LEFT_PARENTHESIS) {
- [_inputStream consumeNextCodePoint];
- return [self consumeURLToken];
- } else if ([_inputStream nextCodePoint] == LEFT_PARENTHESIS) {
- [_inputStream consumeNextCodePoint];
- CSSToken *token = [CSSToken tokenWithType:CSSTokenTypeFunction];
- token.text = name;
- return token;
- } else {
- CSSToken *token = [CSSToken tokenWithType:CSSTokenTypeIdent];
- token.text = name;
- return token;
- }
-}
-
-- (CSSToken *)consumeStringTokenWithEndingCodePoint:(UniChar)endingCodePoint
-{
- CFMutableStringRef value = CFStringCreateMutable(kCFAllocatorDefault, 0);
- CSSToken *token = [CSSToken tokenWithType:CSSTokenTypeString];
-
- while (YES) {
- UniChar codePoint = [_inputStream consumeNextCodePoint];
-
- if (codePoint == endingCodePoint || codePoint == EOF_CHARACTER) {
- break;
- } else if (isNewLine(codePoint)) {
- [self parseError];
- [_inputStream reconsumeCurrentCodePoint];
- token.type = CSSTokenTypeBadString;
- break;
- } else if (codePoint == REVERSE_SOLIDUS) {
- if ([_inputStream nextCodePoint] == EOF_CHARACTER) {
- break;
- } else if (isNewLine([_inputStream nextCodePoint])) {
- [_inputStream consumeNextCodePoint];
- } else {
- UTF32Char escapedCodePoint = [self consumeEscapedCodePoint];
- AppendCodePoint(value, escapedCodePoint);
- }
- } else {
- CFStringAppendCharacters(value, &codePoint, 1);
- }
- }
-
- token.text = (__bridge_transfer NSString *)(value);
- return token;
-}
-
-- (CSSToken *)consumeURLToken
-{
- void (^ consumeWhitespace)() = ^ {
- while (isWhitespace([_inputStream nextCodePoint])) {
- [_inputStream consumeNextCodePoint];
- }
- };
-
- CSSToken *token = [CSSToken tokenWithType:CSSTokenTypeURL];
- token.text = @"";
-
- consumeWhitespace();
-
- if ([_inputStream nextCodePoint] == EOF_CHARACTER) {
- return token;
- }
-
- UniChar codePoint = [_inputStream consumeNextCodePoint];
- if (codePoint == QUOTATION_MARK || codePoint == APOSTROPHE) {
- CSSToken *stringToken = [self consumeStringTokenWithEndingCodePoint:codePoint];
- if (stringToken.type == CSSTokenTypeBadString) {
- [self consumeRemnantsOfBadURL];
- return [CSSToken tokenWithType:CSSTokenTypeBadURL];
- }
- token.text = stringToken.text;
- consumeWhitespace();
-
- if ([_inputStream nextCodePoint] == RIGHT_PARENTHESIS ||
- [_inputStream nextCodePoint] == EOF_CHARACTER) {
- [_inputStream consumeNextCodePoint];
- return token;
- } else {
- [self consumeRemnantsOfBadURL];
- return [CSSToken tokenWithType:CSSTokenTypeBadURL];
- }
- }
-
- CFMutableStringRef value = CFStringCreateMutable(kCFAllocatorDefault, 0);
-
- while (YES) {
- UniChar codePoint = [_inputStream consumeNextCodePoint];
-
- if (codePoint == RIGHT_PARENTHESIS || codePoint == EOF_CHARACTER) {
- return token;
- }
-
- if (isWhitespace(codePoint)) {
- consumeWhitespace();
- if ([_inputStream nextCodePoint] == RIGHT_PARENTHESIS ||
- [_inputStream nextCodePoint] == EOF_CHARACTER) {
- [_inputStream consumeNextCodePoint];
- return token;
- } else {
- [self consumeRemnantsOfBadURL];
- return [CSSToken tokenWithType:CSSTokenTypeBadURL];
- }
- }
-
- if (codePoint == QUOTATION_MARK ||
- codePoint == APOSTROPHE ||
- codePoint == LEFT_PARENTHESIS ||
- isNonPrintable(codePoint)) {
- [self parseError];
- [self consumeRemnantsOfBadURL];
- return [CSSToken tokenWithType:CSSTokenTypeBadURL];
- }
-
- if (codePoint == REVERSE_SOLIDUS) {
- if (isValidEscape([_inputStream currentCodePoint], [_inputStream nextCodePoint])) {
- UTF32Char escapedCodePoint = [self consumeEscapedCodePoint];
- AppendCodePoint(value, escapedCodePoint);
- } else {
- [self parseError];
- [self consumeRemnantsOfBadURL];
- return [CSSToken tokenWithType:CSSTokenTypeBadURL];
- }
- }
-
- CFStringAppendCharacters(value, &codePoint, 1);
- }
-
- return token;
-}
-
-- (CSSToken *)consumeUnicodeRange
-{
- unsigned int (^ parseHexInt) (NSString *) = ^ unsigned int (NSString *string) {
- NSScanner *scanner = [NSScanner scannerWithString:string];
- unsigned int num;
- [scanner scanHexInt:&num];
- return num;
- };
-
- void (^ consumeHexDigits)(CFMutableStringRef) = ^ (CFMutableStringRef ref) {
- while (isHexDigit([_inputStream nextCodePoint]) && CFStringGetLength(ref) < 6) {
- UniChar codePoint = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(ref, &codePoint, 1);
- }
- };
-
- CFMutableStringRef hexDigits = CFStringCreateMutable(kCFAllocatorDefault, 6);
- consumeHexDigits(hexDigits);
-
- unsigned int rangeStart = 0;
- unsigned int rangeEnd = 0;
-
- CFIndex length = CFStringGetLength(hexDigits);
- if (length < 6) {
- while ([_inputStream nextCodePoint] == QUESTION_MARK && CFStringGetLength(hexDigits) < 6) {
- UniChar codePoint = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(hexDigits, &codePoint, 1);
- }
-
- NSString *string = (__bridge NSString *)(hexDigits);
-
- if (string.length > length) {
- rangeStart = parseHexInt([string stringByReplacingOccurrencesOfString:@"?" withString:@"0"]);
- rangeEnd = parseHexInt([string stringByReplacingOccurrencesOfString:@"?" withString:@"F"]);
-
- CSSUnicodeRangeToken *token = [CSSUnicodeRangeToken new];
- token.start = rangeStart;
- token.end = rangeEnd;
- return token;
- } else {
- rangeStart = parseHexInt(string);
- }
- }
-
- if ([_inputStream nextCodePoint] == HYPHEN_MINUS && isDigit([_inputStream nextCodePointAtOffset:1])) {
- [_inputStream consumeNextCodePoint];
- consumeHexDigits(hexDigits);
- rangeEnd = parseHexInt((__bridge NSString *)(hexDigits));
- } else {
- rangeEnd = rangeStart;
- }
-
- CSSUnicodeRangeToken *token = [CSSUnicodeRangeToken new];
- token.start = rangeStart;
- token.end = rangeEnd;
- return token;
-}
-
-- (UTF32Char)consumeEscapedCodePoint
-{
- UniChar codePoint = [_inputStream consumeNextCodePoint];
-
- if (isHexDigit(codePoint)) {
- CFMutableStringRef hexString = CFStringCreateMutable(kCFAllocatorDefault, 6);
- CFStringAppendCharacters(hexString, &codePoint, 1);
-
- while (isHexDigit([_inputStream nextCodePoint]) && CFStringGetLength(hexString) <= 6) {
- UniChar codePoint = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(hexString, &codePoint, 1);
- }
-
- if (isWhitespace([_inputStream nextCodePoint])) {
- [_inputStream consumeNextCodePoint];
- }
-
- NSScanner *scanner = [NSScanner scannerWithString:(__bridge NSString *)(hexString)];
- UTF32Char number;
- [scanner scanHexInt:&number];
-
- return isValidEscapedCodePoint(number) ? number : REPLACEMENT_CHARACTER;
- } else if (codePoint == EOF_CHARACTER) {
- return REPLACEMENT_CHARACTER;
- }
-
- return codePoint;
-}
-
-- (NSString *)consumeName
-{
- CFMutableStringRef value = CFStringCreateMutable(kCFAllocatorDefault, 0);
- while (YES) {
- UniChar codePoint = [_inputStream consumeNextCodePoint];
- if (isName(codePoint)) {
- CFStringAppendCharacters(value, &codePoint, 1);
- } else if (isValidEscape([_inputStream nextCodePoint], [_inputStream nextCodePointAtOffset:1])) {
- UTF32Char escapedCodePoint = [self consumeEscapedCodePoint];
- AppendCodePoint(value, escapedCodePoint);
- } else {
- break;
- }
- }
-
- return (__bridge_transfer NSString *)(value);
-}
-
-- (CSSNumericTokenType)consumeNumber:(NSNumber **)number
-{
- CFMutableStringRef repr = CFStringCreateMutable(kCFAllocatorDefault, 0);
- CSSNumericTokenType type = CSSNumericTokenTypeInteger;
-
- void (^ consumeDigits)() = ^{
- while (isDigit([_inputStream nextCodePoint])) {
- UniChar next = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(repr, &next, 1);
- }
- };
-
- if ([_inputStream nextCodePoint] == PLUS_SIGN ||
- [_inputStream nextCodePoint] == HYPHEN_MINUS) {
- UniChar next = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(repr, &next, 1);
- }
-
- consumeDigits();
-
- if ([_inputStream nextCodePoint] == FULL_STOP &&
- isDigit([_inputStream nextCodePointAtOffset:1])) {
- UniChar next = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(repr, &next, 1);
- next = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(repr, &next, 1);
- type = CSSNumericTokenTypeNumber;
- consumeDigits();
- }
-
- UniChar first = [_inputStream nextCodePoint];
- UniChar second = [_inputStream nextCodePointAtOffset:1];
- UniChar third = [_inputStream nextCodePointAtOffset:2];
-
- if (first == LATIN_CAPITAL_LETTER_E || first == LATIN_SMALL_LETTER_E) {
- if (isDigit(second)) {
- UniChar next = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(repr, &next, 1);
- next = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(repr, &next, 1);
- consumeDigits();
- } else if ((second == PLUS_SIGN || second == HYPHEN_MINUS) && isDigit(third)) {
- UniChar next = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(repr, &next, 1);
- next = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(repr, &next, 1);
- next = [_inputStream consumeNextCodePoint];
- CFStringAppendCharacters(repr, &next, 1);
- consumeDigits();
- }
- }
-
- NSNumber *value = [self convertStringToNumber:(__bridge NSString *)(repr)];
- *number = value;
-
- return type;
-}
-
-- (NSNumber *)convertStringToNumber:(NSString *)string
-{
- NSInteger s = 1;
- if ([string hasPrefix:@"-"]) {
- s = -1;
- string = [string substringFromIndex:1];
- } else if ([string hasPrefix:@"+"]) {
- s = 1;
- string = [string substringFromIndex:1];
- }
-
- NSScanner *scanner = [NSScanner scannerWithString:string];
-
- NSInteger i = 0;
- NSString *digits = nil;
- if ([scanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&digits]) {
- i = [digits integerValue];
- }
-
- [scanner scanString:@"0x002E" intoString:nil];
-
- NSInteger f = 0;
- NSInteger d = 0;
- digits = nil;
- if ([scanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&digits]) {
- f = [digits integerValue];
- d = digits.length;
- }
-
- [scanner scanString:@"e" intoString:nil];
- [scanner scanString:@"E" intoString:nil];
-
- NSInteger t = 1;
- if ([scanner scanString:@"-" intoString:nil]) {
- t = -1;
- } else if ([scanner scanString:@"+" intoString:nil]) {
- t = 1;
- }
-
- NSInteger e = 0;
- digits = nil;
- if ([scanner scanCharactersFromSet:[NSCharacterSet decimalDigitCharacterSet] intoString:&digits]) {
- e = [digits integerValue];
- }
-
- return @(s * (i + f * pow(10, -d)) * pow(10, t * e));
-}
-
-- (void)consumeRemnantsOfBadURL
-{
- while (YES) {
- UniChar codePoint = [_inputStream consumeNextCodePoint];
- if (codePoint == RIGHT_PARENTHESIS || codePoint == EOF_CHARACTER) {
- return;
- }
-
- if (isValidEscape([_inputStream currentCodePoint], [_inputStream nextCodePoint])) {
- [self consumeEscapedCodePoint];
- }
- }
-}
-
-@end