! mathpars.h - Parse Big Numbers and other formats in Inform.
! Version 1.0 (19-Sep-2001)
!
! by Matt Albrecht -
[email protected]
!
! (If you need to edit this file, note that indentations are 4 spaces
! and tabs are not used.)
!
! This has been donated to the Public Domain. Use, abuse, and don't blame me.
!
! To prevent dirtying the global namespace, all members of this file begin with
! "mathpars_", while members private to this file begin with "mathpars__".
! Due to unsigned stuff, requires Z-Machine version 5 or older.
System_file;
! C-like header!
Ifndef MATHPARS__INCLUDED;
Constant MATHPARS__INCLUDED;
Message "Adding Big Number Parser library";
!-------------------------------------------------------------------------------
! Signed Math routines
!-------------------------------------------------------------------------------
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
! Used for scoping in the grammar, such as:
!Verb 'type'
! * mathpars_BigNumber 'on'/'onto'/'in'/'with' Keypad -> Type reverse
! * 'on'/'onto'/'in'/'with' Keypad mathpars_BigNumber -> Type;
[ mathpars_BigNumber
val text old_cf len old_cw old_wn; ! locals
old_wn = wn;
if (NextWordStopped() == -1)
{
! no more words
return GPR_FAIL;
}
wn = old_wn;
text = WordAddress( wn );
len = WordLength( wn );
!print "[ length of word ",wn," is ",len," ]^";
if (len >= 0)
{
if (text->0 >= '0' && text->0 <= '9')
{
val = -1;
old_cf = consult_from;
old_cw = consult_words;
consult_words = 1;
consult_from = wn;
switch (text->(len-1))
{
'b' :
!print "[ parsing big number: binary ]^";
val = mathpars_readBinValue();
'h' :
!print "[ parsing big number: hex ]^";
val = mathpars_readHexValue();
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'd':
!print "[ parsing big number: decimal ]^";
val = mathpars_readDecValue();
}
consult_from = old_cf;
consult_words = old_cw;
if (val ~= -1)
{
++wn;
parsed_number = val;
!print "[ returning number ",val," ]^";
return GPR_NUMBER;
}
}
}
!print "[ did not find a number ]^";
return GPR_FAIL;
];
!-----------------------------------------------------------------
! Reads in from the input parse buffer a hex value, and returns
! it as a number. If the global Mathpars_Result is non-zero, then
! the value is not a Hex value. The value read is considered
! the consult part of the buffer.
!-----------------------------------------------------------------
Global Mathpars_Result;
[ mathpars_readHexValue
val digit text i pos len start;
Mathpars_Result = 0;
if (consult_words ~= 1)
{
HexResult = -1;
return -1;
}
pos = consult_from;
!print "[readHexValue ";
text = WordAddress( pos );
!print "(hex = ",(string)text,")";
len = WordLength( pos );
if (len >= 1)
{
if (text->(len-1) == 'h')
{
! allow for the last character in the string to be a
! 'h', for 80x86 assembly compatability mode.
--len;
}
}
while (text->start == '0')
{
++start;
}
if ((len-start) > 4)
{
! we can only process up to 4 hex digits
Mathpars_Result = -2;
return -1;
}
val = 0;
for (i = start : i < len : i++)
{
!print ": digit ",(char)text->i," is decimal ";
if (text->i >= '0' && text->i <= '9')
{
digit = text->i - '0';
}
else
if (text->i >= 'a' && text->i <= 'f')
{
digit = text->i - 'a' + 10;
}
else
if (text->i >= 'A' && text->i <= 'F')
{
digit = text->i - 'A' + 10;
}
else
{
! non-hex value
!print "*not hex value*^";
Mathpars_Result = text->i;
return -1;
}
! add in the new digit
val = val * 16 + digit;
!print digit," (val now ",val,")";
}
!print ": returning value ",val,"]^";
return val;
];
!-----------------------------------------------------------------
! Reads in from input parse buffer a binary value, and returns it
! as a number. If the global Mathpars_HexResult non-zero, then
! the value is not a Binary value. The value read is considered
! the consult part of the buffer.
!-----------------------------------------------------------------
[ mathpars_readBinValue
val digit text i pos len start; ! locals
Mathpars_Result = 0;
if (consult_words ~= 1)
{
Mathpars_Result = -1;
return -1;
}
pos = consult_from;
!print "[readBinValue ";
text = WordAddress( pos );
!print "(bin = ",(string)text,")";
len = WordLength( pos );
if (len >= 1)
{
if (text->(len-1) == 'b')
{
! allow for the last character in the string to be a
! 'b', for 80x86 assembly compatability mode.
--len;
}
}
while (text->start == '0')
{
++start;
}
if ((len-start) > 8)
{
! we can only process up to 8 binary digits
Mathpars_Result = -2;
return -1;
}
val = 0;
for (i = 0 : i < len : i++)
{
!print ": digit ",(char)text->i," is decimal ";
if (text->i >= '0' && text->i <= '1')
{
digit = text->i - '0';
}
else
{
! non-bin value
!print "*not binary value*^";
Mathpars_Result = text->i;
return -1;
}
! add in the new digit
val = val * 2 + digit;
!print digit," (val now ",val,")";
}
!print ": returning value ",val,"]^";
return val;
];
!-----------------------------------------------------------------
! Reads in from input parse buffer a binary value, and returns it
! as a number. If the global HexResult non-zero, then
! the value is not a Hex value. The value read is considered
! the consult part of the buffer.
!-----------------------------------------------------------------
[ mathpars_readDecValue
val digit text i pos len; ! locals
Mathpars_Result = 0;
if (consult_words ~= 1)
{
Mathpars_Result = -1;
return -1;
}
pos = consult_from;
!print "[readDecValue ";
text = WordAddress( pos );
!print "(dec = ",(string)text,")";
len = WordLength( pos );
if (len >= 1)
{
if (text->(len-1) == 'd')
{
! allow for the last character in the string to be a
! 'd', for 80x86 assembly compatability mode.
--len;
}
}
for (i = 0 : i < len : i++)
{
!print ": digit ",(char)text->i," is decimal ";
if (text->i >= '0' && text->i <= '9')
{
digit = text->i - '0';
}
else
{
! non-decimal value
!print "*not decimal value*^";
Mathpars_Result = text->i;
return -1;
}
! add in the new digit
val = val * 10 + digit;
!print digit," (val now ",val,")";
}
!print ": returning value ",val,"]^";
return val;
];
Endif; ! MATHPARS_INCLUDED