Suggestion for implementaton of "Radix Constasnts"
Original Reporter info from Mantis: XDPascal
-
Reporter name: Paul Robinson xdpascal@xdpascal.com
Original Reporter info from Mantis: XDPascal
- Reporter name: Paul Robinson xdpascal@xdpascal.com
Description:
Perhaps about 40+ years ago, I was reading a programming manual on microfichr, and discovered an interesting means to specify an integer constant in another base. This allows, not just base 16 (as the $ prefix allows), or octal (as the & prefix allows), but any base from 2-36. In that example, it allowed a number like baseRnumber where base was 2-36 and number was a string of characters in that base, e.g. 16R3efc for $3efc , 8R177362 for &177362, etc. At the time I thought it was a great idea. But how would you implement it? Then I saw someone had thought to use the # symbol in infix form (as opposed to the current prefix form) to define a radix constant.
This would allow the above to be specified as 16#4efc and 8#177362.
If interested in adding this feature, this is how it can be implemented:
- in the scanner loop which create tokens there will probably be a case statement like
Case CH of // Ch is the current character
...
'0'..'9': GetNumber
- In the following, ReadUppercaseChar retrieves the next character from the input file (or stream) into the global var CH, and if it is a letter, it's uppercase.
Procedure GetNumber:
var
digit: byte;
isReal: Boolean;
Realsum: Double;
Sum Integer;
begin
Sum :=0;
while Ch in ['0'..'9'] do
begin
Digit := Ord(CH)-ord('0'):
ReadUppercaseChar;
If sum>maximum then
begin
// do error check
end
else
Sum := Sum*10+Digit;
end;
if ch ='.' then
begin
// handle real
...
end
else
if ch ='#' then
begin
ReadUppercaseChar;
HandleRadixConstant(Sum);
end
// optional to handle 0X c-style hex constants
else
if (ch='X') and (sum = 0) then
begin
Sum := 16;
ReadUppercaseChar; // eat the x
NextUpperCh;
HandleRadixConstant(Sum);
end;
// handle the number read
...
end;
- create the procedure to process radix constants
// integers in any base 2..36
procedure ReadOtherBaseNumber(var Sum:Integer);
const
RadixString: Array[0..35] of char=('0','1','2','3','4','5','6','7','8','9',
'A','B','C','D','E','F','G','H','I','J',
'K','L','M','N','O','P','Q','R','S','T',
'U','V','W','X','Y','Z');
var
radixset: set of char = ['A'..;Z''0'..'9'];
Base,
Digit: Integer;
BadNum:Boolean;
begin
if (sum < 2 ) or (sum >35) then
begin
// invalid base - handle error
...
end;
Base := Sum;
sum := 0;
BadNum := TRUE;
while ch in RadixSet do
begin
For Digit := 0 to 35 do
if Ch = RadixString[Digit] then
Break;
If Digit > Base then
begin
// handle error: char not in range
...
exit;
end;
if sum >maxint then
begin
// Integer constant exceeds range
...
exit;
end;
sum := Base * sum + Digit;
BadNum := FALSE;
ReadUppercaseChar;
end;
if BadNum then
begin
// handle error
end;
end;
end;
I think this is a useful feature and I hope you will consider adding it. Thank you for your time in reading this.
Paul Robinson
Mantis conversion info:
- Mantis ID: 38434
- Monitored by: » @PascalDragon (Sven Barth)