From c2efa347a8e5f1d83427c34defa953e594a2bb12 Mon Sep 17 00:00:00 2001 From: Matthias Andreas Benkard Date: Sun, 15 Jun 2008 16:31:15 +0200 Subject: MLKReader: Read numbers. --- MLKFloat.h | 36 +++++++++++++ MLKInteger.h | 35 +++++++++++++ MLKRatio.h | 34 +++++++++++++ MLKReader.m | 156 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++- MLKReadtable.h | 1 + 5 files changed, 261 insertions(+), 1 deletion(-) create mode 100644 MLKFloat.h create mode 100644 MLKInteger.h create mode 100644 MLKRatio.h diff --git a/MLKFloat.h b/MLKFloat.h new file mode 100644 index 0000000..fdb1212 --- /dev/null +++ b/MLKFloat.h @@ -0,0 +1,36 @@ +/* -*- mode: objc; coding: utf-8 -*- */ +/* Étoilisp/Mulklisp, a Common Lisp subset for the Étoilé runtime. + * Copyright (C) 2008 Matthias Andreas Benkard. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "MLKLispValue.h" + +@class NSString; + + +@interface MLKFloat : MLKLispValue +{ +} + ++(MLKFloat *) floatWithExponentMarker:(unichar)exponentMarker + integerPart:(NSString *)intPart + negative:(BOOL)negative + fractionalPart:(NSString *)fractPart + exponent:(NSString *)exponent + exponentNegative:(BOOL)exponentNegative; + +-(void) dealloc; +@end diff --git a/MLKInteger.h b/MLKInteger.h new file mode 100644 index 0000000..38d319e --- /dev/null +++ b/MLKInteger.h @@ -0,0 +1,35 @@ +/* -*- mode: objc; coding: utf-8 -*- */ +/* Étoilisp/Mulklisp, a Common Lisp subset for the Étoilé runtime. + * Copyright (C) 2008 Matthias Andreas Benkard. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "MLKLispValue.h" + +@class NSString; + + +@interface MLKInteger : MLKLispValue +{ +} + ++(MLKInteger *) integerWithString:(NSString *)string + negative:(BOOL)negative + base:(unsigned int)base; + +-(int) intValue; + +-(void) dealloc; +@end diff --git a/MLKRatio.h b/MLKRatio.h new file mode 100644 index 0000000..c67d7dd --- /dev/null +++ b/MLKRatio.h @@ -0,0 +1,34 @@ +/* -*- mode: objc; coding: utf-8 -*- */ +/* Étoilisp/Mulklisp, a Common Lisp subset for the Étoilé runtime. + * Copyright (C) 2008 Matthias Andreas Benkard. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#import "MLKLispValue.h" + +@class NSString, MLKInteger; + + +@interface MLKRatio : MLKLispValue +{ + MLKInteger *numerator; + MLKInteger *denominator; +} + ++(MLKRatio *) ratioWithNumeratorString:(NSString *)numerString + denominatorString:(NSString *)denomString; + +-(void) dealloc; +@end diff --git a/MLKReader.m b/MLKReader.m index 9a9b956..5663efb 100644 --- a/MLKReader.m +++ b/MLKReader.m @@ -26,8 +26,12 @@ #import "MLKPackage.h" #import "MLKClosure.h" #import "MLKStream.h" +#import "MLKFloat.h" +#import "MLKInteger.h" +#import "MLKRatio.h" #import +#import #import #import @@ -206,7 +210,157 @@ { if ([self isPotentialNumber:token readtable:readtable]) { - // ??? + unsigned long i, firstNum, secondNum, exponent, exponentMarkerPos; + unichar sign, exponentSign; + unichar firstSeparator, exponentMarker; + BOOL negative; + MLKInteger *base; + + base = [[MLKDynamicContext currentContext] + valueForBinding:[[MLKPackage findPackage:@"COMMON-LISP"] + intern:@"*READ-BASE*"]]; + + // Read the sign (if present). + if ([readtable isSign:[token characterAtIndex:0]]) + { + sign = [token characterAtIndex:0]; + i = 1; + firstNum = 1; + } + else + { + i = 0; + firstNum = 0; + } + + negative = (firstNum > 0 && sign == '-'); + + while ((i < [token length]) + && [readtable isDecimalDigit:[token characterAtIndex:i]]) + i++; + + if (i == [token length]) + { + return [MLKInteger integerWithString: + [token substringWithRange: + NSMakeRange (firstNum, [token length] - firstNum)] + negative:negative + base:10]; + } + + firstSeparator = [token characterAtIndex:i]; + + if (!([readtable isDecimalPoint:firstSeparator] + || [readtable isExponentMarker:[token characterAtIndex:i]])) + goto digits; + + i++; + secondNum = i; + + if (i == [token length] && [readtable isDecimalPoint:firstSeparator]) + { + return [MLKInteger integerWithString: + [token substringWithRange: + NSMakeRange (firstNum, [token length] - firstNum - 1)] + negative:negative + base:10]; + } + else + { + // We're dealing with a floating point number. Bah. I hate + // floating point numbers. + if ([readtable isExponentMarker:firstSeparator]) + { + exponentMarkerPos = i; + if ([readtable isSign:[token characterAtIndex:i]]) + { + exponentSign = [token characterAtIndex:i]; + i++; + } + else + exponentSign = '+'; + + exponent = i; + + while ((i < [token length]) + && [readtable isDecimalDigit:[token characterAtIndex:i]]) + i++; + + return [MLKFloat floatWithExponentMarker:firstSeparator + integerPart:[token substringWithRange:NSMakeRange(firstNum, exponentMarkerPos - firstNum - 1)] + negative:negative + fractionalPart:@"" + exponent:[token substringFromIndex:exponent] + exponentNegative:(exponentSign == '-')]; + } + else + { + while ((i < [token length]) + && [readtable isDecimalDigit:[token characterAtIndex:i]]) + i++; + + if (i == [token length]) + { + return [MLKFloat floatWithExponentMarker:firstSeparator + integerPart:[token substringWithRange:NSMakeRange (firstNum, secondNum - firstNum - 1)] + negative:negative + fractionalPart:[token substringFromIndex:secondNum] + exponent:@"" + exponentNegative:NO]; + } + + // Assume token[i] is an exponent marker. + exponentMarkerPos = i; + exponentMarker = [token characterAtIndex:i]; + i++; + + if ([readtable isSign:[token characterAtIndex:i]]) + { + exponentSign = [token characterAtIndex:i]; + i++; + } + else + exponentSign = '+'; + + exponent = i; + + while ((i < [token length]) + && [readtable isDecimalDigit:[token characterAtIndex:i]]) + i++; + + return [MLKFloat floatWithExponentMarker:exponentMarker + integerPart:[token substringWithRange:NSMakeRange (firstNum, secondNum - firstNum - 1)] + negative:negative + fractionalPart:[token substringWithRange:NSMakeRange (secondNum, exponentMarkerPos - secondNum)] + exponent:[token substringFromIndex:exponent] + exponentNegative:(exponentSign == '-')]; + } + } + + digits: + i = firstNum; + while ((i < [token length]) + && [readtable isDigit:[token characterAtIndex:0]]) + i++; + + if (i == [token length]) + { + return [MLKInteger integerWithString: + [token substringWithRange: + NSMakeRange (firstNum, [token length] - firstNum)] + negative:negative + base:[base intValue]]; + } + + // Assume token[i] is a slash. + i++; + secondNum = i; + + return [MLKRatio ratioWithNumeratorString: + [token substringWithRange: + NSMakeRange (firstNum, + secondNum - firstNum - 1)] + denominatorString:[token substringFromIndex:secondNum]]; } else { diff --git a/MLKReadtable.h b/MLKReadtable.h index faf98c6..c8421cb 100644 --- a/MLKReadtable.h +++ b/MLKReadtable.h @@ -69,6 +69,7 @@ enum MLKReadtableCase -(BOOL) isDot:(unichar)ch; // Read-base-dependent digit properties. +-(BOOL) isDecimalDigit:(unichar)ch; -(BOOL) isDigit:(unichar)ch; -(int) digitWeight:(unichar)ch; -- cgit v1.2.3