mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-28 16:40:28 +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'];
|
AlphabetChars = ['a'..'z','A'..'Z'];
|
||||||
AlphaNumChars = AlphabetChars+NumericChars;
|
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 ScanWhile(const s: AnsiString; var index: Integer; const ch: TCharSet): AnsiString;
|
||||||
function ScanTo(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;
|
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;
|
function CssValInt(const s: String; Def: integer): Integer;
|
||||||
|
|
||||||
type
|
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;
|
function ScanNumberC(const buf: string; var idx: Integer;
|
||||||
var numberText: string): TCNumberFormat;
|
var numberText: string): TCNumberFormat;
|
||||||
|
|
||||||
@ -109,6 +111,22 @@ begin
|
|||||||
index := length(s) + 1;
|
index := length(s) + 1;
|
||||||
end;
|
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;
|
function ScanTo(const s: AnsiString; var index: Integer; const ch: TCharSet): AnsiString;
|
||||||
var
|
var
|
||||||
i : Integer;
|
i : Integer;
|
||||||
@ -237,10 +255,73 @@ begin
|
|||||||
Result:=Copy(s, i, index-i);
|
Result:=Copy(s, i, index-i);
|
||||||
end;
|
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;
|
function ScanNumberC(const buf: string; var idx: Integer; var numberText: string): TCNumberFormat;
|
||||||
var
|
var
|
||||||
ch : char;
|
ch : char;
|
||||||
sec : string;
|
sub : string;
|
||||||
begin
|
begin
|
||||||
Result := nfError;
|
Result := nfError;
|
||||||
|
|
||||||
@ -250,21 +331,29 @@ begin
|
|||||||
end else
|
end else
|
||||||
ch := #0;
|
ch := #0;
|
||||||
|
|
||||||
if (idx<length(buf)) and (buf[idx]='0') and (buf[idx+1]='x') then begin
|
if (idx+2<=length(buf)) and ((buf[idx]='i') and (buf[idx+1]='n') and (buf[idx+2]='f')) then begin
|
||||||
inc(idx,2);
|
numberText:='inf';
|
||||||
numberText:='0x'+ScanWhile(buf, idx, HexChars);
|
inc(idx, 3);
|
||||||
Result := nfHex;
|
Result := nfFloat;
|
||||||
end else begin
|
end else if (idx+2<=length(buf)) and ((buf[idx]='n') and (buf[idx+1]='a') and (buf[idx+2]='n')) then begin
|
||||||
numberText:=ScanWhile(buf, idx, NumericChars);
|
numberText:='nan';
|
||||||
if ((idx<=length(buf)) and (buf[idx]='.')) then begin
|
inc(idx, 3);
|
||||||
|
if (idx < length(buf)) and (buf[idx]=':') then begin
|
||||||
|
writelN('att');
|
||||||
inc(idx);
|
inc(idx);
|
||||||
sec := ScanWhile(buf, idx, NumericChars);
|
sub := '';
|
||||||
if (sec = '') then Exit;
|
if (ScanNumberC(buf, idx, sub) in [nfHex, nfInteger]) then
|
||||||
numberText:=NumberText+'.'+sec;
|
numberText:=numberText+':'+sub
|
||||||
Result := nfFloat;
|
else
|
||||||
end else
|
Exit; // error
|
||||||
Result := nfInteger;
|
end;
|
||||||
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 (ch<>#0) then begin
|
||||||
if (numberText = '') then Exit;
|
if (numberText = '') then Exit;
|
||||||
|
@ -213,6 +213,7 @@ var
|
|||||||
cmt : string;
|
cmt : string;
|
||||||
done: boolean;
|
done: boolean;
|
||||||
fmt : TCNumberFormat;
|
fmt : TCNumberFormat;
|
||||||
|
si : integer;
|
||||||
begin
|
begin
|
||||||
numformat := wnfNo;
|
numformat := wnfNo;
|
||||||
Result := idx<=length(buf);
|
Result := idx<=length(buf);
|
||||||
@ -269,10 +270,27 @@ begin
|
|||||||
else
|
else
|
||||||
numformat := wnfInteger;
|
numformat := wnfInteger;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
end else if buf[idx] in GrammarChars then begin
|
end else if buf[idx] in GrammarChars then begin
|
||||||
|
si := idx;
|
||||||
resText:=ScanWhile(buf, idx, GrammarChars);
|
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;
|
done:=true;
|
||||||
end else begin
|
end else begin
|
||||||
token:=weError;
|
token:=weError;
|
||||||
|
Loading…
Reference in New Issue
Block a user