// // Interpreter.m // Brainfuck // // Created by Kim Wittenburg on 20.05.13. // Copyright (c) 2013 brainfuck. All rights reserved. // #import "Interpreter.h" #import "Lexer.h" @implementation Interpreter { NSMutableArray *a; NSInteger level; NSString *input; NSInteger inPos; } @synthesize printer; + (Interpreter *)interpreter { return [[self alloc] init]; } - (id)init { self = [super init]; if (self) { } return self; } - (void)execute:(NSString *)script withInput:(NSString *)i error:(NSError *__autoreleasing *)error { input = i; inPos = 0; Lexer *lexer = [Lexer lexer]; NSArray *cmds = [lexer performLexingOnString:script error:error]; level = 0; a = [NSMutableArray new]; [a addObject:[NSNumber numberWithInt:0]]; [self executeCommands:cmds]; } - (void)executeCommands:(NSArray *)cmds { for (id cmd in cmds) { if ([cmd isKindOfClass:[NSArray class]]) { [self loop:cmd]; } else { [self executeCommand:cmd]; } } } - (void)executeCommand:(NSString *)cmd { int c = [cmd characterAtIndex:0]; if (c == '+') { [self increment]; } else if (c == '-') { [self decrement]; } else if (c == '<') { [self previousCell]; } else if (c == '>') { [self nextCell]; } else if (c == '.') { [self printCellValue]; } else if (c == ',') { [self readNextInput]; } } - (void)increment { NSNumber *number = a[level]; number = [NSNumber numberWithInt:number.intValue+1]; a[level] = number; } - (void)decrement { NSNumber *number = a[level]; number = [NSNumber numberWithInt:number.intValue-1]; a[level] = number; } - (void)nextCell { if (++level == a.count) { [a addObject:[NSNumber numberWithInt:0]]; } } - (void)previousCell { if (--level == -1) { [a insertObject:[NSNumber numberWithInt:0] atIndex:0]; level++; } } - (void)printCellValue { NSNumber *ascii = a[level]; NSString *text = [NSString stringWithFormat:@"%c", ascii.intValue]; [self.printer print:text]; } - (void)readNextInput { int ascii; if (inPos == input.length) { ascii = 0; } else { ascii = [input characterAtIndex:inPos++]; } a[level] = [NSNumber numberWithInt:ascii]; } - (void)loop:(NSArray *)cmds { while (((NSNumber *)a[level]).intValue != 0) { [self executeCommands:cmds]; } } @end