mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-04-22 00:29:33 +02:00
[PATCH 168/188] update scanning for additional WAT numeric formats
From 7467c8670fbfe4c2793f323a89091ee8a59c0bda Mon Sep 17 00:00:00 2001 From: Dmitry Boyarintsev <skalogryz.lists@gmail.com> Date: Fri, 27 Mar 2020 13:23:26 -0400 git-svn-id: branches/wasm@46164 -
This commit is contained in:
parent
8030e5f439
commit
a8a0308e48
@ -23,6 +23,7 @@ const
|
||||
AlphabetChars = ['a'..'z','A'..'Z'];
|
||||
AlphaNumChars = AlphabetChars+NumericChars;
|
||||
|
||||
function ScanWhileWithFirst(const s: AnsiString; var index: Integer; const first, body: TCharSet): AnsiString;
|
||||
function ScanWhile(const s: AnsiString; var index: Integer; const ch: TCharSet): AnsiString;
|
||||
function ScanTo(const s: AnsiString; var index: Integer; const ch: TCharSet): AnsiString;
|
||||
function SkipToEoln(const s: AnsiString; var index: Integer): AnsiString;
|
||||
@ -46,8 +47,9 @@ procedure GetCssAbsBoundsRect(Css: TStrings; var r: TRect);
|
||||
function CssValInt(const s: String; Def: integer): Integer;
|
||||
|
||||
type
|
||||
TCNumberFormat = (nfError, nfInteger, nfHex, nfFloat);
|
||||
TCNumberFormat = (nfError, nfInteger, nfHex, nfFloat, nfFloatHex);
|
||||
|
||||
// if buf contains "nan" or "inf" it's also recognized as float numbers
|
||||
function ScanNumberC(const buf: string; var idx: Integer;
|
||||
var numberText: string): TCNumberFormat;
|
||||
|
||||
@ -109,6 +111,22 @@ begin
|
||||
index := length(s) + 1;
|
||||
end;
|
||||
|
||||
function ScanWhileWithFirst(const s: AnsiString; var index: Integer; const first, body: TCharSet): AnsiString;
|
||||
var
|
||||
i : Integer;
|
||||
begin
|
||||
Result := '';
|
||||
if (index <= 0) or (index > length(s)) then Exit;
|
||||
|
||||
i:=index;
|
||||
if not (s[i] in first) then Exit;
|
||||
|
||||
inc(i);
|
||||
while (i<=length(s)) and (s[i] in body) do inc(i);
|
||||
Result := Copy(s, index, i-index);
|
||||
index:=i;
|
||||
end;
|
||||
|
||||
function ScanTo(const s: AnsiString; var index: Integer; const ch: TCharSet): AnsiString;
|
||||
var
|
||||
i : Integer;
|
||||
@ -237,10 +255,73 @@ begin
|
||||
Result:=Copy(s, i, index-i);
|
||||
end;
|
||||
|
||||
function ScanHexNumber(const buf: string; var idx: Integer; var numberText: string): TCNumberFormat;
|
||||
var
|
||||
xp : char;
|
||||
s : string;
|
||||
begin
|
||||
Result := nfError;
|
||||
if (idx=length(buf)) or (buf[idx]<>'0') or (buf[idx+1]<>'x') then Exit;
|
||||
inc(idx, 2);
|
||||
numberText := ScanWhile(buf, idx, HexChars);
|
||||
if numberText = '' then Exit;
|
||||
|
||||
numberText := '0x'+numberText;
|
||||
if ((idx<=length(buf)) and (buf[idx] in ['.','p','P'])) then begin
|
||||
if buf[idx]='.' then begin
|
||||
s := ScanWhileWithFirst(buf, idx, ['.']+HexChars, HexChars);
|
||||
if s = '' then Exit; // should not be empty
|
||||
numberText := numberText + s;
|
||||
end;
|
||||
|
||||
if buf[idx] in ['p','P'] then begin
|
||||
// hexal exponenta is numeric, not hexidemical
|
||||
xp := buf[idx];
|
||||
inc(idx);
|
||||
s := ScanWhileWithFirst(buf, idx, SignNumericChars, NumericChars);
|
||||
if s = '' then Exit;
|
||||
numberText := numberText + xp+s;
|
||||
end;
|
||||
Result := nfFloathex
|
||||
end else
|
||||
Result := nfHex;
|
||||
end;
|
||||
|
||||
function ScanNumeric(const buf: string; var idx: integer; var numberText: string): TCNumberFormat;
|
||||
var
|
||||
mnt : string;
|
||||
exp : string;
|
||||
xp : char;
|
||||
begin
|
||||
Result := nfError;
|
||||
numberText:=ScanWhile(buf, idx, NumericChars);
|
||||
|
||||
if ((idx<=length(buf)) and (buf[idx] in ['.','e','E'])) then begin
|
||||
|
||||
// mantissa (or fractional part) can be empty
|
||||
mnt := ScanWhileWithFirst(buf, idx, ['.']+NumericChars, NumericChars);
|
||||
|
||||
if (buf[idx] in ['e','E']) then begin
|
||||
xp:=buf[idx];
|
||||
inc(idx);
|
||||
exp := ScanWhileWithFirst(buf, idx, SignNumericChars, NumericChars);
|
||||
// exponent cannot be empty, if "e" is present
|
||||
if exp='' then Exit;
|
||||
exp := xp+exp;
|
||||
end else
|
||||
exp := '';
|
||||
|
||||
numberText:=NumberText+mnt+exp;
|
||||
Result := nfFloat;
|
||||
end else if numberText<>'' then
|
||||
Result := nfInteger;
|
||||
end;
|
||||
|
||||
|
||||
function ScanNumberC(const buf: string; var idx: Integer; var numberText: string): TCNumberFormat;
|
||||
var
|
||||
ch : char;
|
||||
sec : string;
|
||||
sub : string;
|
||||
begin
|
||||
Result := nfError;
|
||||
|
||||
@ -250,21 +331,29 @@ begin
|
||||
end else
|
||||
ch := #0;
|
||||
|
||||
if (idx<length(buf)) and (buf[idx]='0') and (buf[idx+1]='x') then begin
|
||||
inc(idx,2);
|
||||
numberText:='0x'+ScanWhile(buf, idx, HexChars);
|
||||
Result := nfHex;
|
||||
end else begin
|
||||
numberText:=ScanWhile(buf, idx, NumericChars);
|
||||
if ((idx<=length(buf)) and (buf[idx]='.')) then begin
|
||||
if (idx+2<=length(buf)) and ((buf[idx]='i') and (buf[idx+1]='n') and (buf[idx+2]='f')) then begin
|
||||
numberText:='inf';
|
||||
inc(idx, 3);
|
||||
Result := nfFloat;
|
||||
end else if (idx+2<=length(buf)) and ((buf[idx]='n') and (buf[idx+1]='a') and (buf[idx+2]='n')) then begin
|
||||
numberText:='nan';
|
||||
inc(idx, 3);
|
||||
if (idx < length(buf)) and (buf[idx]=':') then begin
|
||||
writelN('att');
|
||||
inc(idx);
|
||||
sec := ScanWhile(buf, idx, NumericChars);
|
||||
if (sec = '') then Exit;
|
||||
numberText:=NumberText+'.'+sec;
|
||||
Result := nfFloat;
|
||||
end else
|
||||
Result := nfInteger;
|
||||
end;
|
||||
sub := '';
|
||||
if (ScanNumberC(buf, idx, sub) in [nfHex, nfInteger]) then
|
||||
numberText:=numberText+':'+sub
|
||||
else
|
||||
Exit; // error
|
||||
end;
|
||||
Result := nfFloat;
|
||||
end else if (idx<length(buf)) and (buf[idx]='0') and (buf[idx+1]='x') then begin
|
||||
Result := ScanHexNumber(buf, idx, numberText)
|
||||
end else
|
||||
Result := ScanNumeric(buf, idx, numberText);
|
||||
|
||||
if Result = nfError then Exit;
|
||||
|
||||
if (ch<>#0) then begin
|
||||
if (numberText = '') then Exit;
|
||||
|
@ -213,6 +213,7 @@ var
|
||||
cmt : string;
|
||||
done: boolean;
|
||||
fmt : TCNumberFormat;
|
||||
si : integer;
|
||||
begin
|
||||
numformat := wnfNo;
|
||||
Result := idx<=length(buf);
|
||||
@ -269,10 +270,27 @@ begin
|
||||
else
|
||||
numformat := wnfInteger;
|
||||
end;
|
||||
|
||||
end else if buf[idx] in GrammarChars then begin
|
||||
si := idx;
|
||||
resText:=ScanWhile(buf, idx, GrammarChars);
|
||||
GetGrammar(resText, token, instrCode);
|
||||
|
||||
// second try for the number
|
||||
if (resText = 'nan') or (resText = 'inf') then begin
|
||||
idx := si;
|
||||
fmt := ScanNumberC(buf, idx, resText);
|
||||
if fmt = nfError then begin
|
||||
token := weError;
|
||||
Exit;
|
||||
end else
|
||||
token:=weNumber;
|
||||
case fmt of
|
||||
nfFloat: numformat := wnfFloat;
|
||||
nfHex: numformat := wnfHex;
|
||||
else
|
||||
numformat := wnfInteger;
|
||||
end;
|
||||
end else
|
||||
GetGrammar(resText, token, instrCode);
|
||||
done:=true;
|
||||
end else begin
|
||||
token:=weError;
|
||||
|
Loading…
Reference in New Issue
Block a user