mirror of
https://github.com/ganelson/inform.git
synced 2024-07-09 02:24:21 +03:00
87 lines
2.5 KiB
Plaintext
87 lines
2.5 KiB
Plaintext
B/numt: Number Template.
|
|
|
|
@Purpose: Support for parsing integers.
|
|
|
|
@-------------------------------------------------------------------------------
|
|
|
|
@p Understanding.
|
|
In our target virtual machines, numbers are stored in twos-complement form,
|
|
so that a 16-bit VM can hold the range of integers $-2^{15} = -32768$ to
|
|
$2^{15}-1 = +32767$, while a 32-bit VM can hold $-2^{31} = -2147483648$ to
|
|
$2^{31}-1 = +2147483647$: the token below accepts exactly those ranges.
|
|
|
|
@c
|
|
[ DECIMAL_TOKEN wnc wna r n wa wl sign base digit digit_count original_wn group_wn;
|
|
wnc = wn; original_wn = wn; group_wn = wn;
|
|
{-call:PL::Parsing::Tokens::Values::number}
|
|
wn = wnc;
|
|
r = ParseTokenStopped(ELEMENTARY_TT, NUMBER_TOKEN);
|
|
if ((r == GPR_NUMBER) && (parsed_number ~= 10000)) return r;
|
|
wn = wnc;
|
|
wa = WordAddress(wn);
|
|
wl = WordLength(wn);
|
|
sign = 1; base = 10; digit_count = 0;
|
|
if (wa->0 ~= '-' or '$' or '0' or '1' or '2' or '3' or '4'
|
|
or '5' or '6' or '7' or '8' or '9')
|
|
return GPR_FAIL;
|
|
if (wa->0 == '-') { sign = -1; wl--; wa++; }
|
|
if (wl == 0) return GPR_FAIL;
|
|
n = 0;
|
|
while (wl > 0) {
|
|
if (wa->0 >= 'a') digit = wa->0 - 'a' + 10;
|
|
else digit = wa->0 - '0';
|
|
digit_count++;
|
|
switch (base) {
|
|
2: if (digit_count == 17) return GPR_FAIL;
|
|
10:
|
|
#Iftrue (WORDSIZE == 2);
|
|
if (digit_count == 6) return GPR_FAIL;
|
|
if (digit_count == 5) {
|
|
if (n > 3276) return GPR_FAIL;
|
|
if (n == 3276) {
|
|
if (sign == 1 && digit > 7) return GPR_FAIL;
|
|
if (sign == -1 && digit > 8) return GPR_FAIL;
|
|
}
|
|
}
|
|
#Ifnot; ! i.e., if (WORDSIZE == 4)
|
|
if (digit_count == 11) return GPR_FAIL;
|
|
if (digit_count == 10) {
|
|
if (n > 214748364) return GPR_FAIL;
|
|
if (n == 214748364) {
|
|
if (sign == 1 && digit > 7) return GPR_FAIL;
|
|
if (sign == -1 && digit > 8) return GPR_FAIL;
|
|
}
|
|
}
|
|
#Endif;
|
|
16: if (digit_count == 5) return GPR_FAIL;
|
|
}
|
|
if (digit >= 0 && digit < base) n = base*n + digit;
|
|
else return GPR_FAIL;
|
|
wl--; wa++;
|
|
}
|
|
parsed_number = n*sign; wn++;
|
|
return GPR_NUMBER;
|
|
];
|
|
|
|
@p Truth states.
|
|
And although truth states are not strictly speaking numbers, this seems as
|
|
good a point as any to parse them:
|
|
|
|
@c
|
|
[ TRUTH_STATE_TOKEN original_wn wd;
|
|
original_wn = wn;
|
|
{-call:PL::Parsing::Tokens::Values::truth_state}
|
|
wn = original_wn;
|
|
wd = NextWordStopped();
|
|
if (wd == 'true') { parsed_number = 1; return GPR_NUMBER; }
|
|
if (wd == 'false') { parsed_number = 0; return GPR_NUMBER; }
|
|
wn = original_wn;
|
|
return GPR_FAIL;
|
|
];
|
|
|
|
@p Absolute value.
|
|
It's convenient to have this around somewhere:
|
|
|
|
@c
|
|
[ NUMBER_TY_Abs x; if (x<0) return -x; return x; ];
|