with Uintp; use Uintp;
with Urealp; use Urealp;
separate (Scn)
procedure Nlit is
C : Character;
Base_Char : Character;
Base : Int;
UI_Base : Uint;
UI_Int_Value : Uint;
UI_Num_Value : Uint;
Scale : Int;
UI_Scale : Uint;
Exponent_Is_Negative : Boolean;
Extended_Digit_Value : Int;
Point_Scanned : Boolean;
procedure Error_Digit_Expected;
procedure Scan_Integer;
procedure Error_Digit_Expected is
begin
Error_Msg_S ("digit expected");
end Error_Digit_Expected;
procedure Scan_Integer is
C : Character;
begin
C := Source (Scan_Ptr);
loop
Accumulate_Checksum (C);
UI_Int_Value :=
UI_Int_Value * 10 + (Character'Pos (C) - Character'Pos ('0'));
Scan_Ptr := Scan_Ptr + 1;
Scale := Scale - 1;
C := Source (Scan_Ptr);
if C = '_' then
Accumulate_Checksum ('_');
loop
Scan_Ptr := Scan_Ptr + 1;
C := Source (Scan_Ptr);
exit when C /= '_';
Error_No_Double_Underline;
end loop;
if C not in '0' .. '9' then
Error_Digit_Expected;
exit;
end if;
else
exit when C not in '0' .. '9';
end if;
end loop;
end Scan_Integer;
begin
Base := 10;
UI_Base := Uint_10;
UI_Int_Value := Uint_0;
Scale := 0;
Scan_Integer;
Scale := 0;
Point_Scanned := False;
UI_Num_Value := UI_Int_Value;
Scale := 0;
C := Source (Scan_Ptr);
if C = '.' then
while C = '.' and then Source (Scan_Ptr + 1) /= '.' loop
Accumulate_Checksum ('.');
if Point_Scanned then
Error_Msg_S ("duplicate point ignored");
end if;
Point_Scanned := True;
Scan_Ptr := Scan_Ptr + 1;
C := Source (Scan_Ptr);
if C not in '0' .. '9' then
Error_Msg ("real literal cannot end with point", Scan_Ptr - 1);
else
Scan_Integer;
UI_Num_Value := UI_Int_Value;
end if;
end loop;
elsif C = '#'
or else (C = ':' and then
(Source (Scan_Ptr + 1) = '.'
or else
Source (Scan_Ptr + 1) in '0' .. '9'
or else
Source (Scan_Ptr + 1) in 'A' .. 'Z'
or else
Source (Scan_Ptr + 1) in 'a' .. 'z'))
then
Accumulate_Checksum (C);
Base_Char := C;
UI_Base := UI_Int_Value;
if UI_Base < 2 or else UI_Base > 16 then
Error_Msg_SC ("base not 2-16");
UI_Base := Uint_16;
end if;
Base := UI_To_Int (UI_Base);
Scan_Ptr := Scan_Ptr + 1;
C := Source (Scan_Ptr);
UI_Int_Value := Uint_0;
Scale := 0;
loop
if C in '0' .. '9' then
Accumulate_Checksum (C);
Extended_Digit_Value :=
Int'(Character'Pos (C)) - Int'(Character'Pos ('0'));
elsif C in 'A' .. 'F' then
Accumulate_Checksum (Character'Val (Character'Pos (C) + 32));
Extended_Digit_Value :=
Int'(Character'Pos (C)) - Int'(Character'Pos ('A')) + 10;
elsif C in 'a' .. 'f' then
Accumulate_Checksum (C);
Extended_Digit_Value :=
Int'(Character'Pos (C)) - Int'(Character'Pos ('a')) + 10;
else
Error_Msg_S ("extended digit expected");
exit;
end if;
if Extended_Digit_Value >= Base then
Error_Msg_S ("digit >= base");
end if;
UI_Int_Value := UI_Int_Value * UI_Base + Extended_Digit_Value;
Scale := Scale - 1;
Scan_Ptr := Scan_Ptr + 1;
C := Source (Scan_Ptr);
if C = '_' then
loop
Accumulate_Checksum ('_');
Scan_Ptr := Scan_Ptr + 1;
C := Source (Scan_Ptr);
exit when C /= '_';
Error_No_Double_Underline;
end loop;
elsif C = '.' then
Accumulate_Checksum ('.');
if Point_Scanned then
Error_Msg_S ("duplicate point ignored");
end if;
Scan_Ptr := Scan_Ptr + 1;
C := Source (Scan_Ptr);
Point_Scanned := True;
Scale := 0;
elsif C = Base_Char then
Accumulate_Checksum (C);
Scan_Ptr := Scan_Ptr + 1;
exit;
elsif C = '#' or else C = ':' then
Error_Msg_S ("based number delimiters must match");
Scan_Ptr := Scan_Ptr + 1;
exit;
elsif not Identifier_Char (C) then
if Base_Char = '#' then
Error_Msg_S ("missing '#");
else
Error_Msg_S ("missing ':");
end if;
exit;
end if;
end loop;
UI_Num_Value := UI_Int_Value;
end if;
if not Point_Scanned then
Scale := 0;
UI_Scale := Uint_0;
else
UI_Scale := UI_From_Int (Scale);
end if;
if Source (Scan_Ptr) = 'e' or else Source (Scan_Ptr) = 'E' then
Accumulate_Checksum ('e');
Scan_Ptr := Scan_Ptr + 1;
Exponent_Is_Negative := False;
if Source (Scan_Ptr) = '+' then
Accumulate_Checksum ('+');
Scan_Ptr := Scan_Ptr + 1;
elsif Source (Scan_Ptr) = '-' then
Accumulate_Checksum ('-');
if not Point_Scanned then
Error_Msg_S ("negative exponent not allowed for integer literal");
else
Exponent_Is_Negative := True;
end if;
Scan_Ptr := Scan_Ptr + 1;
end if;
UI_Int_Value := Uint_0;
if Source (Scan_Ptr) in '0' .. '9' then
Scan_Integer;
else
Error_Digit_Expected;
end if;
if Exponent_Is_Negative then
UI_Scale := UI_Scale - UI_Int_Value;
else
UI_Scale := UI_Scale + UI_Int_Value;
end if;
end if;
if Point_Scanned then
Token := Tok_Real_Literal;
Token_Node := New_Node (N_Real_Literal, Token_Ptr);
Set_Realval (Token_Node,
UR_From_Components (
Num => UI_Num_Value,
Den => -UI_Scale,
Rbase => Base));
else
Token := Tok_Integer_Literal;
Token_Node := New_Node (N_Integer_Literal, Token_Ptr);
if UI_Scale = 0 then
Set_Intval (Token_Node, UI_Num_Value);
elsif Operating_Mode /= Check_Syntax
and then (Serious_Errors_Detected = 0 or else Try_Semantics)
then
Set_Intval (Token_Node, UI_Num_Value * UI_Base ** UI_Scale);
else
Set_Intval (Token_Node, No_Uint);
end if;
end if;
return;
end Nlit;