762 lines
17 KiB
ObjectPascal
762 lines
17 KiB
ObjectPascal
|
|
||
|
{******************************************}
|
||
|
{ }
|
||
|
{ FastScript v1.9 }
|
||
|
{ Parser }
|
||
|
{ }
|
||
|
{ (c) 2003-2007 by Alexander Tzyganenko, }
|
||
|
{ Fast Reports Inc }
|
||
|
{ }
|
||
|
{******************************************}
|
||
|
//VCL uses section
|
||
|
{$IFNDEF FMX}
|
||
|
unit fs_iparser;
|
||
|
|
||
|
interface
|
||
|
|
||
|
{$i fs.inc}
|
||
|
|
||
|
uses
|
||
|
{$IFNDEF CROSS_COMPILE}
|
||
|
Windows,
|
||
|
{$ENDIF}
|
||
|
SysUtils, Classes;
|
||
|
//FMX uses
|
||
|
{$ELSE}
|
||
|
interface
|
||
|
|
||
|
{$i fs.inc}
|
||
|
|
||
|
uses
|
||
|
System.Types, FMX.Types, System.SysUtils, System.Classes;
|
||
|
{$ENDIF}
|
||
|
|
||
|
|
||
|
|
||
|
type
|
||
|
TfsIdentifierCharset = set of AnsiChar;
|
||
|
|
||
|
{ TfsParser parser the source text and return such elements as identifiers,
|
||
|
keywords, punctuation, strings and numbers. }
|
||
|
|
||
|
TfsParser = class(TObject)
|
||
|
private
|
||
|
FCaseSensitive: Boolean;
|
||
|
FCommentBlock1: String;
|
||
|
FCommentBlock11: String;
|
||
|
FCommentBlock12: String;
|
||
|
FCommentBlock2: String;
|
||
|
FCommentBlock21: String;
|
||
|
FCommentBlock22: String;
|
||
|
FCommentLine1: String;
|
||
|
FCommentLine2: String;
|
||
|
FHexSequence: String;
|
||
|
FIdentifierCharset: TfsIdentifierCharset;
|
||
|
FKeywords: TStrings;
|
||
|
FLastPosition: Integer;
|
||
|
FPosition: Integer;
|
||
|
FSize: Integer;
|
||
|
FSkiPChar: String;
|
||
|
FSkipEOL: Boolean;
|
||
|
FSkipSpace: Boolean;
|
||
|
FStringQuotes: String;
|
||
|
FText: String;
|
||
|
FUseY: Boolean;
|
||
|
FYList: TList;
|
||
|
FSpecStrChar: Boolean;
|
||
|
function DoDigitSequence: Boolean;
|
||
|
function DoHexDigitSequence: Boolean;
|
||
|
function DoScaleFactor: Boolean;
|
||
|
function DoUnsignedInteger: Boolean;
|
||
|
function DoUnsignedReal: Boolean;
|
||
|
procedure SetPosition(const Value: Integer);
|
||
|
procedure SetText(const Value: String);
|
||
|
function Ident: String;
|
||
|
procedure SetCommentBlock1(const Value: String);
|
||
|
procedure SetCommentBlock2(const Value: String);
|
||
|
public
|
||
|
constructor Create;
|
||
|
destructor Destroy; override;
|
||
|
procedure Clear;
|
||
|
procedure ConstructCharset(const s: String);
|
||
|
|
||
|
{ skip all #0..#31 symbols }
|
||
|
procedure SkipSpaces;
|
||
|
{ get EOL symbol }
|
||
|
function GetEOL: Boolean;
|
||
|
{ get any valid ident except keyword }
|
||
|
function GetIdent: String;
|
||
|
{ get any valid punctuation symbol like ,.;: }
|
||
|
function GetChar: String;
|
||
|
{ get any valid ident or keyword }
|
||
|
function GetWord: String;
|
||
|
{ get valid hex/int/float number }
|
||
|
function GetNumber: String;
|
||
|
{ get valid quoted/control string like 'It''s'#13#10'working' }
|
||
|
function GetString: String;
|
||
|
{ get FR-specific string - variable or db field like [main data."field 1"] }
|
||
|
function GetFRString: String;
|
||
|
{ get Y:X position }
|
||
|
function GetXYPosition: String;
|
||
|
{ get plain position from X:Y }
|
||
|
function GetPlainPosition(pt: TPoint): Integer;
|
||
|
{ is this keyword? }
|
||
|
function IsKeyWord(const s: String): Boolean;
|
||
|
|
||
|
// Language-dependent elements
|
||
|
// For Pascal:
|
||
|
// CommentLine1 := '//';
|
||
|
// CommentBlock1 := '{,}';
|
||
|
// CommentBlock2 := '(*,*)';
|
||
|
// HexSequence := '$'
|
||
|
// IdentifierCharset := ['_', '0'..'9', 'a'..'z', 'A'..'Z'];
|
||
|
// Keywords: 'begin','end', ...
|
||
|
// StringQuotes := ''''
|
||
|
property CaseSensitive: Boolean read FCaseSensitive write FCaseSensitive;
|
||
|
property CommentBlock1: String read FCommentBlock1 write SetCommentBlock1;
|
||
|
property CommentBlock2: String read FCommentBlock2 write SetCommentBlock2;
|
||
|
property CommentLine1: String read FCommentLine1 write FCommentLine1;
|
||
|
property CommentLine2: String read FCommentLine2 write FCommentLine2;
|
||
|
property HexSequence: String read FHexSequence write FHexSequence;
|
||
|
property IdentifierCharset: TfsIdentifierCharset read FIdentifierCharset
|
||
|
write FIdentifierCharset;
|
||
|
property Keywords: TStrings read FKeywords;
|
||
|
property SkiPChar: String read FSkiPChar write FSkiPChar;
|
||
|
property SkipEOL: Boolean read FSkipEOL write FSkipEOL;
|
||
|
property SkipSpace: Boolean read FSkipSpace write FSkipSpace;
|
||
|
property StringQuotes: String read FStringQuotes write FStringQuotes;
|
||
|
property SpecStrChar: Boolean read FSpecStrChar write FSpecStrChar;
|
||
|
property UseY: Boolean read FUseY write FUseY;
|
||
|
|
||
|
{ Current position }
|
||
|
property Position: Integer read FPosition write SetPosition;
|
||
|
{ Text to parse }
|
||
|
property Text: String read FText write SetText;
|
||
|
end;
|
||
|
|
||
|
|
||
|
implementation
|
||
|
|
||
|
|
||
|
{ TfsParser }
|
||
|
|
||
|
constructor TfsParser.Create;
|
||
|
begin
|
||
|
FKeywords := TStringList.Create;
|
||
|
TStringList(FKeywords).Sorted := True;
|
||
|
FYList := TList.Create;
|
||
|
FUseY := True;
|
||
|
Clear;
|
||
|
end;
|
||
|
|
||
|
destructor TfsParser.Destroy;
|
||
|
begin
|
||
|
FKeywords.Free;
|
||
|
FYList.Free;
|
||
|
inherited;
|
||
|
end;
|
||
|
|
||
|
procedure TfsParser.Clear;
|
||
|
begin
|
||
|
FKeywords.Clear;
|
||
|
FSpecStrChar := False;
|
||
|
FCommentLine1 := '//';
|
||
|
CommentBlock1 := '{,}';
|
||
|
CommentBlock2 := '(*,*)';
|
||
|
FHexSequence := '$';
|
||
|
FIdentifierCharset := ['_', '0'..'9', 'a'..'z', 'A'..'Z'];
|
||
|
FSkipChar := '';
|
||
|
FSkipEOL := True;
|
||
|
FStringQuotes := '''';
|
||
|
FSkipSpace := True;
|
||
|
end;
|
||
|
|
||
|
procedure TfsParser.SetCommentBlock1(const Value: String);
|
||
|
var
|
||
|
sl: TStringList;
|
||
|
begin
|
||
|
FCommentBlock1 := Value;
|
||
|
FCommentBlock11 := '';
|
||
|
FCommentBlock12 := '';
|
||
|
|
||
|
sl := TStringList.Create;
|
||
|
sl.CommaText := FCommentBlock1;
|
||
|
if sl.Count > 0 then
|
||
|
FCommentBlock11 := sl[0];
|
||
|
if sl.Count > 1 then
|
||
|
FCommentBlock12 := sl[1];
|
||
|
sl.Free;
|
||
|
end;
|
||
|
|
||
|
procedure TfsParser.SetCommentBlock2(const Value: String);
|
||
|
var
|
||
|
sl: TStringList;
|
||
|
begin
|
||
|
FCommentBlock2 := Value;
|
||
|
FCommentBlock21 := '';
|
||
|
FCommentBlock22 := '';
|
||
|
|
||
|
sl := TStringList.Create;
|
||
|
sl.CommaText := FCommentBlock2;
|
||
|
if sl.Count > 0 then
|
||
|
FCommentBlock21 := sl[0];
|
||
|
if sl.Count > 1 then
|
||
|
FCommentBlock22 := sl[1];
|
||
|
sl.Free;
|
||
|
end;
|
||
|
|
||
|
procedure TfsParser.SetPosition(const Value: Integer);
|
||
|
begin
|
||
|
FPosition := Value;
|
||
|
FLastPosition := Value;
|
||
|
end;
|
||
|
|
||
|
procedure TfsParser.SetText(const Value: String);
|
||
|
var
|
||
|
i: Integer;
|
||
|
begin
|
||
|
FText := Value + #0;
|
||
|
FLastPosition := 1;
|
||
|
FPosition := 1;
|
||
|
FSize := Length(Value);
|
||
|
|
||
|
if FUseY then
|
||
|
begin
|
||
|
FYList.Clear;
|
||
|
FYList.Add(TObject(0));
|
||
|
for i := 1 to FSize do
|
||
|
if FText[i] = #10 then
|
||
|
FYList.Add(TObject(i));
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
procedure TfsParser.ConstructCharset(const s: String);
|
||
|
var
|
||
|
i: Integer;
|
||
|
begin
|
||
|
FIdentifierCharset := [];
|
||
|
for i := 1 to Length(s) do
|
||
|
FIdentifierCharset := FIdentifierCharset + [s[i]];
|
||
|
end;
|
||
|
|
||
|
function TfsParser.GetEOL: Boolean;
|
||
|
begin
|
||
|
SkipSpaces;
|
||
|
{$IFDEF Delphi12}
|
||
|
if CharInSet(FText[FPosition], [#10, #13]) then
|
||
|
{$ELSE}
|
||
|
if FText[FPosition] in [#10, #13] then
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
Result := True;
|
||
|
{$IFDEF Delphi12}
|
||
|
while CharInSet(FText[FPosition], [#10, #13]) do
|
||
|
{$ELSE}
|
||
|
while FText[FPosition] in [#10, #13] do
|
||
|
{$ENDIF}
|
||
|
Inc(FPosition);
|
||
|
end
|
||
|
else
|
||
|
Result := False;
|
||
|
end;
|
||
|
|
||
|
procedure TfsParser.SkipSpaces;
|
||
|
var
|
||
|
s1, s2: String;
|
||
|
Flag, CLine: Boolean;
|
||
|
Spaces: set of AnsiChar;
|
||
|
begin
|
||
|
Spaces := [#0..#32];
|
||
|
if not FSkipEOL then
|
||
|
{$IFDEF Windows}
|
||
|
Spaces := Spaces - [#13];
|
||
|
{$ELSE}
|
||
|
Spaces := Spaces - [#10];
|
||
|
{$ENDIF}
|
||
|
{$IFDEF Delphi12}
|
||
|
while (FPosition <= FSize) and (CharInSet(FText[FPosition], Spaces)) do
|
||
|
{$ELSE}
|
||
|
while (FPosition <= FSize) and (FText[FPosition] in Spaces) do
|
||
|
{$ENDIF}
|
||
|
Inc(FPosition);
|
||
|
{ skip basic '_' }
|
||
|
if (FPosition <= FSize) and (FSkipChar <> '') and (FText[FPosition] = FSkipChar[1]) then
|
||
|
begin
|
||
|
Inc(FPosition);
|
||
|
GetEOL;
|
||
|
SkipSpaces;
|
||
|
end;
|
||
|
|
||
|
if FPosition < FSize then
|
||
|
begin
|
||
|
if FCommentLine1 <> '' then
|
||
|
s1 := Copy(FText, FPosition, Length(FCommentLine1)) else
|
||
|
s1 := ' ';
|
||
|
if FCommentLine2 <> '' then
|
||
|
s2 := Copy(FText, FPosition, Length(FCommentLine2)) else
|
||
|
s2 := ' ';
|
||
|
|
||
|
if (s1 = FCommentLine1) or (s2 = FCommentLine2) then
|
||
|
begin
|
||
|
CLine := (FPosition - 1 > 0) and (FText[FPosition - 1] <> #10) and not FSkipEOL;
|
||
|
while (FPosition <= FSize) and (FText[FPosition] <> #10) do
|
||
|
begin
|
||
|
if (FText[FPosition] = {$IFDEF LINUX}#10{$ELSE}#13{$ENDIF}) and CLine then break;
|
||
|
Inc(FPosition);
|
||
|
end;
|
||
|
SkipSpaces;
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
Flag := False;
|
||
|
|
||
|
if FCommentBlock1 <> '' then
|
||
|
begin
|
||
|
s1 := Copy(FText, FPosition, Length(FCommentBlock11));
|
||
|
if s1 = FCommentBlock11 then
|
||
|
begin
|
||
|
Flag := True;
|
||
|
s2 := FCommentBlock12;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
if not Flag and (FCommentBlock2 <> '') then
|
||
|
begin
|
||
|
s1 := Copy(FText, FPosition, Length(FCommentBlock21));
|
||
|
if s1 = FCommentBlock21 then
|
||
|
begin
|
||
|
Flag := True;
|
||
|
s2 := FCommentBlock22;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
if Flag then
|
||
|
begin
|
||
|
Inc(FPosition, Length(s2));
|
||
|
while (FPosition <= FSize) and (Copy(FText, FPosition, Length(s2)) <> s2) do
|
||
|
Inc(FPosition);
|
||
|
Inc(FPosition, Length(s2));
|
||
|
SkipSpaces;
|
||
|
end;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
FLastPosition := FPosition;
|
||
|
end;
|
||
|
|
||
|
function TfsParser.Ident: String;
|
||
|
begin
|
||
|
if FSkipSpace then
|
||
|
SkipSpaces;
|
||
|
{$IFDEF Delphi12}
|
||
|
if (CharInSet(FText[FPosition], FIdentifierCharset - ['0'..'9']))
|
||
|
or ((FText[FPosition] >= Char($007F)) and (FText[FPosition] <= Char($FFFF))) then
|
||
|
begin
|
||
|
while CharInSet(FText[FPosition], FIdentifierCharset)
|
||
|
or ((FText[FPosition] >= Char($007F)) and (FText[FPosition] <= Char($FFFF))) do
|
||
|
{$ELSE}
|
||
|
if (FText[FPosition] in FIdentifierCharset) and not (FText[FPosition] in ['0'..'9']) then
|
||
|
begin
|
||
|
while (FText[FPosition] in FIdentifierCharset) do
|
||
|
{$ENDIF}
|
||
|
Inc(FPosition);
|
||
|
Result := Copy(FText, FLastPosition, FPosition - FLastPosition);
|
||
|
end
|
||
|
else
|
||
|
Result := '';
|
||
|
end;
|
||
|
|
||
|
function TfsParser.IsKeyWord(const s: String): Boolean;
|
||
|
var
|
||
|
i: Integer;
|
||
|
begin
|
||
|
if FCaseSensitive then
|
||
|
begin
|
||
|
Result := False;
|
||
|
for i := 0 to FKeywords.Count - 1 do
|
||
|
begin
|
||
|
Result := FKeywords[i] = s;
|
||
|
if Result then break;
|
||
|
end;
|
||
|
end
|
||
|
else
|
||
|
Result := FKeywords.IndexOf(s) <> -1;
|
||
|
end;
|
||
|
|
||
|
function TfsParser.GetIdent: String;
|
||
|
begin
|
||
|
Result := Ident;
|
||
|
if IsKeyWord(Result) then
|
||
|
Result := '';
|
||
|
end;
|
||
|
|
||
|
function TfsParser.GetWord: String;
|
||
|
begin
|
||
|
Result := Ident;
|
||
|
end;
|
||
|
|
||
|
function TfsParser.GetChar: String;
|
||
|
begin
|
||
|
{$IFDEF Delphi12}
|
||
|
if CharInSet(FText[FPosition], ['!', '@', '#', '$', '%', '^', '&', '|', '\',
|
||
|
'.', ',', ':', ';', '?', '''', '"', '~', '`', '_', '[', ']', '{', '}',
|
||
|
'(', ')', '+', '-', '*', '/', '=', '<', '>']) then
|
||
|
{$ELSE}
|
||
|
if FText[FPosition] in ['!', '@', '#', '$', '%', '^', '&', '|', '\',
|
||
|
'.', ',', ':', ';', '?', '''', '"', '~', '`', '_', '[', ']', '{', '}',
|
||
|
'(', ')', '+', '-', '*', '/', '=', '<', '>'] then
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
Result := FText[FPosition];
|
||
|
Inc(FPosition);
|
||
|
end
|
||
|
else
|
||
|
Result := '';
|
||
|
end;
|
||
|
|
||
|
function TfsParser.GetString: String;
|
||
|
var
|
||
|
Flag: Boolean;
|
||
|
Str: String;
|
||
|
FError: Boolean;
|
||
|
FCpp: Boolean;
|
||
|
|
||
|
function DoQuotedString: Boolean;
|
||
|
var
|
||
|
i, j: Integer;
|
||
|
begin
|
||
|
Result := False;
|
||
|
i := FPosition;
|
||
|
|
||
|
if FText[FPosition] = FStringQuotes[1] then
|
||
|
begin
|
||
|
repeat
|
||
|
Inc(FPosition);
|
||
|
|
||
|
if FCpp and (FText[FPosition] = '\') then
|
||
|
begin
|
||
|
{$IFNDEF FPC}
|
||
|
{$IFDEF Delphi12}
|
||
|
case Lowercase(Char(FText[FPosition + 1]))[1] of
|
||
|
{$ELSE}
|
||
|
case Lowercase(FText[FPosition + 1])[1] of
|
||
|
{$ENDIF}
|
||
|
{$ELSE}
|
||
|
case Lowercase(FText[FPosition + 1]) of
|
||
|
{$ENDIF}
|
||
|
'n':
|
||
|
begin
|
||
|
Str := Str + #10;
|
||
|
Inc(FPosition);
|
||
|
end;
|
||
|
'r':
|
||
|
begin
|
||
|
Str := Str + #13;
|
||
|
Inc(FPosition);
|
||
|
end;
|
||
|
'x':
|
||
|
begin
|
||
|
Inc(FPosition, 2);
|
||
|
j := FPosition;
|
||
|
Result := DoHexDigitSequence;
|
||
|
if Result then
|
||
|
Str := Str + Chr(StrToInt('$' + Copy(FText, j, FPosition - j))) else
|
||
|
FPosition := j;
|
||
|
Dec(FPosition);
|
||
|
end
|
||
|
else
|
||
|
begin
|
||
|
Str := Str + FText[FPosition + 1];
|
||
|
Inc(FPosition);
|
||
|
end;
|
||
|
end;
|
||
|
end
|
||
|
else if FText[FPosition] = FStringQuotes[1] then
|
||
|
begin
|
||
|
if not FCpp and (FText[FPosition + 1] = FStringQuotes[1]) then
|
||
|
begin
|
||
|
Str := Str + FStringQuotes[1];
|
||
|
Inc(FPosition);
|
||
|
end
|
||
|
else
|
||
|
break
|
||
|
end
|
||
|
else
|
||
|
Str := Str + FText[FPosition];
|
||
|
{$IFDEF Delphi12}
|
||
|
until CharInSet(FText[FPosition], [#0..#31] - [#9]);
|
||
|
{$ELSE}
|
||
|
until FText[FPosition] in [#0..#31] - [#9];
|
||
|
{$ENDIF}
|
||
|
if FText[FPosition] = FStringQuotes[1] then
|
||
|
begin
|
||
|
Inc(FPosition);
|
||
|
Result := True;
|
||
|
end
|
||
|
else
|
||
|
FPosition := i;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function DoControlString: Boolean;
|
||
|
var
|
||
|
i: Integer;
|
||
|
begin
|
||
|
Result := False;
|
||
|
i := FPosition;
|
||
|
|
||
|
if FText[FPosition] = '#' then
|
||
|
begin
|
||
|
Inc(FPosition);
|
||
|
Result := DoUnsignedInteger;
|
||
|
if Result then
|
||
|
Str := Chr(StrToInt(Copy(FText, i + 1, FPosition - i - 1))) else
|
||
|
FPosition := i;
|
||
|
end;
|
||
|
end;
|
||
|
{$HINTS OFF}
|
||
|
begin
|
||
|
Result := '';
|
||
|
if FSkipSpace then
|
||
|
SkipSpaces;
|
||
|
Flag := True;
|
||
|
FError := False;
|
||
|
FCpp := {FStringQuotes = '"'} FSpecStrChar;
|
||
|
|
||
|
repeat
|
||
|
Str := '';
|
||
|
if DoQuotedString or DoControlString then
|
||
|
Result := Result + Str
|
||
|
else
|
||
|
begin
|
||
|
FError := Flag;
|
||
|
break;
|
||
|
end;
|
||
|
|
||
|
Flag := False;
|
||
|
until False;
|
||
|
|
||
|
if not FError then
|
||
|
Result := '''' + Result + '''';
|
||
|
end;
|
||
|
{$HINTS ON}
|
||
|
function TfsParser.DoDigitSequence: Boolean;
|
||
|
begin
|
||
|
Result := False;
|
||
|
|
||
|
{$IFDEF Delphi12}
|
||
|
if CharInSet(FText[FPosition], ['0'..'9']) then
|
||
|
begin
|
||
|
while CharInSet(FText[FPosition], ['0'..'9']) do
|
||
|
{$ELSE}
|
||
|
if FText[FPosition] in ['0'..'9'] then
|
||
|
begin
|
||
|
while FText[FPosition] in ['0'..'9'] do
|
||
|
{$ENDIF}
|
||
|
Inc(FPosition);
|
||
|
Result := True;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TfsParser.DoHexDigitSequence: Boolean;
|
||
|
begin
|
||
|
Result := False;
|
||
|
|
||
|
{$IFDEF Delphi12}
|
||
|
if CharInSet(FText[FPosition], ['0'..'9', 'a'..'f', 'A'..'F']) then
|
||
|
begin
|
||
|
while CharInSet(FText[FPosition], ['0'..'9', 'a'..'f', 'A'..'F']) do
|
||
|
{$ELSE}
|
||
|
if FText[FPosition] in ['0'..'9', 'a'..'f', 'A'..'F'] then
|
||
|
begin
|
||
|
while FText[FPosition] in ['0'..'9', 'a'..'f', 'A'..'F'] do
|
||
|
{$ENDIF}
|
||
|
Inc(FPosition);
|
||
|
Result := True;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TfsParser.DoUnsignedInteger: Boolean;
|
||
|
var
|
||
|
Pos1: Integer;
|
||
|
s: String;
|
||
|
begin
|
||
|
Pos1 := FPosition;
|
||
|
|
||
|
s := Copy(FText, FPosition, Length(FHexSequence));
|
||
|
if s = FHexSequence then
|
||
|
begin
|
||
|
Inc(FPosition, Length(s));
|
||
|
Result := DoHexDigitSequence;
|
||
|
end
|
||
|
else
|
||
|
Result := DoDigitSequence;
|
||
|
|
||
|
if not Result then
|
||
|
FPosition := Pos1;
|
||
|
end;
|
||
|
|
||
|
function TfsParser.DoUnsignedReal: Boolean;
|
||
|
var
|
||
|
Pos1, Pos2: Integer;
|
||
|
begin
|
||
|
Pos1 := FPosition;
|
||
|
Result := DoUnsignedInteger;
|
||
|
|
||
|
if Result then
|
||
|
begin
|
||
|
if FText[FPosition] = '.' then
|
||
|
begin
|
||
|
Inc(FPosition);
|
||
|
Result := DoDigitSequence;
|
||
|
end;
|
||
|
|
||
|
if Result then
|
||
|
begin
|
||
|
Pos2 := FPosition;
|
||
|
if not DoScaleFactor then
|
||
|
FPosition := Pos2;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
if not Result then
|
||
|
FPosition := Pos1;
|
||
|
end;
|
||
|
|
||
|
function TfsParser.DoScaleFactor: Boolean;
|
||
|
begin
|
||
|
Result := False;
|
||
|
{$IFDEF Delphi12}
|
||
|
if CharInSet(FText[FPosition], ['e', 'E']) then
|
||
|
{$ELSE}
|
||
|
if FText[FPosition] in ['e', 'E'] then
|
||
|
{$ENDIF}
|
||
|
begin
|
||
|
Inc(FPosition);
|
||
|
{$IFDEF Delphi12}
|
||
|
if CharInSet(FText[FPosition], ['+', '-']) then
|
||
|
{$ELSE}
|
||
|
if FText[FPosition] in ['+', '-'] then
|
||
|
{$ENDIF}
|
||
|
Inc(FPosition);
|
||
|
Result := DoDigitSequence;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TfsParser.GetNumber: String;
|
||
|
var
|
||
|
Pos1: Integer;
|
||
|
begin
|
||
|
Result := '';
|
||
|
if FSkipSpace then
|
||
|
SkipSpaces;
|
||
|
Pos1 := FPosition;
|
||
|
|
||
|
if DoUnsignedReal or DoUnsignedInteger then
|
||
|
Result := Copy(FText, FLastPosition, FPosition - FLastPosition) else
|
||
|
FPosition := Pos1;
|
||
|
|
||
|
if FHexSequence <> '$' then
|
||
|
while Pos(FHexSequence, Result) <> 0 do
|
||
|
begin
|
||
|
Pos1 := Pos(FHexSequence, Result);
|
||
|
Delete(Result, Pos1, Length(FHexSequence));
|
||
|
Insert('$', Result, Pos1);
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
function TfsParser.GetFRString: String;
|
||
|
var
|
||
|
i, c: Integer;
|
||
|
fl1, fl2: Boolean;
|
||
|
begin
|
||
|
Result := '';
|
||
|
i := FPosition;
|
||
|
fl1 := True;
|
||
|
fl2 := True;
|
||
|
c := 1;
|
||
|
|
||
|
Dec(FPosition);
|
||
|
repeat
|
||
|
Inc(FPosition);
|
||
|
{ if FText[FPosition] in [#10, #13] then
|
||
|
begin
|
||
|
FPosition := i;
|
||
|
break;
|
||
|
end;}
|
||
|
if fl1 and fl2 then
|
||
|
{$IFDEF Delphi12}
|
||
|
if CharInSet(FText[FPosition], ['<', '[']) then
|
||
|
{$ELSE}
|
||
|
if FText[FPosition] in ['<', '['] then
|
||
|
{$ENDIF}
|
||
|
Inc(c)
|
||
|
{$IFDEF Delphi12}
|
||
|
else if CharInSet(FText[FPosition], ['>', ']']) then
|
||
|
{$ELSE}
|
||
|
else if FText[FPosition] in ['>', ']'] then
|
||
|
{$ENDIF}
|
||
|
Dec(c);
|
||
|
if fl1 then
|
||
|
if FText[FPosition] = '"' then
|
||
|
fl2 := not fl2;
|
||
|
if fl2 then
|
||
|
if FText[FPosition] = '''' then
|
||
|
fl1 := not fl1;
|
||
|
until (c = 0) or (FPosition >= Length(FText));
|
||
|
|
||
|
Result := Copy(FText, i, FPosition - i);
|
||
|
end;
|
||
|
|
||
|
function TfsParser.GetXYPosition: String;
|
||
|
var
|
||
|
i, i0, i1, c, pos, X, Y: Integer;
|
||
|
begin
|
||
|
i0 := 0;
|
||
|
i1 := FYList.Count - 1;
|
||
|
|
||
|
while i0 <= i1 do
|
||
|
begin
|
||
|
i := (i0 + i1) div 2;
|
||
|
pos := Integer(FYList[i]);
|
||
|
|
||
|
if pos = FPosition then
|
||
|
c := 0
|
||
|
else if pos > FPosition then
|
||
|
c := 1
|
||
|
else
|
||
|
c := -1;
|
||
|
|
||
|
if c < 0 then
|
||
|
i0 := i + 1
|
||
|
else
|
||
|
begin
|
||
|
i1 := i - 1;
|
||
|
if c = 0 then
|
||
|
i0 := i;
|
||
|
end;
|
||
|
end;
|
||
|
|
||
|
X := 1;
|
||
|
Y := i0;
|
||
|
i := Integer(FYList[i0 - 1]) + 1;
|
||
|
|
||
|
while i < FPosition do
|
||
|
begin
|
||
|
Inc(i);
|
||
|
Inc(X);
|
||
|
end;
|
||
|
Result := IntToStr(Y) + ':' + IntToStr(X)
|
||
|
end;
|
||
|
|
||
|
function TfsParser.GetPlainPosition(pt: TPoint): Integer;
|
||
|
var
|
||
|
i: Integer;
|
||
|
begin
|
||
|
Result := -1;
|
||
|
i := pt.Y - 1;
|
||
|
if (i >= 0) and (i < FYList.Count) then
|
||
|
Result := Integer(FYList[i]) + pt.X;
|
||
|
end;
|
||
|
|
||
|
end.
|