Re: Change Set: tallyLiterals.1.cs
Eliot Miranda <[email protected]>
| Newsgroups | gmane.comp.lang.smalltalk.squeak.general |
|---|---|
| Message-ID | <CAC20JE0Po+nNO1KfFQxmjpPWE2W8EyXBQ=yTgGGUizt4qWGptA@mail.gmail.com> |
On Mon, Jun 1, 2026 at 2:02 PM Christoph Thiede via Squeak-dev < [email protected]> wrote: > *=============== Summary ===============* > > Change Set: tallyLiterals > Date: 1 June 2026 > Author: Christoph Thiede > > Adds support for tally bases and radix 1 to number parser. Also updates > Shout and tests. > !! At first I considered making 1r111 = 3 as supposed earlier on the mailing > list but then I found the following more consistent: > > 1r000 = 0. > 1t = 0. > 1t1 = 1. > 1t111 = 3. > > *=============== Diff ===============* > > *ExtendedNumberParser>>nextFraction {parsing-public} · ct 6/1/2026 21:45 > (changed)* > nextFraction > | numerator denominator numberOfTrailingZeroInIntegerPart | > base := self defaultBase. > neg := self peekSignIsMinus. > (integerPart := self nextUnsignedIntegerOrNilBase: base) > ifNil: [numberOfTrailingZeroInIntegerPart := 0] > ifNotNil: [ > numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero. > (sourceStream peekFor: $r) > ifTrue: ["<base>r<integer>" > - (base := integerPart) < 2 > + (base := integerPart) < 1 > ifTrue: [ > sourceStream skip: -1. > - ^ self expected: 'an integer greater than 1 > as valid radix']. > + ^ self expected: 'an integer greater than 0 > as valid radix']. > self peekSignIsMinus > ifTrue: [neg := neg not]. > integerPart := self nextUnsignedIntegerBase: base. > numberOfTrailingZeroInIntegerPart := nDigits - > lastNonZero]]. > (sourceStream peekFor: $.) > ifTrue: > [^self readFractionPartNumberOfTrailingZeroInIntegerPart: > numberOfTrailingZeroInIntegerPart]. > integerPart > ifNil: > ["No integerPart, raise an error" > ^ self expected: 'a digit']. > numerator := neg > ifTrue: [integerPart negated] > ifFalse: [integerPart]. > self readExponent ifTrue: [numerator := numerator * (base > raisedToInteger: exponent)]. > (sourceStream peekFor: $/) ifFalse: [^numerator]. > base := 10. > base := self defaultBase. > (denominator := self nextUnsignedIntegerOrNilBase: base) > ifNil: > [sourceStream skip: -1. "Not a valid denominator, ungobble / > and return numerator" > ^numerator]. > (sourceStream peekFor: $r) > ifTrue: ["<base>r<integer>" > - (base := denominator) < 2 > + (base := denominator) < 1 > ifTrue: [ > sourceStream skip: -1. > - ^ self expected: 'an integer greater than 1 as valid > radix']. > + ^ self expected: 'an integer greater than 0 as valid > radix']. > denominator := self nextUnsignedIntegerBase: base]. > self readExponent ifTrue: [denominator := denominator * (base > raisedToInteger: exponent)]. > ^numerator / denominator > > *ExtendedNumberParser>>nextNumber {parsing-public} · ct 6/1/2026 22:52 > (changed)* > nextNumber > "main method for reading a number. > This one can read Float Integer and ScaledDecimal" > > | numberOfTrailingZeroInIntegerPart | > base := self defaultBase. > neg := self peekSignIsMinus. > integerPart := self nextUnsignedIntegerOrNilBase: base. > integerPart ifNil: [(sourceStream peekFor: $.) > ifTrue: [ > "Try .1 syntax" > ^self readNumberWithoutIntegerPart] > ifFalse: [ > "This is not a regular number beginning with a digit > It is time to check for exceptional condition NaN and Infinity" > ^self readNamedFloatOrFail]]. > numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero. > (sourceStream peekFor: $r) > ifTrue: ["<base>r<integer>" > | oldNeg pos | > pos := sourceStream position - 1. > - (base := integerPart) < 2 > - ifTrue: ["A radix currently need to be greater than 1, > ungobble the r and return the integer part" > + (base := integerPart) < 1 > + ifTrue: ["A radix currently need to be greater than 0, > ungobble the r and return the integer part" > sourceStream skip: -1. > ^neg > ifTrue: [base negated] > ifFalse: [base]]. > oldNeg := neg. > self peekSignIsMinus ifTrue: [neg := neg not]. > integerPart := self nextUnsignedIntegerOrNilBase: base. > integerPart ifNil: [ > (sourceStream peekFor: $.) ifTrue: [self > readNumberWithoutIntegerPartOrNil ifNotNil: [:aNumber | ^aNumber]]. > sourceStream position: pos. > ^oldNeg > ifTrue: [base negated] > ifFalse: [base]]. > numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero]. > + (sourceStream peekFor: $t) > + ifTrue: ["1t<integer>" > + integerPart = 1t1 > + ifTrue: [ > + | char | > + nDigits := lastNonZero := 0. > + [(char := sourceStream next) = $1 ifFalse: [ > + char ifNotNil: [sourceStream skip: -1]. > + ^ neg ifTrue: [nDigits negated] ifFalse: > [nDigits]]. > + nDigits := nDigits + 1] repeat] > + ifFalse: [ > + sourceStream skip: -1]]. > ^ (sourceStream peekFor: $.) > ifTrue: [self > readNumberWithFractionPartNumberOfTrailingZeroInIntegerPart: > numberOfTrailingZeroInIntegerPart] > ifFalse: [self makeIntegerOrScaledInteger] > > *NumberParser>>nextElementaryLargeIntegerBase: {parsing-large int} · ct > 6/1/2026 22:14 (changed)* > nextElementaryLargeIntegerBase: aRadix > "Form an unsigned integer with incoming digits from sourceStream. > Return this integer, or zero if no digits found. > Stop reading if end of digits or if a LargeInteger is formed. > Count the number of digits and the position of lastNonZero digit and > store them in instVar." > > | value digit char | > - value := 0. > nDigits := 0. > lastNonZero := 0. > + value := 0. > [ > value isLarge ifTrue: [ ^value ]. > char := sourceStream next ifNil: [ ^value ]. > ((digit := char digitValue) < 0 or: [digit >= aRadix]) ifTrue: [ > sourceStream skip: -1. > ^value ]. > nDigits := nDigits + 1. > digit = 0 > ifFalse: [ > lastNonZero := nDigits. > value := value * aRadix + digit ] > ifTrue: [ value := value * aRadix ] ] repeat > > *SHParserST80>>scanNumber {scan} · ct 6/1/2026 22:34 (changed)* > scanNumber > > | c | > currentTokenSourcePosition := sourcePosition. > self skipDigits. > (c := self currentChar) == $r > ifTrue: [ > | base | > base := (source copyFrom: currentTokenSourcePosition to: > sourcePosition - 1) asUnsignedInteger. > - base < 2 ifTrue: [ self fail ": radix must be greater than > 1" ]. > + base < 1 ifTrue: [ self fail ": radix must be greater than > 1" ]. > self peekChar == $- ifTrue: [ self nextChar ]. > self skipDigitsBase: base. > (c := self currentChar) == $. ifTrue: [ > (self isDigit: self peekChar base: base) ifTrue: [ > self skipDigitsBase: base]. > c := self currentChar ] ] > ifFalse: [ > + c == $t ifTrue: [ > + | base | > + base := (source copyFrom: currentTokenSourcePosition to: > sourcePosition - 1) asUnsignedInteger. > + base = 1t1 ifTrue: [ > + self peekChar == $- ifTrue: [ self nextChar ]. > + [ self nextChar = $1 ] whileTrue]]. > c == $. ifTrue: [ > self peekChar isDigit ifFalse: [ > ^currentToken := source copyFrom: > currentTokenSourcePosition to: sourcePosition - 1 ]. > self skipDigits. > c := self currentChar ] ]. > c == $s > ifTrue: [ > (c := self nextChar) isDigit > ifFalse: [ c isLetter ifTrue: [sourcePosition := > sourcePosition - 1 ] ] > ifTrue: [ self skipDigits ] ] > ifFalse: [ > (c == $d > or: [ c == $e > or: [ c == $q ] ]) > ifTrue: [ > ((c := self nextChar) isDigit or: [ c == $- and: [ > self peekChar isDigit ] ]) > ifFalse: [ sourcePosition := sourcePosition - 1 ] > ifTrue: [ self skipDigits ] ] ]. > currentToken := source copyFrom: currentTokenSourcePosition to: > sourcePosition - 1 > > *SqNumberParser>>nextFraction {parsing-public} · ct 6/1/2026 21:45 > (changed)* > nextFraction > | numerator denominator numberOfTrailingZeroInIntegerPart | > base := self defaultBase. > neg := self peekSignIsMinus. > (integerPart := self nextUnsignedIntegerOrNilBase: base) > ifNil: ["No integerPart, raise an error" > ^ self expected: 'a digit']. > numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero. > (sourceStream peekFor: $r) > ifTrue: ["<base>r<integer>" > - (base := integerPart) < 2 > + (base := integerPart) < 1 > ifTrue: [ > sourceStream skip: -1. > - ^ self expected: 'an integer greater than 1 as valid > radix']. > + ^ self expected: 'an integer greater than 0 as valid > radix']. > self peekSignIsMinus > ifTrue: [neg := neg not]. > integerPart := self nextUnsignedIntegerBase: base. > numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero]. > (sourceStream peekFor: $.) > ifTrue: > [^self readFractionPartNumberOfTrailingZeroInIntegerPart: > numberOfTrailingZeroInIntegerPart]. > numerator := neg > ifTrue: [integerPart negated] > ifFalse: [integerPart]. > self readExponent ifTrue: [numerator := numerator * (base > raisedToInteger: exponent)]. > (sourceStream peekFor: $/) ifFalse: [^numerator]. > base := self defaultBase. > (denominator := self nextUnsignedIntegerOrNilBase: base) > ifNil: > [sourceStream skip: -1. "Not a valid denominator, ungobble / > and return numerator" > ^numerator]. > (sourceStream peekFor: $r) > ifTrue: ["<base>r<integer>" > - (base := denominator) < 2 > + (base := denominator) < 1 > ifTrue: [ > sourceStream skip: -1. > - ^ self expected: 'an integer greater than 1 as valid > radix']. > + ^ self expected: 'an integer greater than 0 as valid > radix']. > denominator := self nextUnsignedIntegerBase: base]. > self readExponent ifTrue: [denominator := denominator * (base > raisedToInteger: exponent)]. > ^numerator / denominator > > *SqNumberParser>>nextInteger {parsing-public} · ct 6/1/2026 21:45 > (changed)* > nextInteger > "Read an Integer from sourceStream, asnwser that Integer. > In Smalltalk syntax, a radix can be specified, and an exponent too." > > | numberOfTrailingZeroInIntegerPart | > base := self defaultBase. > neg := self peekSignIsMinus. > integerPart := self nextUnsignedIntegerOrNilBase: base. > numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero. > (sourceStream peekFor: $r) > ifTrue: ["<base>r<integer>" > - (base := integerPart) < 2 > + (base := integerPart) < 1 > ifTrue: [ > sourceStream skip: -1. > - ^ self expected: 'an integer greater than 1 as valid > radix']. > + ^ self expected: 'an integer greater than 0 as valid > radix']. > self peekSignIsMinus > ifTrue: [neg := neg not]. > integerPart := self nextUnsignedIntegerBase: base. > numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero]. > ^ self makeIntegerOrScaledInteger > > *SqNumberParser>>nextNumber {parsing-public} · ct 6/1/2026 22:51 (changed)* > nextNumber > "main method for reading a number. > This one can read Float Integer and ScaledDecimal" > > | numberOfTrailingZeroInIntegerPart | > base := self defaultBase. > neg := self peekSignIsMinus. > integerPart := self nextUnsignedIntegerOrNilBase: base. > integerPart ifNil: [ > "This is not a regular number beginning with a digit > It is time to check for exceptional condition NaN and Infinity" > ^self readNamedFloatOrFail]. > numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero. > (sourceStream peekFor: $r) > ifTrue: ["<base>r<integer>" > - (base := integerPart) < 2 > + (base := integerPart) < 1 > ifTrue: [ > sourceStream skip: -1. > - ^ self expected: 'an integer greater than 1 as valid > radix']. > + ^ self expected: 'an integer greater than 0 as valid > radix']. > self peekSignIsMinus > ifTrue: [neg := neg not]. > integerPart := self nextUnsignedIntegerBase: base. > - numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero]. > + numberOfTrailingZeroInIntegerPart := nDigits - lastNonZero] > + ifFalse: [ > + (sourceStream peekFor: $t) > + ifTrue: ["1t<integer>" > + integerPart = 1t1 > + ifTrue: [ > + | char | > + nDigits := lastNonZero := 0. > + [(char := sourceStream next) = $1 ifFalse: [ > + char ifNotNil: [sourceStream skip: -1]. > + ^ neg ifTrue: [nDigits negated] ifFalse: > [nDigits]]. > + nDigits := nDigits + 1] repeat] > + ifFalse: [ > + sourceStream skip: -1]]]. > ^ (sourceStream peekFor: $.) > ifTrue: [self > readNumberWithFractionPartNumberOfTrailingZeroInIntegerPart: > numberOfTrailingZeroInIntegerPart] > ifFalse: [self makeIntegerOrScaledInteger] > > *SqNumberParser>>nextUnsignedInteger {parsing-public} · ct 6/1/2026 21:45 > (changed)* > nextUnsignedInteger > "Read an unsigned Integer from sourceStream, asnwser that Integer. > In Smalltalk syntax, a radix can be specified, and an exponent too." > > base := self defaultBase. > neg := false. > integerPart := self nextUnsignedIntegerOrNilBase: base. > (sourceStream peekFor: $r) > ifTrue: ["<base>r<integer>" > - (base := integerPart) < 2 > + (base := integerPart) < 1 > ifTrue: [ > sourceStream skip: -1. > - ^ self expected: 'an integer greater than 1 as valid > radix']. > + ^ self expected: 'an integer greater than 0 as valid > radix']. > integerPart := self nextUnsignedIntegerBase: base]. > ^ self makeIntegerOrScaledInteger > > *SqNumberParserTest>>testBases {tests - fail} · ct 6/1/2026 22:51 > (changed)* > testBases > > self assert: (SqNumberParser parse: '16r20') equals: 32. > self assert: (SqNumberParser parse: '2r10') equals: 2. > + self assert: (SqNumberParser parse: '1r000') equals: 0. > self assert: ((SqNumberParser on: '10') > nextIntegerBase: 2) equals: 2. > self assert: ((SqNumberParser on: '10') > defaultBase: 2; > nextNumber) equals: 2. > self assert: ((SqNumberParser on: '1000r10') > defaultBase: 2; > nextNumber) equals: 8. > > *SqNumberParserTest>>testTally {tests - fail} · ct 6/1/2026 22:49* > + testTally > + > + | rs | > + self assert: (SqNumberParser parse: '1t') equals: 0. > + self assert: (SqNumberParser parse: '1t1') equals: 1. > + self assert: (SqNumberParser parse: '1t111') equals: 3. > + self assert: (SqNumberParser parse: '-1t11') equals: -2. > + > + rs := '1t11e1' readStream. > + self assert: (SqNumberParser parse: rs) equals: 2. > + self assert: rs upToEnd equals: 'e1'. > + > + rs := '2t1' readStream. > + self assert: (SqNumberParser parse: rs) equals: 2. > + self assert: rs upToEnd equals: 't1'. > + > + rs := '1t0' readStream. > + self assert: (SqNumberParser parse: rs) equals: 0. > + self assert: rs upToEnd equals: '0'. > + > + rs := '1t22' readStream. > + self assert: (SqNumberParser parse: rs) equals: 0. > + self assert: rs upToEnd equals: '22'. > > -- > *Sent from **Squeak Inbox Talk > <https://github.com/hpi-swa-lab/squeak-inbox-talk>*Squeak-dev mailing > list -- [email protected] > To unsubscribe send an email to > [email protected] -- _,,,^..^,,,_ best, Eliot Squeak-dev mailing list -- [email protected] To unsubscribe send an email to [email protected]