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. --- MLKReader.m | 156 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 155 insertions(+), 1 deletion(-) (limited to 'MLKReader.m') 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 { -- cgit v1.2.3