121 lines
2.8 KiB
Objective-C
121 lines
2.8 KiB
Objective-C
//
|
|
// MPTokenStream.m
|
|
// MathPad
|
|
//
|
|
// Created by Kim Wittenburg on 20.09.14.
|
|
// Copyright (c) 2014 Kim Wittenburg. All rights reserved.
|
|
//
|
|
|
|
#import "MPTokenStream.h"
|
|
|
|
#import "MPToken.h"
|
|
|
|
@implementation MPTokenStream {
|
|
NSUInteger _currentTokenIndex;
|
|
NSUInteger eofLocation;
|
|
|
|
BOOL *whitespaceIgnores;
|
|
NSUInteger maxWhitespaceIgnores;
|
|
NSUInteger currentWhitespaceState;
|
|
}
|
|
|
|
- (instancetype)initWithTokens:(NSArray *)tokens
|
|
{
|
|
self = [super init];
|
|
if (self) {
|
|
self.tokens = tokens;
|
|
whitespaceIgnores = malloc(10 * sizeof(BOOL));
|
|
maxWhitespaceIgnores = 10;
|
|
currentWhitespaceState = 0;
|
|
[self beginAcceptingWhitespaceTokens];
|
|
_currentTokenIndex = 0;
|
|
if (tokens.count > 0) {
|
|
eofLocation = NSMaxRange([tokens.lastObject range]);
|
|
} else {
|
|
eofLocation = 0;
|
|
}
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (void)beginAcceptingWhitespaceTokens
|
|
{
|
|
[self pushWhitespaceState:YES];
|
|
}
|
|
|
|
- (void)beginIgnoringWhitespaceTokens
|
|
{
|
|
[self pushWhitespaceState:NO];
|
|
}
|
|
|
|
- (void)pushWhitespaceState:(BOOL)state
|
|
{
|
|
currentWhitespaceState++;
|
|
if (currentWhitespaceState >= maxWhitespaceIgnores) {
|
|
maxWhitespaceIgnores += 10;
|
|
BOOL *reallocatedWhitespaceIgnores = realloc(whitespaceIgnores, maxWhitespaceIgnores);
|
|
if (reallocatedWhitespaceIgnores) {
|
|
whitespaceIgnores = reallocatedWhitespaceIgnores;
|
|
} else {
|
|
@throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"Realloc Failed" userInfo:nil];
|
|
}
|
|
}
|
|
whitespaceIgnores[currentWhitespaceState] = state;
|
|
}
|
|
|
|
- (void)endIgnoringOrAcceptingWhitespaceTokens
|
|
{
|
|
currentWhitespaceState--;
|
|
}
|
|
|
|
- (void)skipWhitespaces
|
|
{
|
|
if (whitespaceIgnores[currentWhitespaceState]) {
|
|
return;
|
|
}
|
|
while (_currentTokenIndex < self.tokens.count) {
|
|
MPToken *token = self.tokens[_currentTokenIndex];
|
|
if (token.tokenType != MPWhitespaceToken) {
|
|
return;
|
|
}
|
|
[self currentTokenConsumed];
|
|
}
|
|
}
|
|
|
|
- (BOOL)hasMoreTokens
|
|
{
|
|
[self skipWhitespaces];
|
|
return _currentTokenIndex < self.tokens.count;
|
|
}
|
|
|
|
- (id<MPToken>)currentToken
|
|
{
|
|
[self skipWhitespaces];
|
|
if (_currentTokenIndex >= _tokens.count) {
|
|
return [[MPToken alloc] initEOFTokenAtLocation:eofLocation];
|
|
}
|
|
return _tokens[_currentTokenIndex];
|
|
}
|
|
|
|
- (id<MPToken>)peekNextToken
|
|
{
|
|
NSUInteger currentTokenIndex = _currentTokenIndex;
|
|
[self currentTokenConsumed]; // Pretend the current token has been consumed
|
|
id<MPToken> token = [self currentToken];
|
|
_currentTokenIndex = currentTokenIndex; // Undo the lookahead
|
|
return token;
|
|
}
|
|
|
|
- (void)currentTokenConsumed
|
|
{
|
|
[self currentToken];
|
|
++_currentTokenIndex;
|
|
}
|
|
|
|
- (void)dealloc
|
|
{
|
|
free(whitespaceIgnores);
|
|
}
|
|
|
|
@end
|