<div dir="ltr"><div dir="ltr"><div>Reminder: until now, the exponent has always been read in base 10, whatever the radix of the significand.</div><div><br></div><div>For example:</div><div> 1 << 53 = 2r1e53</div><div><br></div><div>This commit is changing the interpretation of such numbers...<br></div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">Le mer. 1 déc. 2021 à 16:34, <<a href="mailto:commits@source.squeak.org">commits@source.squeak.org</a>> a écrit :<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Marcel Taeumel uploaded a new version of Kernel to project The Trunk:<br>
<a href="http://source.squeak.org/trunk/Kernel-ct.1419.mcz" rel="noreferrer" target="_blank">http://source.squeak.org/trunk/Kernel-ct.1419.mcz</a><br>
<br>
==================== Summary ====================<br>
<br>
Name: Kernel-ct.1419<br>
Author: ct<br>
Time: 27 October 2021, 10:21:05.275233 pm<br>
UUID: ecfac90e-ea85-774f-b13d-0ecad50c894a<br>
Ancestors: Kernel-eem.1418<br>
<br>
Makes it possible to specify a different default base in number parsers. There is no need to hard-code the 10 and I am actually building something with a different default number system. Clients can still change the base via the radix notation.<br>
<br>
(ExtendedNumberParser on: '10')<br>
defaultBase: 16;<br>
nextNumber. "16"<br>
(ExtendedNumberParser on: '2r10')<br>
defaultBase: 16;<br>
nextNumber. "2"<br>
(ExtendedNumberParser on: 'ar10')<br>
defaultBase: 16;<br>
nextNumber. "10".<br>
<br>
Also adds Integer class >> #readFrom:base:ifFail: for convenience. Removes redundant class-side overrides on SqNumberParser.<br>
<br>
=============== Diff against Kernel-eem.1418 ===============<br>
<br>
Item was changed:<br>
----- Method: ExtendedNumberParser>>nextFraction (in category 'parsing-public') -----<br>
nextFraction<br>
| numerator denominator numberOfTrailingZeroInIntegerPart |<br>
+ base := self defaultBase.<br>
- base := 10.<br>
neg := self peekSignIsMinus.<br>
(integerPart := self nextUnsignedIntegerOrNilBase: base)<br>
ifNil: [numberOfTrailingZeroInIntegerPart := 0]<br>
ifNotNil: [<br>
numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero.<br>
(sourceStream peekFor: $r)<br>
ifTrue: ["<base>r<integer>"<br>
(base := integerPart) < 2<br>
ifTrue: [<br>
sourceStream skip: -1.<br>
^ self expected: 'an integer greater than 1 as valid radix'].<br>
self peekSignIsMinus<br>
ifTrue: [neg := neg not].<br>
integerPart := self nextUnsignedIntegerBase: base.<br>
numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero]].<br>
(sourceStream peekFor: $.)<br>
ifTrue:<br>
[^self readFractionPartNumberOfTrailingZeroInIntegerPart: numberOfTrailingZeroInIntegerPart].<br>
integerPart<br>
ifNil:<br>
["No integerPart, raise an error"<br>
^ self expected: 'a digit'].<br>
numerator := neg<br>
ifTrue: [integerPart negated]<br>
ifFalse: [integerPart].<br>
self readExponent ifTrue: [numerator := numerator * (base raisedToInteger: exponent)].<br>
(sourceStream peekFor: $/) ifFalse: [^numerator].<br>
base := 10.<br>
+ base := self defaultBase.<br>
(denominator := self nextUnsignedIntegerOrNilBase: base)<br>
ifNil:<br>
[sourceStream skip: -1. "Not a valid denominator, ungobble / and return numerator"<br>
^numerator].<br>
(sourceStream peekFor: $r)<br>
ifTrue: ["<base>r<integer>"<br>
(base := denominator) < 2<br>
ifTrue: [<br>
sourceStream skip: -1.<br>
^ self expected: 'an integer greater than 1 as valid radix'].<br>
denominator := self nextUnsignedIntegerBase: base].<br>
self readExponent ifTrue: [denominator := denominator * (base raisedToInteger: exponent)].<br>
^numerator / denominator!<br>
<br>
Item was changed:<br>
----- Method: ExtendedNumberParser>>nextNumber (in category 'parsing-public') -----<br>
nextNumber<br>
"main method for reading a number.<br>
This one can read Float Integer and ScaledDecimal"<br>
<br>
| numberOfTrailingZeroInIntegerPart |<br>
+ base := self defaultBase.<br>
- base := 10.<br>
neg := self peekSignIsMinus.<br>
integerPart := self nextUnsignedIntegerOrNilBase: base.<br>
integerPart ifNil: [(sourceStream peekFor: $.)<br>
ifTrue: [<br>
"Try .1 syntax"<br>
^self readNumberWithoutIntegerPart]<br>
ifFalse: [<br>
"This is not a regular number beginning with a digit<br>
It is time to check for exceptional condition NaN and Infinity"<br>
^self readNamedFloatOrFail]].<br>
numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero.<br>
(sourceStream peekFor: $r)<br>
ifTrue: ["<base>r<integer>"<br>
| oldNeg pos |<br>
pos := sourceStream position - 1.<br>
(base := integerPart) < 2<br>
ifTrue: ["A radix currently need to be greater than 1, ungobble the r and return the integer part"<br>
sourceStream skip: -1.<br>
^neg<br>
ifTrue: [base negated]<br>
ifFalse: [base]].<br>
oldNeg := neg.<br>
self peekSignIsMinus ifTrue: [neg := neg not].<br>
integerPart := self nextUnsignedIntegerOrNilBase: base.<br>
integerPart ifNil: [<br>
(sourceStream peekFor: $.) ifTrue: [self readNumberWithoutIntegerPartOrNil ifNotNil: [:aNumber | ^aNumber]].<br>
sourceStream position: pos.<br>
^oldNeg<br>
ifTrue: [base negated]<br>
ifFalse: [base]].<br>
numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero].<br>
^ (sourceStream peekFor: $.)<br>
ifTrue: [self readNumberWithFractionPartNumberOfTrailingZeroInIntegerPart: numberOfTrailingZeroInIntegerPart]<br>
ifFalse: [self makeIntegerOrScaledInteger]!<br>
<br>
Item was changed:<br>
----- Method: FORTRANNumberParser>>nextNumber (in category 'parsing-public') -----<br>
nextNumber<br>
"main method for reading a number with FORTRAN syntax.<br>
This one can read Real and Integer (not complex)"<br>
<br>
| numberOfTrailingZeroInIntegerPart numberOfNonZeroFractionDigits mantissa value numberOfTrailingZeroInFractionPart noInt |<br>
+ base := self defaultBase..<br>
- base := 10.<br>
(self nextMatchAll: 'NaN') ifTrue: [^Float nan].<br>
neg := self peekSignIsMinus.<br>
(self nextMatchAll: 'Infinity') <br>
ifTrue: [^neg ifTrue: [Float negativeInfinity] ifFalse: [Float infinity]].<br>
(noInt := sourceStream peekFor: $.) <br>
ifTrue: <br>
[integerPart := 0.<br>
numberOfTrailingZeroInIntegerPart := 0]<br>
ifFalse: <br>
[integerPart := self nextUnsignedIntegerBase: base.<br>
numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero].<br>
(noInt or: [sourceStream peekFor: $.]) <br>
ifTrue: <br>
[fractionPart := self nextUnsignedIntegerBase: base ifFail: [nil].<br>
fractionPart isNil <br>
ifTrue: <br>
[noInt <br>
ifTrue: <br>
["no interger part, no fraction part..."<br>
self expected: 'a digit 0 to 9'.<br>
^nil].<br>
fractionPart := 0]<br>
ifFalse: <br>
[numberOfNonZeroFractionDigits := lastNonZero.<br>
numberOfTrailingZeroInFractionPart := nDigits - lastNonZero].<br>
self readExponent]<br>
ifFalse: <br>
[self readExponent ifFalse: [^neg ifTrue: [integerPart negated] ifFalse: [integerPart]].<br>
fractionPart := 0].<br>
fractionPart isZero <br>
ifTrue: <br>
[mantissa := integerPart // (base raisedTo: numberOfTrailingZeroInIntegerPart).<br>
exponent := exponent + numberOfTrailingZeroInIntegerPart]<br>
ifFalse: <br>
[mantissa := integerPart * (base raisedTo: numberOfNonZeroFractionDigits) <br>
+ (fractionPart // (base raisedTo: numberOfTrailingZeroInFractionPart)).<br>
exponent := exponent - numberOfNonZeroFractionDigits].<br>
value := self <br>
makeFloatFromMantissa: mantissa<br>
exponent: exponent<br>
base: base.<br>
^neg ifTrue: [value isZero ifTrue: [Float negativeZero] ifFalse: [value negated]] ifFalse: [value]!<br>
<br>
Item was added:<br>
+ ----- Method: Integer class>>readFrom:base:ifFail: (in category 'instance creation') -----<br>
+ readFrom: aStringOrStream base: base ifFail: aBlock<br>
+ "Answer an instance of one of the concrete subclasses if Integer. <br>
+ Initial plus or minus sign accepted, and bases > 10 use letters A-Z.<br>
+ Imbedded radix specifiers not allowed; use Number class readFrom: for that.<br>
+ Execute aBlock if there are no digits."<br>
+ <br>
+ ^(ExtendedNumberParser on: aStringOrStream) nextIntegerBase: base ifFail: aBlock!<br>
<br>
Item was changed:<br>
Object subclass: #NumberParser<br>
+ instanceVariableNames: 'sourceStream base neg integerPart fractionPart exponent scale nDigits lastNonZero requestor failBlock defaultBase'<br>
- instanceVariableNames: 'sourceStream base neg integerPart fractionPart exponent scale nDigits lastNonZero requestor failBlock'<br>
classVariableNames: ''<br>
poolDictionaries: ''<br>
category: 'Kernel-Numbers'!<br>
<br>
+ !NumberParser commentStamp: 'ct 10/27/2021 22:04' prior: 0!<br>
- !NumberParser commentStamp: 'nice 3/15/2010 00:16' prior: 0!<br>
NumberParser is an abstract class for parsing and building numbers from string/stream.<br>
It offers a framework with utility methods and exception handling.<br>
<br>
Number syntax is not defined and should be subclassResponsibility.<br>
<br>
Instance variables:<br>
sourceStream <Stream> the stream of characters from which the number is read<br>
base <Integer> the radix in which to interpret digits<br>
neg <Boolean> true in case of minus sign<br>
integerPart <Integer> the integer part of the number<br>
fractionPart <Integer> the fraction part of the number if any<br>
exponent <Integer> the exponent used in scientific notation if any<br>
scale <Integer> the scale used in case of ScaledDecimal number if any<br>
nDigits <Integer> number of digits read to form an Integer<br>
lasNonZero <Integer> position of last non zero digit, starting at 1 from left, 0 if all digits are zero<br>
requestor <TextEditor | nil> can be used to insert an error message in the requestor<br>
failBlock <BlockClosure> Block to execute whenever an error occurs.<br>
The fail block can have 0, 1 or 2 arguments (errorString and source position)<br>
+ defaultBase <Integer> the default radix in which to interpret digits, unless specified differently via radix notation!<br>
- !<br>
<br>
Item was added:<br>
+ ----- Method: NumberParser>>defaultBase (in category 'accessing') -----<br>
+ defaultBase<br>
+ <br>
+ ^ defaultBase!<br>
<br>
Item was added:<br>
+ ----- Method: NumberParser>>defaultBase: (in category 'accessing') -----<br>
+ defaultBase: anInteger<br>
+ <br>
+ self assert: anInteger < 28 description: 'Default base must be lower than 28 to keep radix r distinguishable from digits. For higher bases, pass the base manually to #nextNumberBase: autc.'.<br>
+ defaultBase := anInteger!<br>
<br>
Item was added:<br>
+ ----- Method: NumberParser>>defaultRadixBase (in category 'accessing') -----<br>
+ defaultRadixBase<br>
+ <br>
+ ^ 10!<br>
<br>
Item was added:<br>
+ ----- Method: NumberParser>>initialize (in category 'initialize-release') -----<br>
+ initialize<br>
+ <br>
+ defaultBase := 10!<br>
<br>
Item was changed:<br>
----- Method: NumberParser>>nextInteger (in category 'parsing-public') -----<br>
nextInteger<br>
"Read an Integer from sourceStream, asnwser that Integer.<br>
This is a generic version dealing with an optional sign and a simple sequence of decimal digits.<br>
Subclass might define extended syntax."<br>
<br>
+ base := self defaultBase.<br>
- base := 10.<br>
^self nextIntegerBase: base ifFail: [^self expected: ('a digit between 0 and ' copyWith: (Character digitValue: base - 1))]!<br>
<br>
Item was changed:<br>
----- Method: NumberParser>>nextUnsignedInteger (in category 'parsing-public') -----<br>
nextUnsignedInteger<br>
"Read an Integer from sourceStream, asnwser that Integer.<br>
This is a generic version dealing with a simple sequence of decimal digits.<br>
Subclass might define extended syntax."<br>
+ <br>
+ base := self defaultBase.<br>
- <br>
- base := 10.<br>
^self nextUnsignedIntegerBase: base ifFail: [^self expected: ('a digit between 0 and ' copyWith: (Character digitValue: base - 1))]!<br>
<br>
Item was changed:<br>
----- Method: NumberParser>>on: (in category 'initialize-release') -----<br>
on: aStringOrStream <br>
sourceStream := aStringOrStream isString <br>
ifTrue: [ aStringOrStream readStream ]<br>
ifFalse: [ aStringOrStream ].<br>
+ base := self defaultBase.<br>
- base := 10.<br>
neg := false.<br>
integerPart := fractionPart := exponent := scale := 0.<br>
requestor := failBlock := nil!<br>
<br>
Item was changed:<br>
----- Method: NumberParser>>readExponent (in category 'parsing-private') -----<br>
readExponent<br>
"read the exponent if any (stored in instVar).<br>
Answer true if found, answer false if none.<br>
If exponent letter is not followed by a digit,<br>
this is not considered as an error.<br>
Exponent are always read in base 10."<br>
<br>
| eneg epos |<br>
exponent := 0.<br>
(self isExponentLetter: sourceStream peek) ifFalse: [^ false].<br>
sourceStream next.<br>
eneg := sourceStream peekFor: $-.<br>
epos := eneg not and: [self allowPlusSignInExponent and: [sourceStream peekFor: $+]].<br>
+ exponent := self nextUnsignedIntegerOrNilBase: self defaultBase.<br>
- exponent := self nextUnsignedIntegerOrNilBase: 10.<br></blockquote><div>Above is the questionable change for reading the exponent...</div><div> <br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">
exponent ifNil: ["Oops, there was no digit after the exponent letter.Ungobble the letter"<br>
exponent := 0.<br>
sourceStream<br>
skip: ((eneg or: [epos])<br>
ifTrue: [-2]<br>
ifFalse: [-1]).<br>
^ false].<br>
eneg ifTrue: [exponent := exponent negated].<br>
^true!<br>
<br>
Item was removed:<br>
- ----- Method: SqNumberParser class>>on: (in category 'instance creation') -----<br>
- on: aStringOrStream<br>
- ^self new on: aStringOrStream!<br>
<br>
Item was removed:<br>
- ----- Method: SqNumberParser class>>parse: (in category 'instance creation') -----<br>
- parse: aStringOrStream <br>
- ^(self new)<br>
- on: aStringOrStream;<br>
- nextNumber!<br>
<br>
Item was removed:<br>
- ----- Method: SqNumberParser class>>parse:onError: (in category 'instance creation') -----<br>
- parse: aStringOrStream onError: failBlock <br>
- ^(self new)<br>
- on: aStringOrStream;<br>
- failBlock: failBlock;<br>
- nextNumber!<br>
<br>
Item was changed:<br>
----- Method: SqNumberParser>>nextFraction (in category 'parsing-public') -----<br>
nextFraction<br>
| numerator denominator numberOfTrailingZeroInIntegerPart |<br>
+ base := self defaultBase.<br>
- base := 10.<br>
neg := self peekSignIsMinus.<br>
(integerPart := self nextUnsignedIntegerOrNilBase: base)<br>
ifNil: ["No integerPart, raise an error"<br>
^ self expected: 'a digit'].<br>
numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero.<br>
(sourceStream peekFor: $r)<br>
ifTrue: ["<base>r<integer>"<br>
(base := integerPart) < 2<br>
ifTrue: [<br>
sourceStream skip: -1.<br>
^ self expected: 'an integer greater than 1 as valid radix'].<br>
self peekSignIsMinus<br>
ifTrue: [neg := neg not].<br>
integerPart := self nextUnsignedIntegerBase: base.<br>
numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero].<br>
(sourceStream peekFor: $.)<br>
ifTrue:<br>
[^self readFractionPartNumberOfTrailingZeroInIntegerPart: numberOfTrailingZeroInIntegerPart].<br>
numerator := neg<br>
ifTrue: [integerPart negated]<br>
ifFalse: [integerPart].<br>
self readExponent ifTrue: [numerator := numerator * (base raisedToInteger: exponent)].<br>
(sourceStream peekFor: $/) ifFalse: [^numerator].<br>
+ base := self defaultBase.<br>
- base := 10.<br>
(denominator := self nextUnsignedIntegerOrNilBase: base)<br>
ifNil:<br>
[sourceStream skip: -1. "Not a valid denominator, ungobble / and return numerator"<br>
^numerator].<br>
(sourceStream peekFor: $r)<br>
ifTrue: ["<base>r<integer>"<br>
(base := denominator) < 2<br>
ifTrue: [<br>
sourceStream skip: -1.<br>
^ self expected: 'an integer greater than 1 as valid radix'].<br>
denominator := self nextUnsignedIntegerBase: base].<br>
self readExponent ifTrue: [denominator := denominator * (base raisedToInteger: exponent)].<br>
^numerator / denominator!<br>
<br>
Item was changed:<br>
----- Method: SqNumberParser>>nextInteger (in category 'parsing-public') -----<br>
nextInteger<br>
"Read an Integer from sourceStream, asnwser that Integer.<br>
In Smalltalk syntax, a radix can be specified, and an exponent too."<br>
<br>
| numberOfTrailingZeroInIntegerPart |<br>
+ base := self defaultBase.<br>
- base := 10.<br>
neg := self peekSignIsMinus.<br>
integerPart := self nextUnsignedIntegerOrNilBase: base.<br>
numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero.<br>
(sourceStream peekFor: $r)<br>
ifTrue: ["<base>r<integer>"<br>
(base := integerPart) < 2<br>
ifTrue: [<br>
sourceStream skip: -1.<br>
^ self expected: 'an integer greater than 1 as valid radix'].<br>
self peekSignIsMinus<br>
ifTrue: [neg := neg not].<br>
integerPart := self nextUnsignedIntegerBase: base.<br>
numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero].<br>
^ self makeIntegerOrScaledInteger!<br>
<br>
Item was changed:<br>
----- Method: SqNumberParser>>nextNumber (in category 'parsing-public') -----<br>
nextNumber<br>
"main method for reading a number.<br>
This one can read Float Integer and ScaledDecimal"<br>
<br>
| numberOfTrailingZeroInIntegerPart |<br>
+ base := self defaultBase.<br>
- base := 10.<br>
neg := self peekSignIsMinus.<br>
integerPart := self nextUnsignedIntegerOrNilBase: base.<br>
integerPart ifNil: [<br>
"This is not a regular number beginning with a digit<br>
It is time to check for exceptional condition NaN and Infinity"<br>
^self readNamedFloatOrFail].<br>
numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero.<br>
(sourceStream peekFor: $r)<br>
ifTrue: ["<base>r<integer>"<br>
(base := integerPart) < 2<br>
ifTrue: [<br>
sourceStream skip: -1.<br>
^ self expected: 'an integer greater than 1 as valid radix'].<br>
self peekSignIsMinus<br>
ifTrue: [neg := neg not].<br>
integerPart := self nextUnsignedIntegerBase: base.<br>
numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero].<br>
^ (sourceStream peekFor: $.)<br>
ifTrue: [self readNumberWithFractionPartNumberOfTrailingZeroInIntegerPart: numberOfTrailingZeroInIntegerPart]<br>
ifFalse: [self makeIntegerOrScaledInteger]!<br>
<br>
Item was changed:<br>
----- Method: SqNumberParser>>nextScaledDecimal (in category 'parsing-public') -----<br>
nextScaledDecimal<br>
"Main method for reading a (scaled) decimal number.<br>
Good Gracious, do not accept a decimal in another base than 10!!<br>
In other words, do not accept radix notation like 2r1.1, even not 10r5.3<br>
Do not accept exponent notation neither, like 1.0e-3"<br>
<br>
| numberOfNonZeroFractionDigits numberOfTrailingZeroInFractionPart |<br>
+ base := self defaultBase.<br>
- base := 10.<br>
neg := sourceStream peekFor: $-.<br>
integerPart := self nextUnsignedIntegerBase: base.<br>
(sourceStream peekFor: $.)<br>
ifTrue: [fractionPart := self nextUnsignedIntegerOrNilBase: base.<br>
fractionPart ifNil: ["Oops, the decimal point seems not part of this number"<br>
sourceStream skip: -1.<br>
^ neg<br>
ifTrue: [integerPart negated asScaledDecimal: 0]<br>
ifFalse: [integerPart asScaledDecimal: 0]].<br>
numberOfNonZeroFractionDigits := lastNonZero.<br>
numberOfTrailingZeroInFractionPart := nDigits - lastNonZero.<br>
(self readScaleWithDefaultNumberOfDigits: nDigits)<br>
ifFalse: ["No scale were provided. use number of digits after decimal point as scale"<br>
scale := nDigits].<br>
^self makeScaledDecimalWithNumberOfNonZeroFractionDigits: numberOfNonZeroFractionDigits andNumberOfTrailingZeroInFractionPart: numberOfTrailingZeroInFractionPart].<br>
self readScaleWithDefaultNumberOfDigits: 0.<br>
neg ifTrue: [integerPart := integerPart negated].<br>
^integerPart asScaledDecimal: scale!<br>
<br>
Item was changed:<br>
----- Method: SqNumberParser>>nextUnsignedInteger (in category 'parsing-public') -----<br>
nextUnsignedInteger<br>
"Read an unsigned Integer from sourceStream, asnwser that Integer.<br>
In Smalltalk syntax, a radix can be specified, and an exponent too."<br>
<br>
+ base := self defaultBase.<br>
- base := 10.<br>
neg := false.<br>
integerPart := self nextUnsignedIntegerOrNilBase: base.<br>
(sourceStream peekFor: $r)<br>
ifTrue: ["<base>r<integer>"<br>
(base := integerPart) < 2<br>
ifTrue: [<br>
sourceStream skip: -1.<br>
^ self expected: 'an integer greater than 1 as valid radix'].<br>
integerPart := self nextUnsignedIntegerBase: base].<br>
^ self makeIntegerOrScaledInteger!<br>
<br>
Item was changed:<br>
----- Method: SqNumberParser>>readScaleWithDefaultNumberOfDigits: (in category 'parsing-private') -----<br>
readScaleWithDefaultNumberOfDigits: anInteger<br>
"Read the scale if any and store it into scale instance Variable.<br>
Answer true if found, answer false if none.<br>
The scale is specified by letter s, optionnally followed by a positive integer in base 10.<br>
If no integer is specified, that means using as many digits as provided after the fraction separator, as provided by parameter anInteger.<br>
A letter s followed by another letter is not considered as a scale specification, because it could be part of a message."<br>
<br>
scale := 0.<br>
sourceStream atEnd<br>
ifTrue: [ ^ false ].<br>
(sourceStream peekFor: $s)<br>
ifFalse: [ ^ false ].<br>
+ scale := self nextUnsignedIntegerOrNilBase: self defaultBase.<br>
- scale := self nextUnsignedIntegerOrNilBase: 10.<br>
scale<br>
ifNil: [ <br>
scale := anInteger.<br>
(sourceStream peek ifNil: [ false ] ifNotNil: [ :nextChar | nextChar isLetter ])<br>
ifTrue: [ <br>
sourceStream skip: -1. "ungobble the s"<br>
^ false ]<br>
ifFalse: [ ^ true ] ].<br>
^ true!<br>
<br>
<br>
</blockquote></div></div>