#include "Lexer.h" #include "Number.h" #include "string.h" #include "Boolean.h" #include "Error.h" #include "defs.h" BOOL isdigit (string x) { return (x == "0" || x == "1" || x == "2" || x == "3" || x == "4" || x == "5" || x == "6" || x == "7" || x == "8" || x == "9"); } BOOL isspace (string x) { return (x == " " || x == "\t" || x == "\n" || x == "\r"); } BOOL isjunk (string x) { return isspace (x) || x == ";"; } BOOL issymbol (string x) { return (x != "" && x != "(" && x !=")" && !isjunk (x)); } @implementation Lexer + (id) newFromSource: (string) s file: (string) f { return [[Lexer alloc] initWithSource: s file: f]; } - (id) initWithSource: (string) s file: (string) f { self = [super init]; source = str_new(); str_copy(source, s); filename = f; linenum = 1; return self; } - (SchemeObject*) nextToken { local integer len; local Number *num; local Symbol *sym; local String *str; local Boolean *bl; for (len = 0; isjunk(str_mid(source, len, len+1)); len++) { if (str_mid(source, len, len+1) == ";") { while (str_mid(source, len, len+1) != "\n") { len++; } } if (str_mid(source, len, len+1) == "\n") { linenum++; } } str_copy (source, str_mid(source, len)); switch (str_mid (source, 0, 1)) { case "(": str_copy (source, str_mid (source, 1)); return [Symbol leftParen]; case ")": str_copy (source, str_mid (source, 1)); return [Symbol rightParen]; case "0": case "1": case "2": case "3": case "4": case "5": case "6": case "7": case "8": case "9": for (len = 1; isdigit(str_mid(source, len, len+1)); len++); num = [Number newFromInt: stoi (str_mid(source, 0, len))]; [num source: filename]; [num line: linenum]; str_copy (source, str_mid(source, len)); return num; case "\"": for (len = 1; str_mid(source, len, len+1) != "\""; len++); str = [String newFromString: str_mid(source, 1, len)]; [str source: filename]; [str line: linenum]; str_copy (source, str_mid(source, len+1)); return str; case "'": str_copy (source, str_mid (source, 1)); return [Symbol quote]; case ".": str_copy (source, str_mid (source, 1)); return [Symbol dot]; case "#": str_copy (source, str_mid (source, 1)); switch (str_mid (source, 0, 1)) { case "t": bl = [Boolean trueConstant]; str_copy (source, str_mid (source, 1)); return bl; case "f": bl = [Boolean falseConstant]; str_copy (source, str_mid (source, 1)); return bl; default: return [Error type: "parse" message: "Invalid # constant" by: self]; } case "": return nil; default: for (len = 1; issymbol(str_mid(source, len, len+1)); len++); sym = [Symbol forString: str_mid (source, 0, len)]; str_copy (source, str_mid(source, len)); return sym; } } - (integer) lineNumber { return linenum; } - (integer) line { return linenum; } - (string) source { return filename; } @end